{"_id":"hyperapp","_rev":"147-45ed030842ea29147faa949d29117792","name":"hyperapp","dist-tags":{"latest":"2.0.22","alpha":"2.0.0-alpha.10","beta":"2.0.0-beta.25"},"versions":{"0.0.0":{"name":"hyperapp","version":"0.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"author":"","license":"ISC","_id":"hyperapp@0.0.0","_shasum":"f3270e7e6239b1d2523e2cd570ecfafc53391960","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"f3270e7e6239b1d2523e2cd570ecfafc53391960","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.0.tgz","integrity":"sha512-h+U748qjssHGzH+T5oAXzjFzxPIdCa0g/pLSgItTmPjd09NIamkhDjLitgoXO4lNaKBtL6zFXIIvP/1vSEMnAg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHkPpLXXhxMwGVWxB6HaWYCPnmrr+CWaiV5x+M7F6w25AiAbXRlMRJPERi58ASrDVCjR5Gtl/weup7azTwyBBNepFg=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.0.tgz_1483613596230_0.734972219215706"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.1":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building UI applications","version":"0.0.1","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","virtual-dom"],"scripts":{"build":"browserify app.js -s app -g uglifyify | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify | uglifyjs > dist/html.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i1500 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"2ccaff81a68df3bb3cf345d99d8d56235dab2e89","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.1","_shasum":"bace4665c02cc4e47150a324d791e4acd58959dc","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"bace4665c02cc4e47150a324d791e4acd58959dc","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.1.tgz","integrity":"sha512-6vaiC6VygAPGVFUQQA/64wFmtZuyCp8/ESPefvBymSdSjOpGY06YH0pudtaTEDASH7j47z4owdY8nEDkCn2yQw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLYP9MgBXMVM8+GhmZozCYE6ymYTP7yEiN+lA4W4bSrAIgYaTgk7ojt9m2NIk6jdEMQWCQzalUij0ihENrwBDjC7A="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.1.tgz_1484890930431_0.3140470813959837"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.2":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building UI applications","version":"0.0.2","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","virtual-dom"],"scripts":{"build":"browserify app.js -s app -g uglifyify | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify | uglifyjs > dist/html.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i1500 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"6c467ae955352adc4e22dd8bbc3eed46a1e1d62b","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.2","_shasum":"3129ae2146a74769b0089c4816d10f1bbcc3faf9","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"3129ae2146a74769b0089c4816d10f1bbcc3faf9","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.2.tgz","integrity":"sha512-snxcABNkTD+WnUtme+276DFpu/Xd6ibX96ks0p7n95tFvC9YdL7EeysWJsAVGKqbVXZmQTN2uBxXMNm40R26vw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDTKmIAAw1CeGD6N2GfpVwrhY8EUU+RXBefHAFX8blR8AiEArvZahawDRZm0rh3RlspxJj18Hl0YGMJUNqq+dtqFu38="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.2.tgz_1485096972671_0.798669453477487"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.3":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building UI applications","version":"0.0.3","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","virtual-dom","vdom","template string"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"9a6a0c02c56b13294d47266b1c6399ae259c8812","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.3","_shasum":"6dc07d73a78e6499df4c5f4b84b2ed52554e2306","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"6dc07d73a78e6499df4c5f4b84b2ed52554e2306","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.3.tgz","integrity":"sha512-UWtUav04nq7vu1kE3julWpsZ+iKs+alZb5xYXomN558y0chmH88k2me7Mq5ud6/9qSuMhHoCtWDXjNARooeGpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFh/0SZf2455pcMkESKfrHPDJUT5Cvx7mYeNlI8JVqvzAiAfgI4LLBGq0UlILErQftFeb+isgHMyS+oW0DuaEJ3fwA=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.3.tgz_1485103159289_0.5605358134489506"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.4":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.4","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","virtual-dom","vdom","template string"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"2ebb9ce05186d9cba24b9eca97cbc4fd716e1e68","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.4","_shasum":"a0352804980ed56ce8301727ceeafbe0a117758e","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"a0352804980ed56ce8301727ceeafbe0a117758e","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.4.tgz","integrity":"sha512-TzHnR9aAb1+b+OGx/8adDi7ENR/ftA6bEyxc1NXOyggz0+N1LfVvgYfwBojm4VbdxwBIFd7LWs3Z82eM9Pqh/g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0uyU4uhIH1DMjqIDi9/7lXxK6D+k9M+r5OCqfaVDSVwIgTfqDWWgh7yDJ4J4PdXuHJvv03I7m4gTT17JzLw1sM0Y="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.4.tgz_1485790968203_0.2732128859497607"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.5":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.5","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","virtual-dom","vdom","template string"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"1f80fbedf97576b3bb3259b2abe1a519ae44f53f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.5","_shasum":"81ff6e608ef85de0104eaf6b4f0002d37949c24d","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"81ff6e608ef85de0104eaf6b4f0002d37949c24d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.5.tgz","integrity":"sha512-bJILBy87Ynrs6G3WL96iOdl5wkbSakVlxNrCTTvmd53lK3MM4jW95B/yIVRhG8KvEAMQB7JInBXemL1uzHtGbQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBSbxstUlxrwjFhC3thZ9AKe93GUZr0Cn2DQtzPJtFgwIhANjFoPlvmLqLb+8QxHIErqCN7+0yIVwtob/RkBf6+3Am"}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.5.tgz_1485917193986_0.9009661788586527"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.6":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.6","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","virtual-dom","vdom","template string"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"302e3c98c769d86f318b98c95a01031adaf2e0f9","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.6","_shasum":"7d08bd2d70a403aadb92d9ce3e14387c61b8aea4","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"7d08bd2d70a403aadb92d9ce3e14387c61b8aea4","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.6.tgz","integrity":"sha512-6MRGsKu+L+JP1nP1J6G/O/dGr7Wr3KA5k30nsP+qg9rUSumuvljATkNxEBlpyPVbCo+S3mezQc5Vnuni3au5eA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTcMggYIcN91Xx0p7uox0DwrDnASpE1Drj1uw6wGe+xwIgRwgfoehiHNR2egomJFl32rknKE1ByoeA9n7fINZVrOo="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.6.tgz_1486005877746_0.1429450479336083"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.7":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.7","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","functional","virtual-dom","vdom","template string","hyperscript","vanilla"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js && browserify h.js -s h -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/h.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"28c2f3fbceb2779c1567b51a09d9693ae9eb2b78","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.7","_shasum":"8b50d3e55b5b3f71beb89e412f85ce7a07de3b43","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"8b50d3e55b5b3f71beb89e412f85ce7a07de3b43","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.7.tgz","integrity":"sha512-MkVNuF9327UQLFG30vDmzL0SwpmiP5FdBfQquNT4QnHLaclvU7+PEo3aGVUWgxBgmO5Fe2WlTXzstiy8C5byOA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF4jjPfLq5/+Zw/mPpSyWxTtxmqZ2OdC5trQTY5AblaQAiBouRWNdIHz85ObilmRyTfgqp5VFpbADipdTh0trGS3Xw=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.7.tgz_1486116478364_0.5366007548291236"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.8":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.8","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","functional","virtual-dom","vdom","template string","hyperscript","vanilla"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js && browserify h.js -s h -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/h.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"fde3aa097895e331ff8465d7d5ae0dfbaf9a814f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.8","_shasum":"4dbe8ea52e3f291f368abad11df6efbba7efb105","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"4dbe8ea52e3f291f368abad11df6efbba7efb105","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.8.tgz","integrity":"sha512-CSLOLnvf7pQ9StZvzyf4SrLKf1i5MEbkGll/TIla0T4/xh9wFRF5I2sBVFm7IchbWhe3B4ak+xjk4fT2xVvBhA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEMCHz5aEVv62DrN6e1TEVtIZk7B3Rx+IP/xydSmuIdT+LcCIGwXjd3rTCBBK2aY94z5QSd7TXS2nhNUXpmZ3pz3NFkI"}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.8.tgz_1486189270812_0.9663328959140927"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.9":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.9","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","functional","virtual-dom","vdom","template string","hyperscript","vanilla"],"scripts":{"build":"browserify app.js -s app -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/app.min.js && browserify html.js -s html -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/html.min.js && browserify h.js -s h -g uglifyify -p bundle-collapser/plugin | uglifyjs > dist/h.min.js","gzip":"gzip -c dist/app.min.js > dist/app.min.js.gz","zopfli":"zopfli dist/app.min.js -c --i2000 > dist/app.min.js.gz"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"browserify":"^13.1.1","bundle-collapser":"^1.2.1","uglifyify":"^3.0.4","uglifyjs":"^2.4.10"},"gitHead":"0f7bc3b195b662a01f0c3ed122ed9354118a7e1f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.9","_shasum":"06d2cbef979ec2f179753d9ea1a289f41786d6e0","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"06d2cbef979ec2f179753d9ea1a289f41786d6e0","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.9.tgz","integrity":"sha512-PBXaN6jcWGtkZhAAmEIDKtQe3E9NYsDp0dWCp8AbGRpBrH8DTXp8zovtBIW3wSK1x/AxC6ozyFwHUr9fzMIqwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFwhNyDuER4/oEHyYzCqII9QIYAAnYLzItct6zzU652kAiBjq5n99fJk5bK5ELnBWDlaKUc5yFjbLY4eyUNHSUUQrQ=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.9.tgz_1486222311597_0.30906709004193544"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.10":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.10","main":"src/index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","functional","virtual-dom","vdom","template string","hyperscript","vanilla"],"scripts":{"build":"cross-env NODE_ENV=production webpack --progress","test":"cross-env NODE_ENV=tests jest --coverage --colors --cache"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"babel-core":"^6.22.1","babel-loader":"^6.2.10","babel-preset-babili":"^0.0.10","babel-preset-es2015":"^6.22.0","compression-webpack-plugin":"^0.3.2","cross-env":"^3.1.4","jest":"^18.1.0","webpack":"^2.2.1","wrapper-webpack-plugin":"^0.1.11"},"jest":{"verbose":true},"gitHead":"bb40dd4fc7c8cbe5d3eb27530bfd84117c87ff5f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.10","_shasum":"6d144ce47cb0a2fb8704d1d02832f6e73ac23329","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"6d144ce47cb0a2fb8704d1d02832f6e73ac23329","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.10.tgz","integrity":"sha512-GGXLfxjpB2A4RTrz2GjR2p5NhikKYKRY29CkmWKuaxM7maOSOggDvZL7cIBZwXsCw+qVcoLDZC2ENkLKMuEwYg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJm86s0ys8sP4nYFna3R4H24524EXjjZQqlggm5M16VQIgAbT7IoDxbhPO32BPa4dIKc2RSCg4l7MJLCVOnA5cjzM="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.10.tgz_1486395879908_0.2505820654332638"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.11":{"name":"hyperapp","description":"HyperApp is a 1kb functional JavaScript library for building modern UI applications","version":"0.0.11","main":"src/index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","functional","virtual-dom","vdom","template string","hyperscript","vanilla"],"scripts":{"build":"cross-env NODE_ENV=production webpack --progress","test":"cross-env NODE_ENV=tests jest --coverage --colors --cache"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"babel-core":"^6.22.1","babel-loader":"^6.2.10","babel-preset-babili":"^0.0.10","babel-preset-es2015":"^6.22.0","compression-webpack-plugin":"^0.3.2","cross-env":"^3.1.4","jest":"^18.1.0","webpack":"^2.2.1","wrapper-webpack-plugin":"^0.1.11"},"jest":{"verbose":true},"gitHead":"904c66a14b18e33d274263075a6492c3847c8d96","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.11","_shasum":"2bcf81f609614d31097440c43b2b4a39d382e096","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"2bcf81f609614d31097440c43b2b4a39d382e096","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.11.tgz","integrity":"sha512-QiirfKssAanYE++n8HlrxtW4i5twy92GmLpm8ESouquZYy2+eHEaZSRwNyfb27xHIJvZ+brOlEMKSNPcwAIK/A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBFtD9vO3qoovE/dhBj4ix96/SN4+pDSj/kOFQpXp0TQIhAOAfZ3u9t7f10sNX+pQlplritDwleUb+DTmrCGp+L/Ag"}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.11.tgz_1486399714446_0.4114930871874094"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.12":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.0.12","main":"index.js","author":{"name":"Jorge Bucaran"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"keywords":["hyperx","hypertext","functional","virtual-dom","template string","hyperscript","vanilla"],"scripts":{"t":"jest --coverage --colors --cache","b":"npm run b:all > /dev/null","b:all":"npm run b:hyperapp && npm run b:hyperapp:hx","b:hyperapp":"rollup -n hyperapp -cmf umd -o dist/hyperapp.js -- index.js","b:hyperapp:hx":"rollup -n hyperapp -cmf umd -o dist/hyperapp.hx.js -- hx.js"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rollup-plugin-uglify":"^1.0.1"},"jest":{"verbose":true},"gitHead":"2c41aa48032fb29ce249af691242d8d596fb6dc6","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.12","_shasum":"937f1d5f15ce75ad50254b2760a554af5d9da3bb","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"937f1d5f15ce75ad50254b2760a554af5d9da3bb","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.12.tgz","integrity":"sha512-ZXymzcH5frOBMJZDvG3V7TcFodm8dYGigxKGq8gBPbPYBvMG1EBUfK031KvolirxXT/pxWZIVEQ3lBoMZoVZdw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFMkWYBSzlrZhDf1eu5XbfUimEm6Qeg7lKImelS/YHPvAiEAy29wBCBtv3/QLdL+LhqwDjbTwrI22w3gFVGgOi1rido="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.12.tgz_1486490163720_0.15126425633206964"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.13":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.0.13","main":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hypertext","functional","virtual-dom","template string","hyperscript","vanilla"],"scripts":{"test":"jest --coverage --colors --cache","build":"npm run b:hyperapp > /dev/null && npm run b:hyperapp.hx > /dev/null","b:hyperapp":"rollup -n hyperapp -cmf umd -i src/hyperapp.js -o dist/hyperapp.js","b:hyperapp.hx":"rollup -n hyperapp -cmf umd -i src/index.js -o dist/hyperapp.hx.js"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rollup-plugin-uglify":"^1.0.1"},"jest":{"verbose":true},"gitHead":"31cbf595a8fe8a985d467766327659ea63471259","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.13","_shasum":"ef4b64903e1bd0c226ceca69fa877763852a0ac5","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"ef4b64903e1bd0c226ceca69fa877763852a0ac5","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.13.tgz","integrity":"sha512-+keMkdDPJm9ke0xfMHb9/6NeBaoS0S1ieUmnRHoNmB8ZkG9Trh+uVwWo8yhkQTyzb6Xf4rvUGuLBVxR4W71nCA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCelxtkBGCrPU0oCnp54BvrOU/gmF0A9/k3v6z7cOLzyQIgZZDpo7cS/riX0DoTQK0IfWNnnqoh3QEb9Fb3D3ZvOz0="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.13.tgz_1486644204619_0.9813543637283146"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.0.14":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.0.14","main":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hypertext","functional","virtual-dom","template string","hyperscript","vanilla"],"scripts":{"test":"jest --coverage --colors --cache","build":"rollup -n hyperapp -cmf umd -i src/index.js -o dist/hyperapp.js > /dev/null"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rollup-plugin-uglify":"^1.0.1"},"jest":{"verbose":true},"gitHead":"09c661466a1f9adc077bb55a83053b1326ce26d3","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.0.14","_shasum":"c3aa5168ede19bae71ed4a0946ea407b2c770913","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"c3aa5168ede19bae71ed4a0946ea407b2c770913","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.0.14.tgz","integrity":"sha512-+rtdVp8M5ETOro6kk2BoBjWn3B5dOQunGTZQc0WQ6ExVUy8iItTjIfpKqsoRHpcfrj0uFGkK6sUE4ZJ7PrbyPQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMyMWUUlsSsI5OUjgLEfXt5pzhfdvx0ykr4WFkGmLWPAiBRco/wZhstBeO2uDe4upNtBLQKSRADrfBn2L5wnBOsXQ=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.0.14.tgz_1486845392885_0.6859956388361752"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.1.0":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.1.0","main":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hypertext","functional","virtual-dom","template string","hyperscript","vanilla"],"scripts":{"test":"jest --coverage --colors --cache","build":"rollup -n hyperapp -cmf umd -i src/index.js -o dist/hyperapp.js"},"dependencies":{"hyperx":"^2.0.5"},"devDependencies":{"jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rollup-plugin-uglify":"^1.0.1"},"jest":{"verbose":true},"gitHead":"f30a91cd5123dacfa9d4c50283b91de2a3469e9b","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.1.0","_shasum":"390b2f1495dd7060bee75060f4084d4d586820f8","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"390b2f1495dd7060bee75060f4084d4d586820f8","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.1.0.tgz","integrity":"sha512-LsKVY0S+B1OV3Wi6vfKxMPCASvnFWEOfrAA6bWzHJQdMEpuEfkN1HtavRWowa03UyPcNQiISZDgsMQ98m5ZFpg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBJaWBj97aT2rB8PPvwRT3sMJlNEV3lj+Cm/If2uvA0YAiAULOwGKsDNlsdQTod3sUXGzKTvX9hIHhJdLJDxpNgZoA=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.1.0.tgz_1486899086582_0.9817130933515728"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.2.0":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.2.0","main":"src/index.js","browser":"dist/hyperapp.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hypertext","functional","virtual-dom","template string","hyperscript","vanilla"],"scripts":{"test":"jest --coverage --colors --cache","build":"rollup -n hyperapp -cmf iife -i src/index.js -o dist/hyperapp.js"},"dependencies":{},"devDependencies":{"hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rollup-plugin-uglify":"^1.0.1"},"jest":{"verbose":true},"gitHead":"12de0a4dc71095fd1107a6051edf10fa52497e2f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.2.0","_shasum":"9cf7e702d07d746aabe3f5562a61be9d419292da","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"9cf7e702d07d746aabe3f5562a61be9d419292da","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.2.0.tgz","integrity":"sha512-WNHCewVJW69IuqVAvA2x3ZA+LhBBpIBCdHp52SKSCeRNN2mZq8Da2ZEe2Yyxh/RVxCo+I1yDxDBMI+e5EeGSnQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAN7DhzNTQmKr8BBE1i2iO+wfW79GJVgFDUjEtWJrWacAiEA7DT5OrThrd5b0m9SyjjxzuzEaMR0kQBrTh42QZxJsxY="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.2.0.tgz_1486928466461_0.7662609575781971"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.2.1":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.2.1","main":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hypertext","functional","virtual-dom","template string","hyperscript","vanilla"],"scripts":{"test":"jest --coverage --colors --cache","build":"rollup -n hyperapp -cmf iife -i src/index.js -o dist/hyperapp.js"},"dependencies":{},"devDependencies":{"hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-commonjs":"^7.0.0","rollup-plugin-node-resolve":"^2.0.0","rollup-plugin-uglify":"^1.0.1"},"jest":{"verbose":true},"gitHead":"4bd9f666c7534f414b6363eb8dd01feb4f56b0bd","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.2.1","_shasum":"40632db7787dbeafac26e70f9971262166454aa6","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"40632db7787dbeafac26e70f9971262166454aa6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.2.1.tgz","integrity":"sha512-fZkBzlvyvLtwTKp6WdHdq1js8muBqO5zLYtpF8/JpKX7RVqQa5I0vOvPOIKK0HZk74pyI2/HDqAoUGTRyu8rqw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG0NnHS5CMq5hkHWJVLsFIboPx578mLUX3Okxo2mozrZAiEAs57eB7OKtPKtLo2EVOsxLvKmlt1MydWBK7bT3YZugEU="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.2.1.tgz_1486931152365_0.7972302755806595"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.3.0":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.3.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"f554f92a05ef77486e49d6fc4579c6af9e6518f3","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.3.0","_shasum":"687cf9d305598491e5c52c111a9308d574c0e140","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"687cf9d305598491e5c52c111a9308d574c0e140","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.3.0.tgz","integrity":"sha512-wEevbKayNl7tpM5d0zqseAHtO2x0y29xlFzO6wqmRrbtRYW1to3/EFFQ4iSLvmJz0oRRBB4QHrLqvwC+YMxhuA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7EgU1IQr0ZN29Gsauky/xWSi9El24qAq3wvSMzp69SAiEA1jWKCDhnJcvSR4J8UAYASK8fnD5fKK+ij4JHvK+shn0="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.3.0.tgz_1487108101145_0.5867830580100417"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.3.1":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.3.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"1e83a145dbd7ac88b48c525d148ca1b4ab45a056","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.3.1","_shasum":"43c52f5a286ed098b62f1e914eefa53bcff6b17d","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"43c52f5a286ed098b62f1e914eefa53bcff6b17d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.3.1.tgz","integrity":"sha512-pY0mypeG07mn8CQHDICni+QZKu3hO4lu47IUYvaN8Gwf/hMwFoJrJZpxYHDis1sagG41/GCs0dfztkZkS3MSYQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC9R6l/ATlFU6MvTO3uLJaKTtxi3V5F8sp3ZEwVRDCr/AiEA0QYEr8t4sljUg+4IrWnQ7dePP7KveRBbSpacjPTg99M="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.3.1.tgz_1487108486788_0.03699988266453147"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.3.2":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.3.2","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"e028764f8aaa9279ade5eeed7549c8bfad5a872d","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.3.2","_shasum":"157e564049908af7002a052837a1ef9db28651a0","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"157e564049908af7002a052837a1ef9db28651a0","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.3.2.tgz","integrity":"sha512-pa6m7NOztQRaFn2OQrXXFOOpYHgl9x9v1jZRQqeVtsEdYEtJ1AMvFFB2vG1NuG0z/VO+4s8Nz2BIhIcuyQr1EA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHsMskWM7yLB6yrF4hWE/tK4WMGeEZ0MM+Y48hoiPZjwAiEAsTNG7/i/D2KXULycDCHYgBSr4uwPWSdIvO8eE3MR+g4="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.3.2.tgz_1487109612000_0.004878680920228362"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.4.0":{"name":"hyperapp","description":"1kb JavaScript library for building modern UI applications","version":"0.4.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"2bdd99ef9502b3cc83947e0f16c7bb5abd52fe45","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.4.0","_shasum":"997d53871016350ce5f054ffd50878c3d86add22","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"997d53871016350ce5f054ffd50878c3d86add22","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.4.0.tgz","integrity":"sha512-UiB/IsVUWO45tUBhTcz+/kvvySvYkTSgIUKe1SSDyzat9vEo90b1+loJIP2TE1a5o3+Vf+cjEAOh14nTEV9oeQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF+MTMwSVtrU4jwkmUhN2piBZQs054bDNUnaxcwdbH7bAiB7NTWLbRDey64qR8bBLbPO01tq9NnMorSn2sIBf8FGvg=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.4.0.tgz_1487116424526_0.402504006633535"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.4.1":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.4.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"f9bc9653ff0bf87e152945c6c858866a0c7ed9e8","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.4.1","_shasum":"6e7477c136356da1a0949b84e613cbba94631400","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"6e7477c136356da1a0949b84e613cbba94631400","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.4.1.tgz","integrity":"sha512-ie/cwX04iwjW5xtZxgduhxkGAXSwgQKUJEFoyxumR8EnpLCQDaWcX9j0XDiLyvcONu3l9r1ckyQAS62hoXlMkw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC45VXHOtY4MdJcw4oXuYS+tCZO9JJDHfNAqJFq0gyx6QIgY8lRQfAF93sgcP7wA0gZiwqMoaZ/sR71OgZQHWnfNh4="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.4.1.tgz_1487331380758_0.9789016377180815"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.4.2":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.4.2","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"488bf39442f1248355ca06c40e3be510d2fd8351","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.4.2","_shasum":"2e6b49721a57ef766b836bed76fb774f3c766a29","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"2e6b49721a57ef766b836bed76fb774f3c766a29","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.4.2.tgz","integrity":"sha512-8DFhKnC9absksC0EubOw8iKsw5yS5utjnZKKI6Pb7dAHtvOi1N0JXm1xPCjXXJZgSc/D7nkwJ72tCE3cvNxzjw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCB3G9QTAenYi4Hk0k9iQz7KGPFylTAiNddNzSnRKLTvQIgZAVkGp5v5z77pRXFJVFTKbKLLiMA/WK1AZuQck3v9HA="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.4.2.tgz_1487398396311_0.4938671456184238"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.5.0":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.5.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"e47017ae2e238fce675b3aad29fb9c24affe1329","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.5.0","_shasum":"3c80c499382edadbd7900fc012a63e15364cafd4","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"3c80c499382edadbd7900fc012a63e15364cafd4","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.5.0.tgz","integrity":"sha512-dJwNHYgPTNVzQHzEw39Ay2pkdkHaTVSLf0B0hrq6ImLP4wVnq1ggnVbRYU8KBLEoKV3ku8NBWz1wSG7b2zWMcA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEyu7TbdTabr7a5fUoCrbhF8Ev6mG+VmUXBEMMdZRFmZAiBi4DlK3gLSgq26CzfSv5hphkFTaORdX/FtcbsgGLkIhw=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.5.0.tgz_1487682957221_0.27698421222157776"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.6.0":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.6.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^18.1.0","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"fc3a85d8cbe4af38b9f1002b6664ec526c96f893","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.6.0","_shasum":"c99a9ee9ace0893467bcaae7d7682708814996a9","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"c99a9ee9ace0893467bcaae7d7682708814996a9","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.6.0.tgz","integrity":"sha512-pnWoGrgwSImAEwKwbCdzOpdURsYXp/d3/s5rQzLaeINfno31DweA6u6GUqtkHJ43FvV+FLZayFUZ3EtHFgWDmQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBq+M/tOekBpRgnBvUjS9rfn1xWT51S4YSIb2jXn+gYlAiEA+CLQvj95wzIY7tKPCfM92oLqUC4m1lK3xW+c/ARDzw4="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.6.0.tgz_1488223015351_0.17176259844563901"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.7.0":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.7.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^19.0.2","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"6122b1ec7e3e44c82cd4a385b4cd457bec1d2b81","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.7.0","_shasum":"eaaf281d1afa09d716080c0fca46389bf1ebc6f2","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"eaaf281d1afa09d716080c0fca46389bf1ebc6f2","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.7.0.tgz","integrity":"sha512-m2nNcDtrF6QWJuBkKzLTQ8+V/ec+dY8mSplUQUfpmldcKT4NpoIwVIOMinM7jA90BTvehgFgEXhcLm1HVhXIPQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7Y+BmdBISzxWNbeutJJYGaGTVl3GilE2iLJsGfuFzFAiEAlv/IxVA0PB5uGc9K2F0lNCg3ustm7LSUCStvh5/DLwo="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.7.0.tgz_1488780974014_0.23842385387979448"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.7.1":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.7.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","hyperx":"^2.0.5","jest":"^19.0.2","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"5008ba6a197360a5b0f62fc04a7213d801913569","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.7.1","_shasum":"932acc82c132c4998908562e6b04a325b65321a9","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"932acc82c132c4998908562e6b04a325b65321a9","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.7.1.tgz","integrity":"sha512-8q33UBl0jpcGIOLnlfjmbsz4b4AU3OhUDdnQ+GHoNQsfjF3tjBrVcPsCwDRr+35H36MlG1awtsd7iZWDZUtVQA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxzq0BabtKkjqFj7BkbNVbbehn5o0sZdmpuigDRt3u6QIgJ1yveFtjIzaI3vIAUPB77EnMQCVk9aM2CUEZqMQlQ0w="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.7.1.tgz_1488827516984_0.12855307920835912"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.8.0":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.8.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","jest":"^19.0.2","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"05f93515aed3e78fe9603e788f975fcf21dc0e42","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.8.0","_shasum":"1dc6cce8adfbe8cfe96a955b1fa71f62c123a1f2","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"1dc6cce8adfbe8cfe96a955b1fa71f62c123a1f2","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.8.0.tgz","integrity":"sha512-0DkvaatydC3VVySEHjVJFXNfvo3pAK1ApxJNWYF2JSvl1CbLO81dfNk1pVS2u5Dgunh+ZKpj29LH11gW/KG6yA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGqYkOoKnOQLwTaxZ8wxmjQlFH+OcE1nIsTOY5lkbbL1AiBdP+6xnr9bfknz3bWdHideCPc3w4/r/q/r1aqTiw+woA=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.8.0.tgz_1492069537666_0.689708041260019"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.8.1":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.8.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","jest":"^19.0.2","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"d36aff5c75e8827b414a4dcbd0baee62d9b2853d","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.8.1","_shasum":"21e13246deb148d213a52cbbfdbebcb2038fb482","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"21e13246deb148d213a52cbbfdbebcb2038fb482","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.8.1.tgz","integrity":"sha512-mmt1lL604WCmk3IZ3Vl5YlO5YBNguYtmNg+MdlReekSAyrxn3ohXVvZ7P1C2sq7aoh+wL4apYEQdFbDPVUAbtg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCQItqSV6dv0DgBcJFORx/mJZF6ztF5CUv8lo9MsFjWiAIgcfSLT/n5JSUEz9iyaw3tSqikV+ALit8Zh+f9FC079+M="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.8.1.tgz_1492073382386_0.8736709787044674"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.9.0":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.9.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","jest":"^19.0.2","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"b4fa8aceceda7138aef6c8c27e27fef11d6717f7","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.9.0","_shasum":"fd277932c55af9c72cfe106f414220a66a8203b5","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"fd277932c55af9c72cfe106f414220a66a8203b5","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.9.0.tgz","integrity":"sha512-XQUiX2UOPjkeY30v/K56yQcKuOEW9fUur76/R3hVkN4ynrXZ+6PFPDl6BSNIDWtFSJbQt7HWSFzcsrnGNysJnw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZV/jIMe2l3k4QeVBLnr+7l0e35AXtqYoBGrHsFCO+MQIhAL7G5S10/xFzvwVzrKEqxvk2k/+ySZIZ7EWwmWlL7l1H"}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/hyperapp-0.9.0.tgz_1493543193830_0.9798755587544292"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.9.1":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.9.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.22.0","jest":"^19.0.2","prettier":"~1.2.2","rollup":"^0.41.4","rollup-plugin-uglify":"^1.0.1"},"gitHead":"ef14a8af8e63b82fb93375529bce03170c8229c4","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.9.1","_shasum":"bb8fa50dbed88ca9737f0f873bfb6d751e8ced95","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"bb8fa50dbed88ca9737f0f873bfb6d751e8ced95","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.9.1.tgz","integrity":"sha512-XnIQ4i0TV+ThBMyOLrv64GUp16YbJLC9wr4ymoHHae8pfibIJIOvIDv8ET45B2wBn7iM14hHvojKX3FXKCBqvA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXr/sURPqArTc87y4lJhuzZDIZAj7PIjQSLwmTo1NNVwIgQpX/UQHyb+JVSE9Wsh3PccyivaEvmvbHI+cQxWF6Kc4="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/hyperapp-0.9.1.tgz_1494353097922_0.7837697111535817"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.9.2":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.9.2","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","jest":"^20.0.4","prettier":"~1.4.1","rollup":"^0.41.6","rollup-plugin-uglify":"^2.0.1"},"gitHead":"186395f26c8c9b5eef08910b246f12a618d18cbf","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.9.2","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-qmziB1HM13G/kEAZX7FX4osSciy2NLEIktVogYRY+ZPTU0UhvkbALi55pnF0oCWRJDyRR8loqOqZk3bjcItAww==","shasum":"9392b07318baa188a97a723f674f4dea874b9c53","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.9.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD3e7Wk/2inSvYc3DQQHffhY9800iGdEUFZaXYQCxLalwIhAMMtr4GiW5gUy/q7n7VVpxsKzlBpapbnTHlKCv/Dms3j"}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.9.2.tgz_1496565553068_0.8009257623925805"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.9.3":{"name":"hyperapp","description":"1kb JavaScript library for building frontend applications.","version":"0.9.3","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperx","hyperscript","jsx","react","elm","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","jest":"^20.0.4","prettier":"~1.4.1","rollup":"^0.41.6","rollup-plugin-uglify":"^2.0.1"},"gitHead":"a0c70d2cc89d45ce4c66ad23c7cc02877f2de962","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.9.3","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-LFJ3JzznYEg6yaEaEeFQgVGZWIlhp89OorZiW/fTv6Inkl/LwLKSEhR36Ggn91olEnI52luotgv33/MlVrTLIQ==","shasum":"f2613c7ac0530c14323f2200e9e4be87ff38ffb1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.9.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCK1krEcOp21KTn4kE4IZ8Ptv0KvodOuFastS9xGMUOTAIhAOapVgy+f/zPaaP47D/aV52rMyAa/berCBys7zw5TpTj"}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.9.3.tgz_1497868336038_0.5757884033955634"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.10.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.10.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","react","elm","jsx","virtual dom","vdom","hyperx","hyperscript"],"scripts":{"test":"bundlesize && jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","bundlesize":"^0.6.1","jest":"^20.0.4","prettier":"~1.5.2","rollup":"^0.43.0","rollup-plugin-uglify":"^2.0.1"},"bundlesize":[{"path":"./dist/hyperapp.js","threshold":"1.5Kb"}],"gitHead":"486047c0f341f299b84ea4cd2f7a4b85cb5dd020","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.10.0","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-VfRIzLpdd8uJtGwu8WoswOAS+a/qgSR5iMewq/906o2HSsKQhepfUpKdHUzZtTsWvUqPrZvtEbn98kfQ5DQSww==","shasum":"201ef2c074b6fbcdb667b0dd8f09d9de1bae6ffb","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.10.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIFiNKlgBShPPOCNkqO2Lx1V+QJzwDCGivREn/L6XMOgIgdIHGCYfKaux07Thvh6P96Ihe35+RZv4ig1NoM9G72Pk="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.10.0.tgz_1499631601348_0.6406978366430849"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.10.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.10.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","react","elm","jsx","virtual dom","vdom","hyperx","hyperscript"],"scripts":{"test":"bundlesize && jest --coverage --no-cache","build":"rollup -cm -n hyperapp -f umd -i src/index.js -o dist/hyperapp.js","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","bundlesize":"^0.6.1","jest":"^20.0.4","prettier":"~1.5.3","rollup":"^0.45.2","rollup-plugin-uglify":"^2.0.1"},"bundlesize":[{"path":"./dist/hyperapp.js","threshold":"1.5Kb"}],"gitHead":"be397bbae43cdcd901da5ba581c18ef68e0e8cf3","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.10.1","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-VuGaETfivaaa2Z+gde1B7BkO9Dd95MQL4Vozty4w2xnuxMi5uS43zt+NvYTU/cVhllaKkOdA9F+uzARVoVjFyA==","shasum":"73cac9f97b8f3082cb3a15f7fd8db1196433825c","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.10.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9ahsCSsMMObRFLKOSIBkvdpe8cpPKANqqcktrsyN3OgIgCO6noeBFyGhkH9GVGKPqOcrk16cCGojGAWz70O0+zXY="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.10.1.tgz_1500293309671_0.525185561273247"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.11.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.11.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","react","elm","jsx","virtual dom","vdom","hyperx","hyperscript"],"scripts":{"test":"bundlesize && jest --coverage --no-cache","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","bundlesize":"^0.6.1","jest":"^20.0.4","prettier":"~1.5.3","rollup":"^0.45.2","uglify-js":"^2.7.5"},"bundlesize":[{"path":"./dist/hyperapp.js","threshold":"1.5Kb"}],"gitHead":"c2ed96cf6661bbf3ec8a6d3214ecadb5ad32df5c","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.11.0","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-bozBJZSutBj6KgkuNo1k14TIj5LPpS4qorwYMqMFlzz2m1BPEu2kXia/AxnRatps4xduWHB4rk7cRqSs1CVo7A==","shasum":"80b8af17aa50fd1908e8a8091711a23b1193fe3d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.11.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD59+2mfgVzdaBpynT5yqKrElk5BO6lVpALMOEykgBCRgIgS+27WPVGKdlcG3Oytd8ZrSY8J4LmD+0txJ06SNJSrkk="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.11.0.tgz_1502561071145_0.5810849929694086"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.12.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.12.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","react","elm","jsx","virtual dom","vdom","hyperx","hyperscript"],"scripts":{"test":"bundlesize && jest --coverage --no-cache","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","bundlesize":"^0.6.1","jest":"^20.0.4","prettier":"~1.5.3","rollup":"^0.45.2","uglify-js":"^2.7.5"},"bundlesize":[{"path":"./dist/hyperapp.js","threshold":"1.5Kb"}],"gitHead":"aa5887bd27f249e84185f163470a434780a8ab69","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.12.0","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-/hSMNXUnQbfZspJd14tXppHhoI4/ig34FAV1riPo8W2n3DWeBLd/+GbH2cMqIx9lcYapsFimYRYJP5ZrNLaa4g==","shasum":"224c98dfb9bd8fbe6a79ac2d9e6f267a6df8677a","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.12.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBkjMC1Oq9cIfEr8OWT8Lni7sLNNpmgN+amUlOmsxMlsAiAnCXnLgMqVHAX4EWTMnuIOPMkzbRuVKW0JccH1r0usTQ=="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.12.0.tgz_1503067617723_0.293881046352908"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.12.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.12.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","jsx","vdom","hyperx","hyperscript"],"scripts":{"test":"jest --coverage --no-cache","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepublish":"npm run build","format":"prettier --semi false --write 'src/**/*.js'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","jest":"^20.0.4","prettier":"~1.6.0","rollup":"^0.49.1","uglify-js":"^2.7.5"},"gitHead":"0d042a0a72f3c8fd86fc32ebaf7e29ced375af19","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.12.1","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-MRsQyCSyBy6zQ2F1hiCOGZYWy+CRqjOh/1iLH3fWpA9+68qtGW4UrFrcFucujbvf31YnycePbOKjXtT6sAJyHg==","shasum":"6dc951d948d44bf800a05c072a31a08becb190df","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.12.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA8EUUgRTKViZFpVImXTIcRiNJo47VJM/3lXGl9tngdAAiEAmztXDnoftoAz16j/uoSgcQdhrdgpQpkN3VAyXKXHvZQ="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.12.1.tgz_1504640844306_0.7646898506209254"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.13.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.13.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","jsx","vdom","hyperx","hyperscript"],"scripts":{"test":"jest --coverage --no-cache && tsc --project test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepublish":"npm run build","prepare":"npm run build","format":"prettier --semi false --write 'src/**/*.js' '{,test/ts/}*.{ts,tsx}'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","jest":"^20.0.4","prettier":"~1.6.0","rollup":"^0.49.1","typescript":"^2.5.2","uglify-js":"^2.7.5"},"gitHead":"b5f6119f600607c907f6fcfc8259e8e3683c3d59","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.13.0","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-BgLoyc95EwoP8cswlpR4IwfeWVOAgPPPMbIqZKqCq+9c3IObCYX6jhfAzi7/K7qOYFP238KE2pp+Z4M/uFJcWQ==","shasum":"3fa25b090ccb8e7b8d67f9f1d442c1ecd16fd5c3","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.13.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDU0Jq06qClyUcbkhIY/caFkFklMeAiqBL5BMZRaaQ+qAIgIZbxZ3crMWC9BVwfRLwv1dJd0qgU9tckH44gL7b5Qaw="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.13.0.tgz_1506575804293_0.4404863209929317"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.14.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.14.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","jsx","vdom","hyperx","hyperscript"],"scripts":{"test":"jest --coverage --no-cache && tsc --project test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepublish":"npm run build","prepare":"npm run build","format":"prettier --semi false --write 'src/**/*.js' '{,test/ts/}*.{ts,tsx}'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","jest":"^20.0.4","prettier":"~1.6.0","rollup":"^0.49.1","typescript":"^2.5.2","uglify-js":"^2.7.5"},"gitHead":"8425fd22507f97151a6927646f5cf849b151d961","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.14.0","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-BK+2EFUzyg39HnJlLf+h2O93HBHRNw7DFdWvUK4kuLjEYdt44U4qqKQy8ihgJYnaHUq2Fs4ZcFf+r4UsuqSgtQ==","shasum":"f5aac800be828f665e7e00a82cbc80b3c8cd4101","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.14.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHTdwpdeCtoULtEcDr2jmEQakPSuD4aF8FtbjWZp+kxBAiEArhu0WceqP/5hO50gLl1CaZiyxbhto9fzuVqRlb7qlM8="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.14.0.tgz_1507231925909_0.8854112126864493"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.15.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.15.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","jsx","vdom","hyperx","hyperscript"],"scripts":{"test":"jest --coverage --no-cache && tsc --project test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepublish":"npm run build","prepare":"npm run build","format":"prettier --semi false --write 'src/**/*.js' '{,test/ts/}*.{ts,tsx}'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"es2015"},"devDependencies":{"babel-preset-es2015":"^6.24.1","jest":"^20.0.4","prettier":"~1.6.0","rollup":"^0.49.1","typescript":"^2.5.2","uglify-js":"^2.7.5"},"gitHead":"a43f75cedd1e1e38e53e32ffbad7dbe684104777","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.15.0","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"jbucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-7gNcEI3zRu4n1afUS1yskTNtVKx5D2+5ZGyrITkemIkhk52XN7YVTZMkCH3tCPiRN3+wbI8aQPBATZnGFCpYSA==","shasum":"439061c5c94d562b0f169f6fbf44e48e06182f2b","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.15.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID80Ioms273UfhN6UcGF2ukNnEuocf3hZwIZiCzwPZAnAiEApfjU2f2huo1lzYF32wHOzi5kC5TyiQ/lyzNWnpRqpig="}]},"maintainers":[{"name":"jbucaran","email":"jbucaran@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.15.0.tgz_1507658130149_0.3121294258162379"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.15.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.15.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","jsx","hyperx","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc --project test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --source-map dist/hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write 'src/**/*.js' '{,test/ts/}*.{ts,tsx}'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"1.6.0","jest":"^21.2.1","prettier":"~1.7.4","rollup":"^0.50.0","typescript":"^2.5.2","uglify-js":"^2.7.5"},"gitHead":"0e5f4f153c8ebc707ce51dc684fea73d3fabe416","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.15.1","_npmVersion":"5.3.0","_nodeVersion":"8.5.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-C6MpORwsgRLXNAMBS2oAq4yGdC1ZWGqxPBA3+c/TOKCNRS/Pzs0N7r1/bcgnrptuLLHktnfJ9ebdrUrwhXMh0g==","shasum":"9e411b983d4ed6f9128e902f919116c2e387bcdd","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.15.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFc6ZnUq66H2mIxpjz1iSpYgV7nwDZUI3z/K17izkMOkAiA5AvfvzbWvwssfBRoBizGeeiBdkjJkybOkyi9xqLzC3Q=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.15.1.tgz_1507754976447_0.7782944678328931"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.16.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.16.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","jsx","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --in-source-map dist/hyperapp.js.map --source-map dist/hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write 'src/**/*.js' '{,test/ts/}*.{ts,tsx}'","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"1.6.1","jest":"^21.2.1","prettier":"~1.7.4","rollup":"^0.50.0","typescript":"~2.5.2","uglify-js":"^2.7.5"},"gitHead":"fb5f14bbe9cc76606a2254aac1d20115251e2436","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.16.0","_shasum":"5ab1239f6fd638a0db52f7db49a94f2cc63ae051","_from":".","_npmVersion":"3.10.10","_nodeVersion":"6.11.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"shasum":"5ab1239f6fd638a0db52f7db49a94f2cc63ae051","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.16.0.tgz","integrity":"sha512-8N6T7Uwfu3ZJ5QE/O6E5oCdoc/PQ9FIb7WMt/lPmsF/l3MvYGcC3Z0dbFyHT1y3rgzN9FSpuXOxmtYH67OahCw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHBuFS2GpgEHHzMaIgOVAE3k//jJg7H9GtMUihtUbm4bAiA/vXOvRDhHKEzYd1QLbD7Zq7UjpAJou2ZPRyNM8arlJA=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.16.0.tgz_1509907053800_0.6779799230862409"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.16.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.16.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --in-source-map dist/hyperapp.js.map --source-map dist/hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write \"src/**/*.js\" \"{,test/ts/}*.{ts,tsx}\"","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^21.2.1","prettier":"^1.8.2","rollup":"^0.51.2","typescript":"^2.6.1","uglify-js":"^2.7.5"},"gitHead":"cdf760963806e2d8a85fdbea2a38c17e5e812223","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.16.1","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-z5iFZCNv3xxJatRFzsmLQWUzljXrqn+GuLNxH8wI7YZuEuwSVDVGw5IOgkpvJq1h0RiR/6y9NGpVV5hTPANoSg==","shasum":"b8043e14c943b2884fd4a08d3070c7a2facc53c3","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.16.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRjsRMvK3vvTSLhz9Hr6pteojNEmH+SwhIokMzxE1myQIhAKFZc9XLQ3FPbosIaJEHzIi37uNc3USmGE6dR7vgKjgg"}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.16.1.tgz_1512047267277_0.5526617323048413"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.16.2":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.16.2","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js --mangle --compress warnings=false --pure-funcs=Object.defineProperty -p relative --in-source-map dist/hyperapp.js.map --source-map dist/hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write \"src/**/*.js\" \"{,test/ts/}*.{ts,tsx}\"","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^21.2.1","prettier":"^1.8.2","rollup":"^0.51.2","typescript":"^2.6.1","uglify-js":"^2.7.5"},"gitHead":"f81e366793406f2cc172228b13d4924621bf1209","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.16.2","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-lReX7A2EBJmVQ7nM9lVNfHxzopBf9Z1S+Wa0zQTTVyM/TtB52hSZVodFjz/JgBdrvPkle6d2vAkzuKQJxC54ag==","shasum":"1ca686cb9f369f54ba6faed0ac949df82dd22066","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.16.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAQK3yVTt/TiintYJZw02U67q9UMypc4sldJf6QcVa6mAiEA+hhigOEYA2twwBOQlf8zKUH+X8ZbtvWQyxpW3mYIpeA="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.16.2.tgz_1512147951699_0.7094912719912827"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.17.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.17.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^21.2.1","prettier":"^1.9.1","rollup":"^0.52.1","typescript":"^2.6.2","uglify-js":"^3.2.1"},"gitHead":"b92c2b6b872b251b4d00738304868fc9b4720f16","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.17.0","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-I1VEuL5hDxa5CQppUWYuSRpSPEoNjq/BXmSE1hSFyyc4/gFuAMA5wiqeru2pOvLcKdoHXCbSvqVlz429NAvdoA==","shasum":"9ff910b77ead03dbacc1bd36d38d89175d8e8473","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.17.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGE+hNibBQHTz/U7TkUlK+scwXfbqvBQjE/UsA1EoQfhAiEA5V62cNWqBuafiMdmJoUtGrPSq7uTsoekucWA3UMgdXE="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.17.0.tgz_1512865728900_0.6255901819095016"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.17.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.17.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^21.2.1","prettier":"^1.9.2","rollup":"^0.52.1","typescript":"^2.6.2","uglify-js":"^3.2.2"},"gitHead":"6ff312dc996fac3538742cbaa8748908f178a5d0","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.17.1","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-QGIKTWLFw9JSS8AM+1stcaXDZEyJUdacTh3hhSgqRa30D2NVcy43nAMyyHLHROFhlLTnYZM2wPz0VA+Ia/PHeA==","shasum":"96b806aecf0e4d20e8abd472b6934bd5b5f7bb58","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.17.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICr267/CPeUO9cUFn9iSrtG6FLf06IWjiKI/YNJhE6AKAiEAl4WX3Tslh9fbRszjhS6WvREwWerfnDsccvO+6O4aojE="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.17.1.tgz_1513278515072_0.7419473908375949"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.18.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.18.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","elm","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^21.2.1","prettier":"^1.9.2","rollup":"^0.52.1","typescript":"^2.6.2","uglify-js":"^3.2.2"},"gitHead":"3b0ddb1b972bef9abc16fc9cc9d999f34d87519f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.18.0","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-b7KAOCzH1eK/st/C5bpgOksunhT/x9shBpsTV/ofB16vibz9ZXnIjZ6SV+9RrH4HzzkuvTYbVPj/EqANz3uvWA==","shasum":"5b98f9ddd0f3ac70afb592d35da7a18cf4edc5fe","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.18.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/u8cWxE0ED7qiIrt431TnVoaQ3Gg67AOTnyYrVpAeEgIgL7ugEkcO9PoFp4T5KZPM3uBqTLqvnPkq6UK1rTmAbEQ="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.18.0.tgz_1513530591334_0.9811984056141227"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.18.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.18.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"^3.3.2"},"gitHead":"8d6bf3eef1ae9c2d33368d3724ade155d455a3c5","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.18.1","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-daoKNTIerklfccja7SKKrKQMvNXIXY378erb4d5VaGF9H5qN00bVTUsOub7umTsDrqP68R+mo/dtjStXWCzCLQ==","shasum":"701be0bc45ce61ab6b7c0fa6d2fb1cf743e82e2f","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.18.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIClKzV/9Lju/V7YlNf84NfcXtKExjDg/WeII0bnKmNQ1AiA8a0I9Q7HNbBtsPdP1CFCG/cE6sdT/G8RqVdvgO/Dykg=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.18.1.tgz_1514397138078_0.7768423894885927"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.18.2":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.18.2","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"^3.2.2"},"gitHead":"b32d2a1d831b9b15575a5c11183ffe7ca4f5f276","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.18.2","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-F0IAy8ZpJUR19IACvGi7DDP1vxuYsfMiscx9w/ZxxMETy3GvXT2afPA0ecHzlVZVRD7GTcVFBMdAeuIQR7J7EQ==","shasum":"d38a88c4027c3f2b6146d25fc4a5b25c085dad70","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.18.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEpfe6JqaVa1ZknBiQDmA3PcAPxCPDgXXeC1HLz33MejAiAbDMHH6IoN8xotse1GpvN9oCSXEt721JaOQIXwEzCZ5Q=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.18.2.tgz_1514429905780_0.043791873613372445"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.18.3":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.18.3","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"3.2.2"},"gitHead":"c7741845556c3f101e931ed7e29ab183c56317ff","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.18.3","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-qo6YudsW7lox32NgAAeBp5WKOFT/FBc+WSiOp8Z1SS8H6D4kXERTozcp5DmzRUF+KsOFpkbSVO6+feFIUQll0w==","shasum":"c357b9d6ceb8c9508a821c581c77dd58ebc1ad9f","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.18.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCQ4blCQPaEn6Du1IdZ2tuC8w4PrKmPpPrpZ7xx2/X/0gIgMrdDqAChFroRPCdZSd8Q+1SCAMdYqe/OMgqW/g5YmKY="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.18.3.tgz_1514430410152_0.8939203124027699"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.18.4":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.18.4","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"3.2.2"},"gitHead":"32a69b3f55aa8023d28563587dbbdbbc26b97d6f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.18.4","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-1VH1WsNYUnoKTcnt0aWc3uSnOQisf7l8H7IdE5mrmpq9AzbHic0PZM28h47n6tXYEwAdsw3myuBwjKMBzXR3Xg==","shasum":"c691cb94a024bf36e234b380f8a91e845f382fc3","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.18.4.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcrQYn/THnlC783RlAVw7ReTSvCxZehX7pLExUewFGxAIgMDRnOALowYxMBuSocHFnjzMXwW9RE2cqPEn+zDe9090="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.18.4.tgz_1514461401790_0.8608423685654998"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"0.18.5":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"0.18.5","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"3.2.2"},"gitHead":"2cd9ca15a5a57cd4440441a6200a08a9bd0dcb66","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@0.18.5","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-iQQ9OEyxpJi7O6rR1l5n7R1XSxhaAw53lnyQylKttGuflaWKS0DYeahBXSrVZyHfUJ3pG3LBQ3wyKCZFz4bj8g==","shasum":"f4118aff3e341f75cc28db7182b5d07523659f67","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-0.18.5.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDCIA1WUVZ+mWJh8aExYYSCWh529cnIg5ubgGhokIp+6AiEAkCypuvhgsgTN/79wp74Fzg1gXiyk9HU0LblmuEs5L3M="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-0.18.5.tgz_1514466393839_0.6921641349326819"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.0.0":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"1.0.0","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"3.2.2"},"gitHead":"c906e06fde5867f725341742156a77c164a3a156","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.0.0","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-S+t3pcQGS09vKc15fOKWQJVQUtyX8q4bHjQzazMCOQueTAHPY0+UvU3KValnjT+qbhuxrJVcEEY0dbzT7AcTFA==","shasum":"b5962f928a3a55fc0f69e39eea511e942b97034e","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBVoGgY7gnnTYfgan3Li2a7Y9FyL3q5JRM+U8s9I2+/qAiAavTE/zav418vwJZbjyAAASmmPHy2o/G3NwG5CjhaRcw=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-1.0.0.tgz_1514479165843_0.3751040240749717"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.0.1":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"1.0.1","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"3.2.2"},"gitHead":"14e7fbe2feb6aace3cd05a518182c98049051a89","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.0.1","_npmVersion":"5.5.1","_nodeVersion":"8.9.0","_npmUser":{"name":"jorgebucaran","email":"jbucaran@gmail.com"},"dist":{"integrity":"sha512-u1/Uufeo5BeZMQW7lFP8PSSbYbDvZvEFuAFJacdSmC3934t9OkddRZNPut7zyR9Pru7Mxya2wSj9lpCo7IhGEQ==","shasum":"4acbe3c432709c7ec29fa320d9d2e54a47e6a17f","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.0.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHlKMU7/G/tUqSwpc8qjAmx2fGfagVsgP11eOXIQ1bYGAiByFzVr13TEZX3mcL9BC3FWlcUdvrYDxYiaowcGGJEjsA=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-1.0.1.tgz_1514733716459_0.3084857380017638"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.0.2":{"name":"hyperapp","description":"1 KB JavaScript library for building frontend applications.","version":"1.0.2","main":"dist/hyperapp.js","jsnext:main":"src/index.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.0.4","prettier":"^1.9.2","rollup":"^0.53.0","typescript":"^2.6.2","uglify-js":"3.2.2"},"gitHead":"904c3b00adfd2ed8f0bafc130a743f308fa2d3c3","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.0.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-EVUP+IG8zAsXMI1b+fPwLJUXFEyx+nUf5aqWywku5Ok/Tn3iVvXspOqU4UHenk5SoXYWPNSSbTUDWydWsaNRuw==","shasum":"aa3e03434650297368339a9465cb0b489fb49332","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.0.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3UvcOetmM0iQvh/4QYZde3nY49fUJiLmeR1f2+FsDKwIhALFTHaikBZ9UVtf2ihF3485bYAetwp1xqWgqViySCYCF"}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp-1.0.2.tgz_1516038313004_0.8057001060806215"},"directories":{},"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.1.0":{"name":"hyperapp","description":"1 KB JavaScript library for building web applications.","version":"1.1.0","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"a03435e2b517654e760b5ab6c333e067e9f1fcf4","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.1.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-K6JC/VGd88p7YnYhJMPRw8j7rCTWbIaQ/h47twW50OSNAjFSUc27At1fFe2+1Q/VyN8GdF9d1Lqpl61oPXhBMw==","shasum":"d6892f16cc4c52698cf44f8a11f2044741899c9d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.1.0.tgz","fileCount":8,"unpackedSize":52058,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE9Sxf3q0Yw9/PqGy4NZuMDbStsW1LxyG2zjOipB0X4QAiBFIhEEQHGxp1/PlP/HtZFJOjWmO0uka697LFegPiX8cA=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.1.0_1518017831902_0.33817815571693655"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.1.1":{"name":"hyperapp","description":"1 KB JavaScript library for building web applications.","version":"1.1.1","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"fe7b0e4e180192007bb1478c78e81b0b57ee183f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.1.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-RwMay6xPZMgkmrS38CT2WrIIfMZAAlNHU+Rx65gJYrGueHQY03sXTMtz8c4CyYAvi2KCupXpYEydC4rLmHLLaA==","shasum":"1e80f0b2b4180defd389f815dfcbd863a9143a97","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.1.1.tgz","fileCount":8,"unpackedSize":52122,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCo9z9l5RmA5GMAkc0l612teUjw8TSEt/0Ov9T/9u9/FwIgP8cuKs88iza+bABmu/Hch7dhbLTm5uI+PCaYRPaXRsg="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.1.1_1518031668996_0.7899510968176431"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.1.2":{"name":"hyperapp","description":"1 KB JavaScript library for building web applications.","version":"1.1.2","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env"},"devDependencies":{"babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"b7fadb8575b6488f9b7dfaa174a1fb4577c21797","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.1.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-6r3YTaNMPw8OOX+AjQy+6WUGP0lJ53yEPOieSrUbCZkrEWksKxEi+65/jS41Fn5T75bzSRfT2T7j2fCamy5q6w==","shasum":"68a0087d2b28df04439ca43646f8b989d4d1d079","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.1.2.tgz","fileCount":8,"unpackedSize":52166,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD45Wp9rozi7O0Bj32Sx92rWsoub7AHMHLe9NIYW778fQIgUtgDgWOUa/a4vcsNrGLVGvf/5B8NtmCMaoAkCM1IcoM="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.1.2_1518245866373_0.2720502914482117"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.0":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.0","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"40e662b42601ceca730c7a2ba28362f38851f1bc","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.2.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-FJpmcuix+s7RC9+InPuYztrmcPWhYY3IJ0WMhyfSksRc6yLueWcuaT0an/Mc367RCte2B5dhgdaP5NgEydj2Jw==","shasum":"021dc2fdb2d5c068e495de3365b639f189df82ae","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.0.tgz","fileCount":8,"unpackedSize":55629,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAnpci1rasfyv0g/VahvBpzw0mSTe5jQHIKFT3gJH9d8AiAknjVAdtX6D29rzRFjG4g4poCiKQDl0FG0S2P+3Bjblw=="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.0_1521389598060_0.890645117434649"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.1":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.1","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"efcdf3663a06edbeb93d466d98f1a2eae399acff","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.2.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-sAroMeV2zS6A3/qsmpv86TNDdNo3d1YvrDRRfn0IJjDvkylNmSgRN7r+bwFFxG8zGMmF4HuQz7fp7uMwNDp6ew==","shasum":"a21a20395ed74427dadca05dcfa0baccd38c4fa7","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.1.tgz","fileCount":8,"unpackedSize":55869,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC7wmhRmmctP6gtdlByh3IVRpaP8JaPx7xJRjeAEIEM+gIgbBMo7M21/9qFAqd9dzKhb/oMKIGgeJwcCj4lP9sZgrw="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.1_1521728824848_0.32000933724965375"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.2":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.2","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"e51d096b80da7e2b26d2a027b6c302403fcd853d","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.2.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-D1VG0HipuiG75UyFIEzs8YH+IEzIlyIwsXODftRU7AjaiSy7Vtl72VvggQ6KPA/U0vLO7kfadmPhqC1AjoXMVA==","shasum":"a2dd9dd897eff14d9f9d2155408518e2f1540958","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.2.tgz","fileCount":8,"unpackedSize":55939,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEmzCbjsFzwUmIXxxsys/L5Cdbq/HG7FbyZ6m8msg1UKAiEAi8BNv+QWPRoZ5sGK2SnW8h2OBbzNGykbAnOk/KmqYTU="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.2_1521820171136_0.6687789929614101"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.3":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.3","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"18a5670784a3ddaac33562ae42a6f73364d56cdf","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"homepage":"https://github.com/hyperapp/hyperapp#readme","_id":"hyperapp@1.2.3","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-1OJuQbl7eOcHjokdpy5o/OHh1AVUgJtKN2M+Ej4cQOqOMf2pyjgairyzN/ui9Qw1gLMrPQ5xKeWHm+n+DWweDA==","shasum":"d31b8f7db5dbb5911dad2dd31af7c486eb57ebe0","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.3.tgz","fileCount":8,"unpackedSize":56186,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQ6t8kBm38nqKhKLoGUwvg0MyGIBGPd5Y2eSZLurUHjQIhAL0R5hfecBb9MIFf168lhhVAC/b6wGXxUSR7Sy5MJTZF"}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.3_1521867575790_0.7751787106613053"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.4":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.4","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","vdom","virtual-dom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"2d1f19d908688b321623353f7cbfbbb5038d7fd1","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@1.2.4","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-2DCweYb6kYaI2DuMcfiH60jdbPrcoEvdt18uIcl8FmLdj1ZhJfnXbbljkBozsDYhUjzio3u+zAWEyiq1A4Wp6A==","shasum":"bc633712386f504b898516a6ba64dcef9e659258","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.4.tgz","fileCount":8,"unpackedSize":56364,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDX844/yCXGBDrs3wxeuUcUaENXiBs2WBYeNjtVC8uvpwIgYWC7aV/IA6XQ/FwVUW2pZcwZfFEluR+XAKkAIXrzwRc="}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.4_1521880139972_0.05806626584384267"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.5":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.5","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --semi false --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.2.0","prettier":"^1.10.2","rollup":"^0.55.3","typescript":"2.7.1","uglify-js":"3.3.9"},"gitHead":"808f42d2373ffb1f3956c37caed768859868b6e2","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@1.2.5","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-XKHTW3fUU8nCt6lZngJoprRTsAbpd0NRtN/BMLTJY6DMs76lgTXyEynw2d1G4di/gNib1FM/ocsdTLCup4SJ/A==","shasum":"81eab50089413a6c0e85899abc2b9cd23393b9cc","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.5.tgz","fileCount":8,"unpackedSize":56397,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLt0wqkjf43xc8+2m8JmJhMbdltTINqm1obtixZoJE+AIhALaSne4gx0LfmE7QWOorAHUaamt3eeGcooV2GVotYlP9"}]},"maintainers":[{"email":"jbucaran@gmail.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.5_1521881014125_0.026330124778655817"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.6":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.6","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.4.3","prettier":"^1.11.1","rollup":"^0.57.1","typescript":"2.8.1","uglify-js":"3.3.16"},"prettier":{"semi":false},"gitHead":"8da3edec673f9b67da03771b8713bda3a2b23519","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@1.2.6","_npmVersion":"5.6.0","_nodeVersion":"10.0.0","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-Kplla3GduO2c8gff1bBOy9iKlJFMHwPn9FeEHTGCut+1zVmpESUKb8/JbmLtJh2h1MELWxih08lXQxpDbv0J4w==","shasum":"fa3b42dad88e50f962b9d9f922dfa7bef3c8ebc8","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.6.tgz","fileCount":9,"unpackedSize":65333,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbD0TRCRA9TVsSAnZWagAAuqUQAKUgB2tX7OSWO1V7pE5j\n/60Pgb5G/zKqD9eSztdJKmeGIcijo7HndcqSTynL6+uXaHPgsLYynZs+CSRD\n2xws/JAA55cClwLKduOYADcGrosp9iKMNr0olXzkk9iLx/oHDbachtcJc+kf\nXh+IQwWhY8QwIkq78s4KQ8t1BcpSDiu5ejt9kwJ/CYTlc8rhA11Jdo0cFTML\nMBUAgx3BJ5N44KbYskk+SkE73mzUJXOh94fAk15CbQZZIIpLIAmHw2+icYnY\nC+zAUGC0MSC2X7bLikcwcnrIo1KGEaSgmCUwmGUDeXpgqK8lxvaqPpPROTny\nPm4zc8F7btakxfb+XlJlk1NcF0V1AUORfWxECOFMbpAnlJmJEhbgyhCy6qgO\ndGo57/SfjZ/EClq9q7EvB97z8YJdUWQyT0vOYi9W6EP3mfWFbfPqYbNd6jlZ\n7lLYdTrHuq02nV1MA7x6LO4oUu1OSfyf/NYRMXO8qsJ6AtDslqxkmmI+zcQb\nz3AJbAOkhX2W3dYmj5CT2rdFHz0qEOWUSK5LHTScOPAoElbFXJbU2jRSF08H\n2CtiNkO1wTkw1WGg5RUOauf4VL1bjjJrY0o7FFtlPhy+WarBfQsoI5GZkXDq\nMDcUmJuwJOwIw/dDZCmTOG6RhOXy9QCi3brbcc/DF38f4V8V39S9Ekz/4YUM\nUEt2\r\n=heog\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF9gg8X+nNxfRRZqB42cTR2CX1QjKNjkTSb0O0wyEZggAiEAqhQy59szKuUPf7tHl9ddK3HLK86mE34VsSz+T/Je1+g="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.6_1527727311909_0.6046998244472896"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.7":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.7","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.4.3","prettier":"^1.11.1","rollup":"^0.57.1","typescript":"2.8.1","uglify-js":"3.3.16"},"prettier":{"semi":false},"gitHead":"ebdfc2c46667e2a87f78363fa02a35eb593a8a01","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@1.2.7","_npmVersion":"6.1.0","_nodeVersion":"10.0.0","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-ec106/4t4lXtNQcE1cI//91XT1rG25Wfm8L0AmSdh3pn4rka4Kzn2IDq2rE2T0Kw2rowuAZt2a75GOqKTnd3BA==","shasum":"6fa8182c941e81f6daa24f1758a00169203e13a1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.7.tgz","fileCount":9,"unpackedSize":65503,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbTw7QCRA9TVsSAnZWagAAMQAP/jS0QJmcwkdrqY41Cfaz\n9LlCIXm4ln4bnC2g5uwW9M8s6+jYvjnbjQOXAz+ke6+E7JkAc4diHou177nn\n+SwTqtWhS1bhAjhv7cyfI1JeeolMRSvLIffakrv7nhb0Hy1FjL+5cM14zRL8\nrmwMT72AhMWw1LkhIkvMLlmFlHHXYifFHKcTZYD2OkRBeLi94itUpLIvS6RP\n2+bywd+Bxn8upuAWzl7jFD1iHB6jUfiGlYPOlauOFMUrjnt9Ivb4Q+lVu4On\nWXYsFYZM3gN5KtCKvcjV5U+geOj67rpZu11O/11E9JpJGQq3WjwgKfY6ZhYh\n/aW2DfcwgGwkmhjYmoR3FLqGh1dKiO41W1XWs9GhNqBq3QFw33eehqk842Eo\nxwCjdadDIU2JqBgbvSneLNZrknfR8P27mFdC5/CW1l5N9caPSbcucSPtv8UX\n1YOxhBeTWgPV/i0AcfSCrAFuWHrGgGFXVYc/TaCgYGQ5wQ1okkjjVH+i1PV0\nww/LmmMR4J2h6CCM9Fcs5Zsml03+SjkHJsETQoEmpqXs68J1u7UtPK1LhGj3\na6u2Ajx2Dzxz1BnsVAD4Tgw8+DRRH+QhwXkrugQIefz50h5r39nYqiyO9edk\n80pdk5KCUaz87UVO8jryektn9zaDrHBHnGKL6eRioFZeNyMTOO3ni7A/G6cy\nWItQ\r\n=UsLx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCFwgjLy2k5ySD6S1EoRw0j2LAjFk5glP6BlzZ7atEQYgIgIWgKSfift1coPQor0LYq64AEGYdIk7C012d1HoEVHXo="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.7_1531907792555_0.4855979032930846"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.8":{"name":"hyperapp","description":"1 kB JavaScript framework for building web applications.","version":"1.2.8","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","files":["src","dist","hyperapp.d.ts"],"author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.6.1","jest":"^22.4.3","prettier":"^1.11.1","rollup":"^0.57.1","typescript":"2.8.1","uglify-js":"3.3.16"},"prettier":{"semi":false},"gitHead":"5fa6109623484797b4da526398f6b8eab03678bf","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@1.2.8","_npmVersion":"6.1.0","_nodeVersion":"10.0.0","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-BqPu/1cJ9hWdMUYNPfmsnh92pap6IAzlG0KOJrdtdMkciJJVUOSwaQTDEaP086TmVOWwjRzlQrZngLQwAE6ocg==","shasum":"48a3b02d6948b8faf3b72f42d70577470d0d4124","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.8.tgz","fileCount":8,"unpackedSize":59740,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbTxSCCRA9TVsSAnZWagAA+XsP/2sQ/O7zuBr/GdvVyUDL\nJQCRmOi6d1aiviTrK4vLeMcevtCcETkN0q4vYmEXCkrsig7gHTXV51etY3Gy\nCM6RQf52zTZQ5XJ9pu7dyM6dNbAaYak50t9HTvhMcZQ+fYODTM1yvRgYHFJx\n/v+8a1gdWtHCnpEJEnhjIKejf9ZUx+DvtEX5SUoyb8f02HoR2zK3ZHfsywtS\nasY9KBp6CSk6kJwBegxIiDFTa5nPiVqsyy3Xp7V1FP+AARHco0fHJtIdBCbp\n0bUpmc7sIHV85RzjrsWebfpN14j0UQl938pkb6rAGX5vBcnTTnGO+r3lOemr\nHnvdBi2AWKdMeGaZuTpyQagUV7caLJ/BHEaqbazLTpe3B2qvZlWQ6sy+Z7W+\nVT+dpS2vFrS+KdMa83qaKnRud/lHSeyFWuTqL49SsLpyaGsxGZtn4H8pPR6l\nhzYJOsQBRLnLFS8pnoHmO/c+FgskPus+BROnFPYcbZv7xcU4UzTsJRXcpqTy\nwn2vAv0ADBKq4OspRo/e+AGpF6V9Y9eP4gwR9KgH6saG0GpTMQKuZsAaWXb0\nH6HBEhiD4lwK6vgW2BJlavG5NeLEXTC1+Qot3a9+ve5eqVB8TRPzR7Kq6RIn\nt9PHjQ2ShHqDBYHsq3w2b7zEHumKNIUCRfxoWtBkuWzSOuS9b59ml1FYaxNT\nMbc2\r\n=E0U+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCdcoEZY+ShgeFfaFFvvwLmKsO6v2bufuO9f5MgarriJwIhAP+BViKzjl7HtmG2zbmZ3aSWyHD0LcJt3eD6oNDTQW0T"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.8_1531909250066_0.7936008592812367"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"1.2.9":{"name":"hyperapp","description":"1 kB JavaScript micro-framework for building declarative web applications.","version":"1.2.9","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","declarative"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.7.0","jest":"^23.5.0","prettier":"^1.14.2","rollup":"^0.65.2","typescript":"3.0.3","uglify-js":"3.4.9"},"prettier":{"semi":false},"gitHead":"bb0d38c2028a20d84e8038bec729a4f22d208648","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@1.2.9","_npmVersion":"6.4.1","_nodeVersion":"10.0.0","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-bIzi12am7pyQ5nc2qnQpN6GWonjdJp+AghY7j9H9L0vccM1OQ3Cqn13cZlmS9KYm91Nf9fwF4KjvbQekFBxHVw==","shasum":"a17ec09634968a5fa5f6b7d649e7a03d9680fcf2","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.9.tgz","fileCount":8,"unpackedSize":60860,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbknyhCRA9TVsSAnZWagAA4/0P+wWZtwVbB/7h++SSrXRG\nZk0XuH107AqKi5n4nX59s7ROJPcwFXCk8VMjH8YBbAUCfsXKQutKn0EXHer0\nV/uPH5bnH/Eml3bcXGJkVyD/uhama4vAS0IL9K67PIE3utUPCefXpiO+Lx58\ncQaDR18UythbotucOzqXFq8DqexATlAqpY969frx7xURN2lodnJDqmmBSc5W\nuTm2V/cWspJDjrwxrcmhKmLLkxkEVKEXPHGBE8f4zk4TR9aiI6Gmc8WIDRn4\nvvhIQfA05xJFSNkJIuvpyy7iH1QX629rc8EVw8hDKEbGeI0EjDtdATydBlmz\ndvEU5vXyBM3AzrsPDEMsKMrUP1EFJPNq+sCQzMC3i5ErHU/ViNK+IYXybh4n\nCR89IyaRbN6zxrmFV4SnEcXITerKiBjmcoK2qoRmXKXPqGc+NfJy0Ax8DaRf\nwasUvM2baYbfV8gLoECFA4eZPXTyUaZfgI7c0G6g27axNuczXxSTK2kUquk9\n2RaeWllNoOHshMSSW3M1J5oWMwaOZ/YS0XysnqkZOh36vnUDdezzlE1fW15P\nllzOO+SBQciC7G6xi5yY9FDJXChl4F54EkU3TVs+nYTM2wn+G/7ZcF4m3UwV\nAk934s05iCHNjwzA+qI3svR87s4T447MNZ6gy2sN/1iK0LGtfXy7BL/DTVhY\nLcwK\r\n=XLuq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICwyrDaCmY1VyFYtSBFr9JTB5JUFqJvE0JzVU4aInMa3AiA8kieQBDPGO36Xe9OpJ4uiZS0Vs/5oUsVEPeHEAi5GBQ=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.9_1536326816415_0.6687386789786716"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"2.0.0-alpha.0":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.0","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.7.0","jest":"^23.5.0","prettier":"^1.14.2","rollup":"^0.65.2","typescript":"3.0.3","uglify-js":"3.4.9"},"prettier":{"semi":false},"readme":"# <img height=24 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n* **Minimal** — We have aggressively minimized the concepts you need to understand to be productive while remaining on par with what other frameworks can do.\n* **Pragmatic** — Hyperapp holds firm on the functional programming front when managing your state, but takes a pragmatic approach to allowing for side effects, asynchronous actions, and DOM manipulations.\n* **Standalone** — Do more with less. Hyperapp combines state management with a virtual DOM engine that supports keyed updates & lifecycle events — all with no dependencies.\n\n## Getting Started\n\nOur first example is a counter that can be incremented or decremented. Go ahead and [try it online](https://codepen.io/hyperapp/pen/zNxZLP/left/?editors=0010).\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst state = {\n  count: 0\n}\n\nconst actions = {\n  down: value => state => ({ count: state.count - value }),\n  up: value => state => ({ count: state.count + value })\n}\n\nconst view = (state, actions) => (\n  <div>\n    <h1>{state.count}</h1>\n    <button onclick={() => actions.down(1)}>-</button>\n    <button onclick={() => actions.up(1)}>+</button>\n  </div>\n)\n\napp(state, actions, view, document.body)\n```\n\nHyperapp consists of a two-function API. <samp>hyperapp.h</samp> returns a new [virtual DOM](#view) node tree and <samp>hyperapp.app</samp> [mounts](#mounting) a new application in the specified DOM element. Without an element, it's possible to use Hyperapp \"headless\", which can be useful when unit testing your program.\n\nThis example assumes you are using a JavaScript compiler like [Babel](https://babeljs.io) or [TypeScript](https://www.typescriptlang.org) and a module bundler like [Parcel](https://parceljs.org), [Webpack](https://webpack.js.org), etc. If you are using JSX, all you need to do is install the JSX [transform plugin](https://babeljs.io/docs/plugins/transform-react-jsx) and add the pragma option to your <samp>.babelrc</samp> file.\n\n```json\n{\n  \"plugins\": [[\"transform-react-jsx\", { \"pragma\": \"h\" }]]\n}\n```\n\nJSX is a language syntax extension that lets you write HTML tags interspersed with JavaScript. Because browsers don't understand JSX, we use a compiler to transform it into <samp>hyperapp.h</samp> function calls under the hood.\n\n```jsx\nconst view = (state, actions) =>\n  h(\"div\", {}, [\n    h(\"h1\", {}, state.count),\n    h(\"button\", { onclick: () => actions.down(1) }, \"-\"),\n    h(\"button\", { onclick: () => actions.up(1) }, \"+\")\n  ])\n```\n\nNote that JSX is not required for building applications with Hyperapp. You can use <samp>hyperapp.h</samp> directly and without a compilation step as shown above. Other alternatives to JSX include [@hyperapp/html](https://github.com/hyperapp/html), [hyperx](https://github.com/substack/hyperx), [t7](https://github.com/trueadm/t7) and [ijk](https://github.com/lukejacksonn/ijk).\n\n## Installation\n\nInstall with npm or Yarn.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Overview\n\nHyperapp applications consist of three interconnected parts: the [state](#state), [view](#view), and [actions](#actions).\n\nOnce initialized, your application executes in a continuous loop, taking in actions from users or from external events, updating the state, and representing changes in the view through a virtual DOM model. Think of an action as a signal that notifies Hyperapp to update the state and schedule the next view redraw. After processing an action, the new state is presented back to the user.\n\n### State\n\nThe state is a plain JavaScript object that describes your entire program. It consists of all the dynamic data that is moved around in the application during its execution. The state cannot be mutated once it is created. We must use actions to update it.\n\n```js\nconst state = {\n  count: 0\n}\n```\n\nLike any JavaScript object, the state can be a nested tree of objects. We refer to nested objects in the state as partial state. A single state tree does not conflict with modularity — see [Nested Actions](#nested-actions) to find out how to update deeply nested objects and split your state and actions.\n\n```js\nconst state = {\n  top: {\n    count: 0\n  },\n  bottom: {\n    count: 0\n  }\n}\n```\n\nBecause Hyperapp performs a shallow merge when updating your state, the top-level state must be a plain JavaScript object, other than this, you can use any type, including arrays, ES6 [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), [Sets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set), [Immutable.js](https://facebook.github.io/immutable-js/) structures, etc.\n\n### Actions\n\nThe only way to change the state is via actions. An action is a unary function (accepts a single argument) expecting a payload. The payload can be anything you want to pass into the action.\n\nTo update the state, an action must return a partial state object. The new state will be the result of a shallow merge between this object and the current state. Under the hood, Hyperapp wires every function from your actions to schedule a view redraw whenever the state changes.\n\n```js\nconst actions = {\n  setValue: value => ({ value })\n}\n```\n\nInstead of returning a partial state object directly, an action can return a function that takes the current state and actions as arguments and returns a partial state object.\n\n```js\nconst actions = {\n  down: value => state => ({ count: state.count - value }),\n  up: value => state => ({ count: state.count + value })\n}\n```\n\nState updates are always immutable. Do not mutate the state object argument within an action and return it — the results are not what you expect (e.g., the view will not be redrawn).\n\nImmutability enables time-travel debugging, helps prevent introducing hard-to-track-down bugs by making state changes more predictable, and allows cheap memoization of components using shallow equality <samp>===</samp> checks.\n\n#### Asynchronous Actions\n\nActions used for side effects (writing to databases, sending a request to a server, etc.) don't need to have a return value. You may call an action from within another action or callback function. Actions which return a Promise, <samp>undefined</samp> or <samp>null</samp> will not trigger redraws or update the state.\n\n```js\nconst actions = {\n  upLater: value => (state, actions) => {\n    setTimeout(actions.up, 1000, value)\n  },\n  up: value => state => ({ count: state.count + value })\n}\n```\n\nAn action can be an <samp>[async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)</samp> function. Because <samp>async</samp> functions return a Promise, and not a partial state object, you need to call another action in order to update the state.\n\n```js\nconst actions = {\n  upLater: () => async (state, actions) => {\n    await new Promise(done => setTimeout(done, 1000))\n    actions.up(10)\n  },\n  up: value => state => ({ count: state.count + value })\n}\n```\n\n#### Nested Actions\n\nActions can be nested inside namespaces. Updating deeply nested state is as easy as declaring actions inside an object in the same path as the part of the state you want to update.\n\n```jsx\nconst state = {\n  counter: {\n    count: 0\n  }\n}\n\nconst actions = {\n  counter: {\n    down: value => state => ({ count: state.count - value }),\n    up: value => state => ({ count: state.count + value })\n  }\n}\n```\n\n#### Interoperability\n\nThe <samp>app</samp> function returns a copy of your actions where every function is wired to changes in the state. Exposing this object to the outside world can be useful to operate your application from another program or framework, subscribe to global events, listen to mouse and keyboard input, etc.\n\nTo see this in action, modify the example from [Getting Started](#getting-started) to save the wired actions to a variable and try using them. You should see the counter update accordingly.\n\n```jsx\nconst main = app(state, actions, view, document.body)\n\nsetInterval(main.up, 250, 1)\nsetInterval(main.down, 500, 1)\n```\n\nIncluding an action returning the state argument can be useful. Because state updates are always immutable, returning a reference to the current state will not schedule a view redraw.\n\n```jsx\nconst actions = {\n  getState: () => state => state\n}\n```\n\n### View\n\nEvery time your application state changes, the view function is called so that you can specify how you want the DOM to look based on the new state. The view returns your specification in the form of a plain JavaScript object known as a virtual DOM and Hyperapp takes care of updating the actual DOM to match it.\n\n```js\nimport { h } from \"hyperapp\"\n\nexport const view = (state, actions) =>\n  h(\"div\", {}, [\n    h(\"h1\", {}, state.count),\n    h(\"button\", { onclick: () => actions.down(1) }, \"-\"),\n    h(\"button\", { onclick: () => actions.up(1) }, \"+\")\n  ])\n```\n\nA virtual DOM is a description of what a DOM should look like using a tree of nested JavaScript objects known as virtual nodes. Think of it as a lightweight representation of the DOM. In the example, the view function returns an object like this.\n\n```jsx\n{\n  nodeName: \"div\",\n  attributes: {},\n  children: [\n    {\n      nodeName: \"h1\",\n      attributes: {},\n      children: [0]\n    },\n    {\n      nodeName: \"button\",\n      attributes: { ... },\n      children: [\"-\"]\n    },\n    {\n      nodeName:   \"button\",\n      attributes: { ... },\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nThe virtual DOM model allows us to write code as if the entire document is thrown away and rebuilt on each change, while we only update what actually changed. We try to do this in the least number of steps possible, by comparing the new virtual DOM against the previous one. This leads to high efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and re-create it entirely on every update — not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is several orders of magnitude more expensive.\n\n### Mounting\n\nTo mount your application in a page, we need a DOM element. This element is referred to as the application container. Applications built with Hyperapp always have a single container.\n\n```jsx\napp(state, actions, view, container)\n```\n\nHyperapp will also attempt to reuse existing elements inside the container enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully rendered page together with your application. Then instead of throwing away the existing content, we'll turn your DOM nodes into an interactive application out of the box.\n\nThis is how we can recycle server-rendered content out the counter example from before. See [Getting Started](#getting-started) for the application code.\n\n```html\n<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <script defer src=\"bundle.js\"></script>\n</head>\n\n<body>\n  <div>\n    <h1>0</h1>\n    <button>-</button>\n    <button>+</button>\n  </div>\n</body>\n</html>\n```\n\n### Components\n\nA component is a pure function that returns a virtual node. Unlike the view function, components are not wired to your application state or actions. Components are dumb, reusable blocks of code that encapsulate markup, styles and behaviors that belong together.\n\nHere's a taste of how to use components in your application. The application is a typical To-Do manager. Go ahead and [try it online here](https://codepen.io/hyperapp/pen/zNxRLy).\n\n```jsx\nimport { h } from \"hyperapp\"\n\nconst TodoItem = ({ id, value, done, toggle }) => (\n  <li\n    class={done && \"done\"}\n    onclick={() =>\n      toggle({\n        value: done,\n        id: id\n      })\n    }\n  >\n    {value}\n  </li>\n)\n\nexport const view = (state, actions) => (\n  <div>\n    <h1>Todo</h1>\n    <ul>\n      {state.todos.map(({ id, value, done }) => (\n        <TodoItem id={id} value={value} done={done} toggle={actions.toggle} />\n      ))}\n    </ul>\n  </div>\n)\n```\n\nIf you don't know all the attributes that you want to place in a component ahead of time, you can use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). Note that Hyperapp components can return an array of elements as in the following example. This technique lets you group a list of children without adding extra nodes to the DOM.\n\n```jsx\nconst TodoList = ({ todos, toggle }) =>\n  todos.map(todo => <TodoItem {...todo} toggle={toggle} />)\n```\n\n#### Lazy Components\n\nComponents can only receive attributes and children from their parent component. Similarly to the top-level view function, lazy components are passed your application global state and actions. To create a lazy component, return a view function from a regular component.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Up = ({ by }) => (state, actions) => (\n  <button onclick={() => actions.up(by)}>+ {by}</button>\n)\n\nexport const Down = ({ by }) => (state, actions) => (\n  <button onclick={() => actions.down(by)}>- {by}</button>\n)\n\nexport const Double = () => (state, actions) => (\n  <button onclick={() => actions.up(state.count)}>+ {state.count}</button>\n)\n\nexport const view = (state, actions) => (\n  <main>\n    <h1>{state.count}</h1>\n    <Up by={2} />\n    <Down by={1} />\n    <Double />\n  </main>\n)\n```\n\n#### Children Composition\n\nComponents receive their children elements via the second argument, allowing you and other components to pass arbitrary children down to them.\n\n```jsx\nconst Box = ({ color }, children) => (\n  <div class={`box box-${color}`}>{children}</div>\n)\n\nconst HelloBox = ({ name }) => (\n  <Box color=\"green\">\n    <h1 class=\"title\">Hello, {name}!</h1>\n  </Box>\n)\n```\n\n## Supported Attributes\n\nSupported attributes include [HTML attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes), [SVG attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute), [DOM events](https://developer.mozilla.org/en-US/docs/Web/Events), [Lifecycle Events](#lifecycle-events), and [Keys](#keys). Note that non-standard HTML attribute names are not supported, <samp>onclick</samp> and <samp>class</samp> are valid, but <samp>onClick</samp> or <samp>className</samp> are not.\n\n### Styles\n\nThe <samp>style</samp> attribute expects a plain object rather than a string as in HTML.\nEach declaration consists of a style name property written in <samp>camelCase</samp> and a value. CSS variables are supported too.\n\nIndividual style properties will be diffed and mapped against <samp>[HTMLElement.style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style)</samp> property members of the DOM element - you should therefore use the JavaScript style object [property names](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference), e.g. <samp>backgroundColor</samp> rather than <samp>background-color</samp>.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### Lifecycle Events\n\nYou can be notified when elements managed by the virtual DOM are created, updated or removed via lifecycle events. Use them for animation, data fetching, wrapping third party libraries, cleaning up resources, etc.\n\nNote that lifecycle events are attached to virtual DOM nodes not to components. Consider adding a key to ensure that the event is attached to a specific DOM element, rather than a recycled one.\n\n#### oncreate\n\nThis event is fired after the element is created and attached to the DOM. Use it to manipulate the DOM node directly, make a network request, create a slide/fade in animation, etc.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Textbox = ({ placeholder }) => (\n  <input\n    type=\"text\"\n    placeholder={placeholder}\n    oncreate={element => element.focus()}\n  />\n)\n```\n\n#### onupdate\n\nThis event is fired every time we update the element attributes. Use <samp>oldAttributes</samp> inside the event handler to check if any attributes changed or not.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Textbox = ({ placeholder }) => (\n  <input\n    type=\"text\"\n    placeholder={placeholder}\n    onupdate={(element, oldAttributes) => {\n      if (oldAttributes.placeholder !== placeholder) {\n        // Handle changes here!\n      }\n    }}\n  />\n)\n```\n\n#### onremove\n\nThis event is fired before the element is removed from the DOM. Use it to create slide/fade out animations. Call <samp>done</samp> inside the function to remove the element. This event is not called in its child elements.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const MessageWithFadeout = ({ title }) => (\n  <div onremove={(element, done) => fadeout(element).then(done)}>\n    <h1>{title}</h1>\n  </div>\n)\n```\n\n#### ondestroy\n\nThis event is fired after the element has been removed from the DOM, either directly or as a result of a parent being removed. Use it for invalidating timers, canceling a network request, removing global events listeners, etc.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Camera = ({ onerror }) => (\n  <video\n    poster=\"loading.png\"\n    oncreate={element => {\n      navigator.mediaDevices\n        .getUserMedia({ video: true })\n        .then(stream => (element.srcObject = stream))\n        .catch(onerror)\n    }}\n    ondestroy={element => element.srcObject.getTracks()[0].stop()}\n  />\n)\n```\n\n### Keys\n\nKeys helps identify nodes every time we update the DOM. By setting the <samp>key</samp> property on a virtual node, you declare that the node should correspond to a particular DOM element. This allow us to re-order the element into its new position, if the position changed, rather than risk destroying it.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ImageGallery = ({ images }) =>\n  images.map(({ hash, url, description }) => (\n    <li key={hash}>\n      <img src={url} alt={description} />\n    </li>\n  ))\n```\n\nKeys must be unique among sibling-nodes. Don't use an array index as key, if the index also specifies the order of siblings. If the position and number of items in a list is fixed, it will make no difference, but if the list is dynamic, the key will change every time the tree is rebuilt.\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const PlayerList = ({ players }) =>\n  players\n    .slice()\n    .sort((player, nextPlayer) => nextPlayer.score - player.score)\n    .map(player => (\n      <li key={player.username} class={player.isAlive ? \"alive\" : \"dead\"}>\n        <PlayerProfile {...player} />\n      </li>\n    ))\n```\n\n#### Top-Level Nodes\n\nKeys are not registered on the top-level node of your view. If you are toggling the top-level view, and you must use keys, wrap them in an unchanging node.\n\n## Links\n\n* [Slack](https://hyperappjs.herokuapp.com)\n* [Twitter](https://twitter.com/hyperappJS)\n* [Examples](https://codepen.io/search/pens/?q=hyperapp)\n* [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\nHyperapp is MIT licensed. See [LICENSE](LICENSE.md).\n","readmeFilename":"README.md","gitHead":"9f334a4a42eb5068de1f245e8bd0507e183a1f4f","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.0","_npmVersion":"5.0.1","_nodeVersion":"7.2.0","_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"dist":{"integrity":"sha512-rEB9S0I4PfkvEDRZAW3rV+PyUcrH4nAt1Hmjy4/LjVcLouMlH3zCuhFYFBw7WD/CvJSWEQGTO9WD5c7y69jHCg==","shasum":"080ca33ecd226041b8399e5533b635ba4c90c34a","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.0.tgz","fileCount":8,"unpackedSize":69259,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcZp43CRA9TVsSAnZWagAAdy8P/1suLchPQVHbilRKfGma\nQUQxbUUtyaqVk7JiGVL1vBE4mgi1Wuu1QLVG6vVTAPGcLvwbsPiiMfVxJ624\nhAK4anX4QTMX2hUMkFJQwFbigAl8ubSuta6TUYazOftsPUu+FGT26J78c44A\ngBsDxt+oaiPYWxUoN5DdY/R0aQcp8I70fwJS4gAS7zDSUu1qJURxW7T1aM3J\nHkJCF9URIgxvgZt1wk8+hTfpKl97Ei9q/yszZ0BO6lbv4g1C+6ofeXST/4D3\n6UhIQ3n3T2NT2LzLNiiu1rwFAwepQUo4er/1z4IB/kZ/PQHsxioG+wfeuUQ5\nV3PwYMbaoJOZqxMDu7oqBwdM4dkJ4VFXLSL78x0Z8T+LFoFDw+VwJwnpF46t\nfoBEO8yzp2VNGTn/m+VhFgRf3TzNIuDmG/LX2bqCe2Ue9JA7s7c0Iq5Y2p7u\n2lP1i+9dVocLl8LedqYVv1AiDxz7kv+Ezgr0xWxrUJ7ZmuNa5TB6E8pAShiE\nvImAZHyQcbtDa5HYJQo0TEoy6ZCpUQNFU9DBDt36hDiIFB14PVMN4UMYTfJ2\nS4XaTwtf6b52lrlx03MvNsSNO/FdN7war+Qu/8n8Oibd90m3zSsu/VGveO0/\n7KmP3Su8Fm4L2ovei3GnV/A9wuMzuhAPxzpvWwunO6kdmaJE9i3oO7l4Dmwn\n4R8b\r\n=vhyv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD35uww4c3ZshNCuGKyfSrxl0QjwpW64ng1rciL61GwLgIhAJ/OTjuhiz529EDqnTzWCuJFsawDQ3zERyfMhl/T3mKE"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.0_1550229047001_0.649381437733797"},"_hasShrinkwrap":false},"2.0.0-alpha.1":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.1","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":["env"],"plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.7.0","jest":"^24.1.0","prettier":"^1.16.4","rollup":"^1.2.2","typescript":"3.3.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# <img height=24 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], duration: 1000 })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => ({ action, duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md).\n","readmeFilename":"README.md","gitHead":"9c892372783574e8d092973ad30719bf1e0090b7","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.1","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-+1bUZxHJIy0kRbfKsURd5YxWHqD3tC0+EvwCNJ8PeaNON3wnA9XzlNxRWg4YM5wBkxev7QmYZhYWycYNmz12GQ==","shasum":"e5e9af6e55c96c244c06aefdec77242af8c6a9cf","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.1.tgz","fileCount":7,"unpackedSize":50153,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbNNTCRA9TVsSAnZWagAAcrwP/inejPHenfFFqKVldF/b\newjdWTcNRn8FmTTlaA9w821Il0xN+eUWug+uoOBT4J+EuLyhV4pRTcGh5QtB\nYsth5HOLMW0G9s9KLN8AI07pr1yRDnIitJ9X1mwB3c74u4m22Qlkzh8fFVYl\nZzGqXn1MwJE5o3zJcdsFjWaXEn5wY6quh4DLsIAh27TodOjm/Qk3OtBZgdNn\nVTQqCBQV/Ji6plYXcjBwd1Mt2/6jEbYWZSoPOO/eQOkxdVOT+leNA82Sp3f6\nMzVHiIPy95bF7L9TOzB836TNdGjfDIhNK28HRWzZb+KWN4qw7/1TgrtDgYJk\ny0okL7T27/zNmWjC+a89/yMrnJ14T5+bqsuagTFA2BIVea8h7K4Hy0qtPV6G\nFTVOVIA3ZsLiIK9nUkGnPjZodUr7tJLO8wvwS+O+crqpuMZ338xdOiWyPuGh\nOud13gLKEW1i5O34fyqrcvcKgNSWgYCyiN/sHiOsiPNMXL40foWqerW3nrA5\nanj4tzcm2l467Vik5EW0QNhIL7YkDkjGHuEiNhS2jXEGbmFoPJZQfTm56mk9\nLjB4tw924EctI+qVe0UX7Zab+uDGj78rbECkUtyRJWnlCpzYhnhnhidzR8JY\n9ughCxp82PRUb/2a8ETKjw0pSpL+BoRjkjLAF6y7irrcndTGoyLV//GfLMjS\nWOnu\r\n=fAlC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDgKYjRqvNP1P93c9cnJ26U/5Qcdw9soCRhENsjgSTPtgIgET+6PqeXhwMoXXewr4d6x4cdbKL8ohZ4SZFaD+u/u3Q="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.1_1550635859066_0.13402508396991508"},"_hasShrinkwrap":false},"2.0.0-alpha.2":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.2","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":["env"],"plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.7.0","jest":"^24.1.0","prettier":"^1.16.4","rollup":"^1.2.2","typescript":"3.3.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# <img height=24 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md).\n","readmeFilename":"README.md","gitHead":"89421ad066c988ce72597720f65873b6dca561bc","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.2","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-2M46T+QlNQ5ChSIyaKoI0YG/efO+Rs7N+3mx1jtQNlEMWqPJI39szfMQ0U5YEN6QjATnH7UemOAroR1dratY3g==","shasum":"529a8e175fbf2e1a12e7d7cc9533bbc290ee0969","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.2.tgz","fileCount":7,"unpackedSize":50151,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbweoCRA9TVsSAnZWagAAIK4P/iTvdnaLuwH5TlX24YCJ\noOv75PbYbfY5wOvc/Y1atPLd5UxjUea9QlkM54O4nV6QHY1GFaozBfz8wQfY\nx6Elh8tGw0TTFDgyysElCoi1AeVogd0PhwbUUc7tPEIYaj1y3a+qyIwi32y6\nkhXFrO4aoitNNAeOqf4vMK73qdsq/6cn+90CPf1xsLgeF0N0Uq2U6wVZv6zc\n9PsvhbBjbDsrMNpdHjU5TiY+fDtQ4B3DkWhRz5hoQUywtUYZPZIdQOk3sUuw\nN6pp/V9ifgJzvjaPeXzzSABcKgPr7LBuCG+FJhGK6cbUghRqz5CKEqTQaenW\nfwJ2XVlTBBFoNCehqltNjSvuoJDbS2zzf/gTUDS1cyH3GabhsJYJFjhiZvq2\nkqZlpLczS8Xv8vB4Tllx7z1NaHHBXkbYVJpla8xLwAlPDIsHDqEod7F/EIqW\n0wjl3pdqi3mlzK5/JIlzlX/BcdZjYyY7xeZ8siGI7A3IeULRo2Xad9IF32yE\nZLkjwqyD4n1m+drDoAKYM6kxQmfZGQtyU4BjBnrT261Pi67DRiCyTdutu+Zz\nZxodVy3M3O9wTEh+lLKLdRHrp8E2MksSH1Dc42Byb/2Hw1lhrVbdurebG056\nYAlHPHVCza1ktd363VZRObeZDFofO+y+n2U6TdMEX+wdJUickO9iq2Q4tqON\nX7yr\r\n=pmtS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLcId4FxOp9pWbS5/wG+cA+2wYM64TTYi2Hm8fGVGmJgIhAO01Z9Buhpln4k2tuA8RlLmPsv2STiX1G5WYfKbSdWr0"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.2_1550780327769_0.21308043434672852"},"_hasShrinkwrap":false},"2.0.0-alpha.3":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.3","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.2.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"9ee9443b2dbe062a01eb217e9fce1ee5dd351bc3","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.3","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-560pYlyTDw+O5RSiF4qeBu3D9ytQfQYJna7qU9x00fgYrnQJSlIHSt0Oa65JTgspCi5grWZYMt8FP8f9aZ4rLQ==","shasum":"ef0f253ecef4dcb0d514d4d00030f70c00ee8d56","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.3.tgz","fileCount":7,"unpackedSize":54436,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcduOsCRA9TVsSAnZWagAAbHcQAJ8JnQQ3L1GLtG+ZkJmy\npwoPLrZwM3Ac2nfFA+vOfw4YdybTR8w56TEwPyotAwu/bCJ1aRlrzzeBj1Ta\n+aLQ8rjq+pUhQd14TSomIC/f0aK+vhfs7Da0+JnPkmQZQpQYYkyRoYm+9Hua\n6zBqTfiDR0bG1fzVSVRmfX+jZ3D+e8fcxuVscx4ddEvwaIU/isyZLZ8eZQF6\nr6TDYzwGHrTVFLeuXCpu2LetNgyMSIFya5glIEOE+biLKlFliNOThQUQAwQx\nBPlmIZL5rcsiizlblMPqSbnQ9+J2C1INVjMz6cA1P+K0455oeAB+LO3h4/Zh\nbdELC8tF1RXDu85Jm9GffiDYksPaiLunhLGNXSx1DN6eBbQaTOqbjXOnEgBt\n3g35DjtEo5aLPec5PdDm7teweGglobXqoc4DBpfvSQXAkZ2WyVsP88jkRUQR\ng/r667e4Wz6H2UPzG/mZXeEhHp9o8Q8vKsyvonNsOv5ZTWcUoRepIhpL8lLP\n9ne3E4MFBsR0SvSpLGuX+muw8+5oCrhhVNuo3Xj0dtZLh8UXVLKg0n1Qk8GP\nPhAapRu0tDnk4evSOO5zb76M2y0BV6JQoVTblUtwyaZDklDDgxJ0Jn2F1X0E\nzF+hZqit0TEEhcXTd1/s7mgugvnNzvmc5JaVJuCr9g/vPeecM3TjvT4mow1g\nOzcw\r\n=JsCC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDdifHCfGqOE+2ASNkBBtONHE3sMlHl3Rz0h+tSXUzRNQIhAKc9dnIJCoK+r4+W7BBnpyc22X04crSCgHkxJQ8YItpA"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.3_1551295403851_0.3391712216134688"},"_hasShrinkwrap":false},"2.0.0-alpha.4":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.4","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.2.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"801d529c1e2e8d0e5c3820e95e43c59c6f23f62d","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.4","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-RCik375UGMLK+xchXsj43cE5Q1i21XuYAHOOOb11Q65SDd+T4EX1XOeJs84zp6yhteG/CqGM6bK9GcxMelaMiQ==","shasum":"a18ebbfba3e12c37ed0f8fa42bfb4ed3416e5964","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.4.tgz","fileCount":7,"unpackedSize":54547,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcd4nKCRA9TVsSAnZWagAAB3gP/2j4ZyaQog2SLBQhtQ3n\nv2LZrC4wnk0iMitadRs8iq30FVGxNxaAfMNqBu5TLdWqh+iHF4+0/RD1aBkW\nZz0m2pAXtWihhmIogxVKB3jSKmvQeHPpMIP8QmYTi+7SUXHYSCGVM92UAx2h\n56CfNJv6WA1M1GghOaRl28ekJt9XUO6AI2cmxWYi+hQixV0pO/smT/R4TVzA\n0zQ9+vNfx1Uxz7cTcanQuriVKYuCszwY7A/knBkYhzG+kya1FJdGWO/1ACiT\n61BObG6YpeTmWTcLOnVqG6VnRLjqEtSkJigNSj8Pu4Ifpw3ZK3HeJH1l32qe\n9NyY1x1aLB9Eif+cKTXR+AiCK8s2L2/n/8811z3dqvHUZwaxZJHdCuKRVXfW\n0o0jbJa2ydrFX50AvGfLPwkZ8Mit4bCD6TNZp8ei3rzp3uQpA6A9AojCnzhX\nwn6SqGc3OOVbLzYcbuMM0AeOQUalRQP8VIJ+IFFU12kQX6tC5wnGd7unS50l\nGTDrTGPdiiCQm7PG52zob8NZaHgq1FpRlNAH+Bw5/oXKmAQV3gUaTNpYyrTK\niUo+mPan9BDvqvLs2q53ruwweUGRJ2n+UWD64XwWjsr5O4cxStrwyfwh6jgi\niRemyDZLdw0isJ/PyBpgtwnJPNo71o5cwVvTCQ23HEZKS1WZjynUMHIX3cNx\nZzE/\r\n=ruDi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDGbLKFE0qGtas2iQToT00B6amPTiLH5sG9LMd7CW9kpAIgCq2MpU7Q5t4sMgGbJ8EJB+SxKvR6K4hLHPmN/j+M/Cg="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.4_1551337930069_0.2854971971330469"},"_hasShrinkwrap":false},"2.0.0-alpha.5":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.5","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.2.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"5e9acea70bc09e653e54102bf6ef0e6e3ad46542","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.5","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-oX4JwOjPNRMc8jisUy+vFfoBsijwidqC3LyBVQNFdK6mSKz0o2u3xLTR2tYlKgD6Pf7HPDs3OT7I4zreow8Kbg==","shasum":"60c6f07705fc80ea61ec7386bc8386090b5e0986","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.5.tgz","fileCount":7,"unpackedSize":54939,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcd4thCRA9TVsSAnZWagAADaMQAJzZRXHXKE8j+/3lZe24\nZicW9NDXeM7aXwnir5qLPuIDxl72eLyrCgYBX19HJDgDwWNpzJ+CxRomlIZ1\nHr9V1Vl4g4khSA4UvSS8OP32vEEDJ0VNVR8xNXtngHhTOFjZCOY2FTHSKKgb\nTJycRpLvYNTCwMy9dNEZQSaBlvW/R9SRpTl9ZyXQCYoXhyLISrk/IDRYIl9H\nU+GalPQt03LBHYmsH0UIb/eKia6ZegORH6fde3/qRYiAdXCoAvnmttmo/JkE\naQiHqBFypHz3hIji7aw2vCC4XLnBt2rQ7YSAS1yyPhlJWQQy+BGJvkZOENTW\nLns1hWg+caxFVHlOkm3j3C6ujBwsdNK7/AcWTG4PLwvDlCQYtdNQhxF6VfRH\n538qDDbmxTXQzeFZTq9uL+RTHe/89750IsHmbgmCPorI1bOpJMAs5haM5od4\nQqlIyZffHNgtzP8TlZ56/35HN+KskLrMe27/WAZW9aVxAXrwUBcCg5Jp8hxA\nM+fLkDrTJ6l/gKXBFtGZA+IpTXfmsjbx+BaaUPnRD8tEimX+DxTFPDTuAB6Y\ndai6D20AEVM3/H53EBd2nh4x8/S0jPamQeW601dWvVFznpqwaiJoHYEkqXvw\nt3DdgQt8xOFv2ZMMXNsxsJlSFWYNaXb16KMCBQol3DP4aiC5o30WLZKNQOBd\n28nx\r\n=QstN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDgg6XA0387BR4vYr1nEwjx8jrUje57cGsw1EP0QqgfLQIgKd0EJQD1iYPSZesAfdBHBEp7qTpmqz2msxf+9lEAqDU="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.5_1551338336817_0.8622193131760296"},"_hasShrinkwrap":false},"2.0.0-alpha.6":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.6","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.2.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"227f2818b234447c008ba657109869df9359c442","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.6","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-61yPKWDW/gvl2YgPGR47zm7REg+/wEzmYdIwg7cjJNSG3lN7F9zKF7Ssm9eNZZTiDsFa6lJfo8AbEiugpUhtZg==","shasum":"471e242d88fddec5e658e450b2ceebf4a29d97a1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.6.tgz","fileCount":7,"unpackedSize":54952,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcd/S6CRA9TVsSAnZWagAAdvMP/0IFGootoWdut6zaA7RG\nDPsnJPb1M2suppOeR2KfpiVoZYDQ4TGHjk+f3dxodxwvj1gQTPTB/g8nowG3\nOcNQy/1nA8gPMjDvzDCQUym/kb0/kFLdIHZFnTyzTGIRvXXQ2X+CMTob8A93\nvaowkU7SfZqsI2LE/jZveMGROROOPn2p4F5uSfX6TuwLZcVo2cS153LexfLw\nK1ANfJHd1FqO7dYoDT6oPIKyqnPtt8FMnF5N2KnmXAZFfXItLGqRekv6z2c9\nXf0ZhdG/5LWhMsWandTx2aW175eq6zFwwGdf4nxS70IwFxzEBdiSlFDCPEdR\n+VI+5aMXvQRTYKlzitqs7xmcjEKWcA9LGSw2hmjsBszoqEccPPFf3CKhmFOQ\n8nloKn1DrxQh6gaAe4TsSPuxYgdiphHEMChn0Y5yW1JNyBxZwtAySy+KaRWF\n7bijE/pIrmkxxGd+ufP1xNHp1PNlpwt+HszfWKKYv+5aHMbiJLzZa6ROj5rJ\nEwlD5S1MvGrWfFf5aa2BrWLOCy8UI9uaxLHfcPkmrAVEdGalDqKTDrBaALcd\n73YCQ/e/OXm2zLTU2IJFPFaDbwJ1ZNMh8U5hGSA0lxX9Ku5NxY5DVBpr/1ji\npKt6JuBDsLb31KQUUfxDkbSNgbjVByy3y3a1GdJ8GOukoaveGaJ7uEaqgwcD\noQAx\r\n=JxFb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA/lMzUm+GMk6sGB6Kf6YUeKmENSlUabpFkXAB/g0O0fAiEAjae0weK8BJFa/zc/C+9nbxxGJj84l5FmFgYIV5KbVqY="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.6_1551365306177_0.30081809869784437"},"_hasShrinkwrap":false},"2.0.0-alpha.7":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.7","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.2.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"47c55aef20aaf381c6945251afd72b056788971c","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.7","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-ciZhZ83ACFRPFo7psN4s94ZCg8VZBWS9srfdx+uhWvJTiJYjGVWz9I7GUG9qaogIZGQ+XiaAuHEUI3OZu3qcwg==","shasum":"2ba1caf446850f525eea4915c063f06f8233ae3a","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.7.tgz","fileCount":7,"unpackedSize":55099,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJce7xaCRA9TVsSAnZWagAAc9gP/1uIfubakKzsifUFqF3E\nAWPQAY2HddYpFRoSH3P3Y6r1MTiLNkQdG2rLPLXJTLxavQXYxk9GqDJPx5Pr\nUnQZxE4rgL6yq4Hnli2acvwkIbxss7LVr16vvP2QSF9yYaISZKzLw3tl0I9f\njeCRQCZZJvaFBwOvfG0I7ucnuScW1jzV/e8nsQYBrf5JezybSy0tB+vN4GpJ\nzW466a1hVpaYpeicxRgx5Q2eGr3BsPvW+XQ+cjXmUbCuhpQJo/7z5UC0kFUz\n6QZCqcaNmD2/2ABaDeSaAhvoV0YnirtYo6Xrd4D8SGqF8CFSndQDDxO7qBvr\nZeaom+k/Op4il7Oh6HVv/BbrbTyL6tKsrUzkxxTxjonazz5fVvGMmWVst0IO\nNOX5vLfDFYL40PyFtUfWMh6BAoJV/7g1g8wJ3z/qOB6T8OlnNAkdYfIxdGLn\nICD4CFp70lXnfENgibdvxlEvVtANaxktuq+se5Ft2OStlkGIakTgT7wVdbtU\nc58iNMhNWgilP1b9y8nyGy6VWLPu5X24Wu0W5pZlsVQHjBBaMBUDHnA0nxv6\nhFhH2QTcc2dI/ZSn/QHiHrXZCAZzSHgUfjAKpt7L1vlRTx0ZMEfFWYnoAH+Y\n7sldP+KrInAm4u8vFtNkWo1u3UPodlHF/g7SxZZXsbjjnsf7v7oVLqbTfVyb\nu9Hv\r\n=M5Gh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/42rOPOz1a7pmFqoJ8kn/2K1wMBBghKTOXqMkV1WlEAIgAKUXJ2Pbp/L0OTe6V6AwrCMoZ1wH17mW5hNROkMxSvo="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.7_1551613017967_0.8644814204279279"},"_hasShrinkwrap":false},"2.0.0-alpha.8":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.8","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/hyperapp/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.2.3","terser":"^3.16.1"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"23b16195958aaac9a6108faa589aaa2dbff04669","bugs":{"url":"https://github.com/hyperapp/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.8","_nodeVersion":"11.10.0","_npmVersion":"6.8.0","dist":{"integrity":"sha512-gchND/z8cim9/knSm3vjEVFoPVzzTE4WoSWKPujWHElHcFzMzimxfyxK0VTV6Tq6Sg2tTUGhI3er7BESMreh5A==","shasum":"11bf83aba553b59f83168442698c1e2cc1183ece","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.8.tgz","fileCount":7,"unpackedSize":50449,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcfB1mCRA9TVsSAnZWagAAjqYQAILFIBs75L5F4cqluh3Q\nlCB4vVDZIKLENwQaH+AppBt7/Ara7/nPsP29zPbG2yZtAe6eqtPapIPHmPgi\nS1eHhdyNoK6dGZ0XbpE2ObBA3Om1qIQ7D9lh64LKQwJxe7hPLwKYzBfukf6N\n/qnKeOhSVFQYaboQHtUQejFiFjfttb1+uoQL81cmfQN9cxK+L3UXjaKSlHlx\nMiEeCtA/UacNNeM9WJ0FB+/nG4Rs54nKaYM4n7zQ6Dk3OsBsYjUKBh+lGtvC\nTiOHdx/wgCg7v22vcpE7/wiirmaxXFLforZmYHGkv/2rRv4QrucJsNGmshBk\ne7/7BCtudibIrPxFjmpWDBoSlhAhASEbREBr/efMeVuG/8xbHhlRRapT1DLC\ns0LhZXHC1mjwS1Vv6Y6fLvdJd+7YZabkK8Qy4Zuc795ovSrTt7730Euubbx5\nYPDshBO3P5xpI7Jj/3OR/g881tReG+Q1FMwtUEttEWkUGLa8EYgfi+L9WeuO\nO5UTcQ7Z6qvSTP4IH8pv24b6H8o4vFgj9FcpC+M/PQ8ZXSjT2cAMZTV/IoYk\nltsp7teiRi1+0nEFh3UaLg16+4DfHzpP9XKCl3R+pkBCM8P1QokBJApTOFf8\nzZplEZ1kueefhY3I9vCJUqOlRLLhaCQH1Pb+naLd4PB7rivSM54XKsoDTomh\nDeEW\r\n=jUcZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAOHnzY3nt8B4icxDKTnHz6SKWJvoXamXSvfg8Bv2y7SAiBFw5j2KD2a/CIRWJ3mrjOxg98PleQPT0pS3M9OZlJAgQ=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.8_1551637861929_0.4642507424024034"},"_hasShrinkwrap":false},"2.0.0-alpha.9":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.9","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.6.0","terser":"^3.17.0"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"77c3fda4c0ee43ecee862fcf6d3d5bc024568556","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.9","_nodeVersion":"11.11.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-a2HJ6SR+ygMFcGpeULKO/ShZ+jKVjooK76KfIEtfmcACA2JSpHZsyi38jqEaNpsJeZsyPdlEPYPpzNIL8HnQ8g==","shasum":"f29dbebee2ce0b4db5175af082b68fb62ece19a5","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.9.tgz","fileCount":7,"unpackedSize":44526,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch7LOCRA9TVsSAnZWagAAWtYP+waRN3nSXgaw4qy8A47b\no8Dfbhf6Q9QwxdMtV5x5PtyNAJUBI73KmTwWcJKG6M6WVuARNQmxOQ/jOOYJ\n1EFKzYTI/k1Ve49QNW9Cg1SDUDQl0tJ5tqZeSkf4Lu3BD4Cojy3WXZ1qO8el\n867wEcXQvMa8m/fXwzag9TrW95Dvo36npRcCyzLZn7egmaFs1T/anoCBrdC8\nzK0f5iTDX65nwc3stQIEN6Q9egFDv+Mdng6sbjwkh0Q/9W0NrkjSxrDYHC9V\nfr5C1MG8XVcZ8hZWYKOPr9lj3W981N2IRNd1ny/+4YOJP12nP7y8NIWxqpxP\nPXuRyymxLPBebUxLTFZqUswDEc0xUdFK3q3hxCVAVlWNN0yFyp2kauBcKdId\nQQFdFO68lKqQkR5qUig3/DJ37ccR0n9n8Kv6iNW9cTuqdmUycnF5Y5v8C5ET\n96k33LZW9V5VOQ/WbHHEX7PXQsQfxVcS4nDpXjgmFtZi+jjYjNVnKgCs9Lu+\nJaKWxq29Ew81tyMIOR605fqBNAu/QhgUtNPpVWrIJezDUFc/d9uTpMSN8Rlb\nApVihQ29RMMQsSQDvcdcTxyxCXi2faEX7+9HPoeLu3bnmh+guHkfhody4Dzm\nbC2JFEqzdpvT5YrIVT0XKFLklsWFRqy+diQ+DPizJZxgKRCSy1GbdduBXc+q\n+ES7\r\n=Ufzm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEMCH0AbHmU0ajDFT/QR6qvpeqXQ2vP+XS9bac3cQnwiF4sCIEulwwzVcjRDODdftMQ15vgefcaMvzt2BElI9xWj+2Iv"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.9_1552397006264_0.33940391491372157"},"_hasShrinkwrap":false},"2.0.0-alpha.10":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-alpha.10","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"prettier":"^1.16.4","rollup":"^1.6.0","terser":"^3.17.0"},"prettier":{"semi":false},"readme":"# Hyperapp\n\n<!-- <img height=12 src=https://cdn.rawgit.com/jorgebucaran/f53d2c00bafcf36e84ffd862f0dc2950/raw/882f20c970ff7d61aa04d44b92fc3530fa758bc0/Hyperapp.svg> -->\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web applications.\n\n## Getting Started\n\nThis is our first example to get started. Right off the bat, I'll show you the hard stuff. If you survive this you basically win.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { delay } from \"@hyperapp/time\"\n\nconst changeName = (state, name) => ({ ...state, name })\n\napp({\n  init: [\n    { name: \"Hello\" },\n    delay([changeName, \"World\"], {\n      duration: 1000\n    })\n  ],\n  view: state => <h1>{state.name}</h1>,\n  container: document.body\n})\n```\n\nWhat's that `delay` magic? Glad you asked. Here's a way it can be implemented. Hyperapp ships with effects and subscriptions out of the box, so you don't have to create your own, but like they say: knowledge is power!\n\n```js\n// hyperapp/time.js\nexport const delay = (fx => (action, { duration }) => [\n  fx,\n  { action, duration }\n])((props, dispatch) =>\n  setTimeout(() => dispatch(props.action), props.duration)\n)\n```\n\n## Installation\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp</a>\n</pre>\n\nThen with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nIf you don't want to set up a build environment, you can download Hyperapp from a CDN like [unpkg.com](https://unpkg.com/hyperapp) and it will be globally available through the <samp>window.hyperapp</samp> object. We support all ES5-compliant browsers, including Internet Explorer 10 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n```\n\n## Links\n\n- [Slack](https://hyperappjs.herokuapp.com)\n- [Twitter](https://twitter.com/hyperappJS)\n- [Examples](https://codepen.io/search/pens/?q=hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"f9f922c0affb0a8b80ce8ff382b79e75e93fdc20","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-alpha.10","_nodeVersion":"11.11.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-6/FEusdfbUq3vX+gsvfRS15XHUkgPLqNV5aTs0PJ7PssHCRG/G1LYWd8nkTN24uosEMrbP6ZrmusBAwNu52X+A==","shasum":"db7cd62e3c3c9fb87b8a14111931be5cb5a2237d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-alpha.10.tgz","fileCount":7,"unpackedSize":44475,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciJvbCRA9TVsSAnZWagAAVFAP/j2LP/tfblzrpKdALtLi\nZypaLruz/9yOpH2EfpyhQhaweCF7piusJeag2WIW3KrrlLcESaGX2LAQ0csy\nUxt4lcEoyEvqNUB9GRWL9mX/ItwBs7VOwdEylLSIzG20uM4N4C9QpsKwTgUu\nynMiKSmeZBb5yWr/283vHD7H1q1MXpu+dbZ4DcM4aiGura1Kh26F4zwy9iAG\nT6paIpSqDAx9YKZQg8ngLvR6cfrDne7npAhn51KgKLyEn4n5wdQ7vgfIodw+\ntz1NIYUp8q+u7kC2k7QMbt/lwqgkJkMycRzHo+Dy1uXu5ym5GWs2G/Lco7E5\nezwStr6mFQ1lUe4iSdFMs4w3exd2KdEkBAqkeYSAxxmi/ZCsrcX+voBOFO8s\n1fn5NOv9Pl1D6FIOXsqEd655KDYmx1TANEF8Mp7ow++iwkTAC/jfK1/ufJgP\ns6pB1uTMRsU5iww3Ke1gPnrI7zcdiw/KYxpkj4kCgYp/kDCHXFomXqh7haaJ\nvViLe/iDERedkPxnsVtDrpbNbO5z3bGXCdkgpGhJcB0v+ZUupdb8MXpFYDxx\nEUx8LvsKCOFb81dTG8BUxZ++cvo6UaNl+KsOGtEYKwhMCb3LIz+6SLQNhY02\n2OjEn5YEin1rIHRlPO1Fpif0hiqAySNLGQOvPfYu1uIPPmnkIGBQrh4CudbA\ncXvB\r\n=P6fh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICs7vAG1kGXKzydntPxqEiBz0txOcZJogxLKUUtIoFBZAiEAkDNVs4YTTXeav64tqi3K6c+ex1TtpZYv8+2otG67Wwg="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-alpha.10_1552456667144_0.7030881516336411"},"_hasShrinkwrap":false},"2.0.0-beta.1":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-beta.1","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js --no-esModule -m -f umd -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"devDependencies":{"rollup":"^1.10.1","terser":"^3.17.0"},"gitHead":"70dad04c5f841c6b215b994e206e6f6139b7eb1d","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/hyperapp/hyperapp/master.svg)](https://travis-ci.org/hyperapp/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/hyperapp/hyperapp/master.svg)](https://codecov.io/gh/hyperapp/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Load Hyperapp in a `<script>` tag and it will be available in the global scope through the `hyperapp` object. We support all ES5-compliant browsers out of the box, including IE11 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n<script>\n  const { h, app } = hyperapp\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` inside the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nInside the `<script>` tag we load Hyperapp as a module from a <a href=https://en.wikipedia.org/wiki/Content_delivery_network title=\"Content Delivery Network\">CDN</a>. Don't worry, it works in all evergreen, self-updating desktop and mobile browsers. The application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\n{{TODO}}\n\n<!--\n\nDid the user resize the browser's window? Did the physical orientation of the hosting device change?\n\nWhen our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state. Think of subscriptions as \"virtual DOM meets events\".\n\n-->\n\nWe want to know when something interesting happens outside of our application. We can dispatch an action when the user clicks on a button, or types into a text field, but how do we subscribe to global key presses, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes or server-sent events? Subscriptions allow us to listen for such things using a declarative paradigm.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription? Think of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n\nSimilar to how we use hyperscript to create virtual nodes instead of writing them out by hand, we use a function to create each type of event we want to subscribe to. For time ticks there is [@hyperapp/time], for global mouse and keyboard events there is [@hyperapp/mouse] and [@hyperapp/keyboard]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] got you covered. In this section, we'll walk through concrete examples that show how to use and create your own subscriptions.\n\n### Controlling time\n\n{{TODO}}\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.1","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-qTZZkbHdvLapfStv61sN2fAEn34u+a22UQWDCWkD7SYu0SPClA9Nl6iK0wcXhV8M835w2oNDre6nnHoGIwkq/Q==","shasum":"4c223dce99916ff2f2922220659c449be2fde907","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.1.tgz","fileCount":7,"unpackedSize":90109,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcy39KCRA9TVsSAnZWagAAhu4P/2qSCFANNLADHvmLXib0\nWTvQQXwMTKP2Hva51RcOLbLhSQNdlJkbu0i3giDWFijz+he1z/yXXylM5/95\nnDzHHNvgd+vUW9ap3RSW9hL0c5hpW8qEu5YBw8tMlsVV12JYAUaU64UiHR2N\nZJHgmubs2d6CsL8ol9Ie7d0taMn9zVFlbjjm8Uklq/LdpMBI6qjB6MQOxctg\ntmzuWNAZoQ6WyqMw9Nz5rPG0cFbYRAQwptCmco0VhQjHDxpIQeZ6e4Pzdrps\ngubNLxrn/YbiFv/lypC3SNzSecYlQDTLJ6hV9Ozu8f790MDe2iKp1IvvWx3V\nivxLXEQfDQICPPc/ggHbmMkFVLIFYgq1I7d/LiIpvOmkMH2F9kqLt2Tx2MtH\nN0pLWhRz+ITXipYebhAT9gIrG3/oVC/pzHo/KqxBMAMy67QfPbLpMIjJf4P0\nEdn81hQQwtinB73WeQ9kyzPyP0Eg5dU5Csgn0pqH81KnS8MzFRXtnDh55/e4\n3WKRHIQiwxCxTj/VZg2sQbbDfGcZmlCV64GrwF1wOPliUxIjuGzFuh1kHCx0\nqED9k/QyVUdvI4h9vh6X+ZVMlKu6bSzp4e54AvmAh4P+dvCE6jZ8qnb5Kb7q\nf5EPSq6TQETnXNBoS+Mh4IrdD5wvMe+M4wLdKXZCbT6ZJPJ/kd5WbAiVKOAv\n+IYE\r\n=3WJZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEeAuAXI/DLMQ483cezikq2G9hfllnAITN7o8LdpQs42AiBBXtLfKMRehO1GZuZjWYg+NqID1Ub4KaPp4ZQJXYrH8g=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.1_1556840265762_0.2750504085607832"},"_hasShrinkwrap":false},"2.0.0-beta.2":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-beta.2","main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js --no-esModule -m -f iife -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish","build:time":"npm run bundle:time && npm run minify:time","bundle:time":"rollup -i src/time/index.js -o dist/hyperappTime.js --no-esModule -m -f iife -n hyperappTime","minify:time":"terser dist/hyperappTime.js -o dist/hyperappTime.js -mc --source-map includeSources,url=hyperappTime.js.map"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"2cc5bafb3807cefea7052c8da8369fc9ecd08955","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Load Hyperapp in a `<script>` tag and it will be available in the global scope through the `hyperapp` object. We support all ES5-compliant browsers out of the box, including IE11 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n<script>\n  const { h, app } = hyperapp\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` inside the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nInside the `<script>` tag we load Hyperapp as a module from a <a href=https://en.wikipedia.org/wiki/Content_delivery_network title=\"Content Delivery Network\">CDN</a>. Don't worry, it works in all evergreen, self-updating desktop and mobile browsers. The application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\n\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.2","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-f+5Z8Z1wznhTUOG9TCI0uXabzU8XG74WV8kVCUUlPI/4+T4jkeIFljNO5P2sf5WMgP+cKeEMpikn2lNSAih6Ng==","shasum":"5848118950e17f782fd3f54330f8c844b8fb3bc6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.2.tgz","fileCount":10,"unpackedSize":91232,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJczbfICRA9TVsSAnZWagAAfVgP/1IemGQK22izWpiICqnC\nRJIN6FeiZL+wfgdp7xiHrrNLJbf6cRcjn3mifr4syCJg8KAhmPR34zpO6OqH\nNsa2D6giO9CZbopbLZseoCdRqLKUSPQwFm6aufyw3VvVNRcucAptwsM1kyWH\nnkabP9xJEMG6J2+GUBjWZnHPiz24QjFIzFcbCTDepcRp6iIezLfGntjmMod3\nEp3d1gntY7Mhk9vyLM2gJR1u37f/vS7ydnPv3WowCJQb/vL8o5L9UZiM0xhU\nJWm0L/9WbxUC+TcyZsp51PEkdsptkyuZt14osH9sfcG2wzyBoY8PV99+Ehwx\nwJfU+Eosb8B2sdgDWCIx6daqa1F/jf1Sj+rxhf2bDFyJxn/6lvvE4jh1z3dq\nJz+tIKc1mwWuawou45UGag6nluLMbvqKFbbLRc5EOZtHASVZwjPcOQurVu07\nF3h6HDCZbgDAjQvtIAcmeP8kqwwNEBNWws6+AHMme2HaB8EgyRZ/Y74Zwz7X\nvyQq5p2G5OI600y3qvfxpV4xQ3jxI7hYpEG+TVThtL3rIYvXOj3ExOyDpbzM\ne51LNb/vwE9zB0MRauBwChYnvhwLTLDP6g1zNSUNxNYuk8fybsA/MdQic60d\nau6sacJ5Xd2Q/iStS/juQL6smHyWg0GwYWwfumgsePMoqahR13wtV9irz2Su\nMXiY\r\n=59S9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB9ZWoe2uONBMQp1yI2rAPakSaRKspJ/Yq569ji4ojJUAiBMprqGhFMnrVAaT77M+6fhrZCY3Dt6DneO0ICHGBhOPw=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.2_1556985799857_0.466350818936103"},"_hasShrinkwrap":false},"2.0.0-beta.3":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-beta.3","main":"src/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js --no-esModule -m -f iife -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish","build:time":"npm run bundle:time && npm run minify:time","bundle:time":"rollup -i src/time/index.js -o dist/hyperappTime.js --no-esModule -m -f iife -n hyperappTime","minify:time":"terser dist/hyperappTime.js -o dist/hyperappTime.js -mc --source-map includeSources,url=hyperappTime.js.map"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"8ad45998873044e6e829e4b2060c67c2fe6bfc2c","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Load Hyperapp in a `<script>` tag and it will be available in the global scope through the `hyperapp` object. We support all ES5-compliant browsers out of the box, including IE11 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n<script>\n  const { h, app } = hyperapp\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` inside the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nInside the `<script>` tag we load Hyperapp as a module from a <a href=https://en.wikipedia.org/wiki/Content_delivery_network title=\"Content Delivery Network\">CDN</a>. Don't worry, it works in all evergreen, self-updating desktop and mobile browsers. The application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\n\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.3","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-kLMANVjuRMOkopl2eer/CQ40iL3JKz1f0JoebH25mvgURE0syF9Udxb67cjTpnsVMxFaoIFnDaj7cwGe5Zshgg==","shasum":"a2afbbcafabd988ad27baa9303be8a9e003881a4","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.3.tgz","fileCount":10,"unpackedSize":91235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJczbleCRA9TVsSAnZWagAAPj0QAIJc++UA7SGHgC7ixzRT\nXitOpEUdZHQJ084SlFW1hI226wuKlG5pyTFQMyCDE4JeMYhWnBpa6uUfjh0I\ng9MZjZenZ8zBgF8jWNJGQZ1ElFLGEuvVKt9L2hKLSMFf4iy5RztwmIsuuTy5\n6aF6iNCrnbOLEF9ggU5uEcm0Bj3QkKCzM8fD/BJ615bHMQ4r8l43ztHmb3H/\nomonK1muoeKGSy9CRYdD5QlDrNI8TErX8o6F3B36xpPQZcmUZV27A98nrWyw\n+nypz7HMV/NZK8EAGFJ3kwIyQ80bi5h2YyluTQSsdiCjShmOUHyQaYuLBUhZ\nPZVpUmpx+IGmwhzae+4moj90DYRjc1+M4OenR+xfIpBOSebVr9aK11ln2sxu\nxnty2mcNqKvYEiG1BDxWJjSCTQxzgEL6VLGl54KmMLvzkwKLh0Dzn1ShzsbJ\nh09xubyUxZgwb72XLiSbhvnLXstDAkDUieB/owMPtNsqonBF4ry0o9MikJm/\nvIjS79oIAI+N3v5VecLUOyzgntfRG6z7wffn8dEADbvEBSJ/XpY1IVaYr4DW\nSsxFWepRSy02//6LWMNRiG+QQxBr9ytr/zoP7kKgs9BMsDQd7LdjcFjRfFpW\ndx50ClvX65//e438R1H2IkMeqrNfZU0f4kaVFCs3ikstZDnf4vdA4pgqvpad\nBTEb\r\n=/I7q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8n/R7yoJwkjsphbNuRvljJSzrfDeDvuBxZQscdpAkKQIhAIZM3t8SC+j0+kqy84+oIhxT2/8lRdCvC49Rb8wP3GfF"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.3_1556986205769_0.7847250537481487"},"_hasShrinkwrap":false},"2.0.0-beta.4":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-beta.4","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js --no-esModule -m -f iife -n hyperapp","minify":"terser dist/hyperapp.js -o dist/hyperapp.js -mc --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish","build:time":"npm run bundle:time && npm run minify:time","bundle:time":"rollup -i src/time/index.js -o dist/hyperappTime.js --no-esModule -m -f iife -n hyperappTime","minify:time":"terser dist/hyperappTime.js -o dist/hyperappTime.js -mc --source-map includeSources,url=hyperappTime.js.map"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"dc80a18274930a706517a77e88aac0fc86934340","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Load Hyperapp in a `<script>` tag and it will be available in the global scope through the `hyperapp` object. We support all ES5-compliant browsers out of the box, including IE11 and above.\n\n```html\n<script src=\"https://unpkg.com/hyperapp\"></script>\n<script>\n  const { h, app } = hyperapp\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` inside the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nInside the `<script>` tag we load Hyperapp as a module from a <a href=https://en.wikipedia.org/wiki/Content_delivery_network title=\"Content Delivery Network\">CDN</a>. Don't worry, it works in all evergreen, self-updating desktop and mobile browsers. The application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\n\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.4","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-fCPfO1XJ2NQpH/Q0egUzHWyK+yf/ngaMQ/O67EcwMV/2OqUOlydwsGpJGGgKrvyauMiNdxIe1mY++Ea3YfYCGA==","shasum":"9a281745ba68bbca15ef2e38628a6d64d98aeae8","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.4.tgz","fileCount":10,"unpackedSize":91236,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJczbmuCRA9TVsSAnZWagAAs+kP/2V0MKLcd4QWPlxPYIeL\nIizrZ0yFfgkVY5v7i7MccuiHv5Dkr5SjQlPhX8WbA5928n9MSgxqMPISSwMH\nG7gykDXwtls5RNhV3hmfFjh6Y8BXJxv/J/Kv8s6YKPiT7x4Lz7uzQ6x5zW7d\n8S37tJVwVWWzrqG59eq+g1Q0WFJS2XxQxLv+0T0KX98wnrQCK/1QWl60iJ9Y\n1l3BuV2BeaZCf0O0XnhVgsIDdqCHfynay6kWVQLlKOZaxbISNQsDqHjZRYtZ\n3AA84xFt7rG6HLKs6jsQSMAa0ovoukMxHu9Pzd1Y46LQjsEePzXr6UhAzuq9\nL6bQs9THlqwTL61SaL17q4sSvCv+WqJha49eEbKYHGacl2+xII8hZBYz573I\nxDKjpfpjSMg8x2IS7br+tJA9hrtVp9N6nr2NfDUB0pHp4gkMA1RAPBmS/9rp\nytt9Fsl/hEfeZPz2c9ibnFy3eG4zMtvHy7kzUltnyrskNlZ5UrOxZdD6SVOb\n3/Z+UyBXlvlg+ET9NiFgYYoRSGs73n5aKOVulSXc1ir2Tvvh5P22zdckkk8K\njZljGAXnv2jiviv6duDlQ0GAAaQ5UtcQNaleuQwDtEh+XEjE/DzcBirqrMk7\n8AzqlyOAwhXSQ8RM0GVrKs94jC7kWut/MS7JJVhzcTeBCFYkK0l7nsmuWGrp\nzet1\r\n=ueGj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFBp5UvxiMzuABo/2YqLfUijhTm2mA0Yo233v8fLYzK4AiBdOsjtfxVOyK4hoM+a5Ctn0euxcUJ7t0Gy7AiIk3fpVQ=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.4_1556986285921_0.38711228400080167"},"_hasShrinkwrap":false},"2.0.0-beta.5":{"name":"hyperapp","description":"JavaScript micro-framework for building web applications.","version":"2.0.0-beta.5","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"tag":"node -p \"s=require('./${pkg:+pkg/$pkg/}package'),s.name+'@'+s.version\"","test":"exit 0","build":"export dir=${pkg:+pkg/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","prepare":"npm run build","foo":"npm publish ${pkg:+@hyperapp/$pkg}","release":"msg=$(npm run -s tag); git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags && npm publish ${pkg:+@hyperapp/$pkg}"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"fc2974035483da46d44dd46f18ee5443ea741067","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.5","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-/oYbjlzSFWSAcEYdyUq3iHn827kRMi0oSGGuYVCCkAcQvi5e7E5T/dUwaq3kWW3Q6urQLiXRwDttT7QnDO2fOw==","shasum":"7099a70e778dc6d7bfa22a4df3105bc29d1263a3","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.5.tgz","fileCount":6,"unpackedSize":87186,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0IYqCRA9TVsSAnZWagAASlIP/i9/GSTojwqRx9S+9Wns\nUF+b+R6/0xUP/Z0xiqBoVWzex/CTbjvFU1+DeNujuxLdXLPSq1xqcnNnpR2s\nU6mXXHB3UZCQQwtwOYS9eA4CHduHXwj27Uo0PufXaX43HEqd8vbV21q82mDM\n+mfzZ6oIleZHQNDtAhguKZOvZ7m3xBKXVJw7qENc5QwX09ZeEXg1KBbGwy5s\npqkZzT8owfN9skfVLehiSsLO2GNMrl7NSsKr86Pzoc07oF3jmIKeT6DKpetn\ncIg//F7ojdv1Ja8Ux1wSQtmiGYZfEjKP7HTW/Mitlvr59cyoAZoaO9bUZhVE\ntZSlVd9I8K8yRXVz45woQUANdKRqQn6IHv9lA+1FUKgIzPE8z1js0UyPhll/\nEhKW5e2cMqC01T1fZ5hrbZ8RsV0zWzt5KCIIietVW3QGuRGQeO1QWmgHqK7q\nJOXhoK81deIe1doeOJnJIDtlvOa2sqJc0CYKcXkEyvhpEBEMMpI+pLxNkExc\nYr/AU2HMzhhsiOjOcs2mPWGDSR3vPm/MXft5OPCHKeJR+xXLE1CeBuKXTMBN\nPe6H0cKCKzJV+LjOnWWU5m0GxB3NygOhf7xRPPQaBPPthmG/8GMmir8vlI6g\nV+nP4+nTmu7Hjvv6hXe8HqRFFg30S5aqAKDiKAX/KRd7+YuA59cvsqerpt+3\nSHgU\r\n=S/wS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGg01sAOg2+i+EKS6UdURHf2PrJYFwd8zG2QG2ZUb9xuAiEAhgmNzYPkxG+HqQZyFg+vkgi3p6NEDTYaTQbYQ54OWyk="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.5_1557169705547_0.8937305052835232"},"_hasShrinkwrap":false},"2.0.0-beta.6":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.6","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"tag":"node -p \"s=require('./${pkg:+pkg/$pkg/}package'),s.name+'@'+s.version\"","test":"exit 0","build":"export dir=${pkg:+pkg/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","prepare":"npm run build","release":"msg=$(npm run -s tag); git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags && npm publish ${pkg:+@hyperapp/$pkg}"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"13c7058a58423bd323bb9d727ba5431bfb1d8374","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.6","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-vq454BrtyRIYjB9BHjIgXf8rBV4pWjiRDiIxfBBttAYWefYgF2u6ZJVhBCBBTe3/4dR9xMT6EmJ1oRMjWTrc8A==","shasum":"0d807a5dfda46ef96a5c0e9623ef070c742d57c6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.6.tgz","fileCount":7,"unpackedSize":89026,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0If0CRA9TVsSAnZWagAAEcoP/26UgwPbXBXmz6vk8A7T\nw6sqk9XMaVhXvutwgJqKwOUYdKlskVHW+orrl3V/7+YqSx2a+ja0mL3AI9Lo\nqDHcU6aJtbL31O88CuXxRYSvzowBiwjmspTRJexMbQpHcYN2aKNKynTcy+oH\nuSTHyjwfWylszks2hoyHfZE6sHixQp1VAQixntd8xrkhqbxf/6dbyCKmn7lC\nCx4Wh2AW6pDBMlCRkfokUXlYfUi9ELjlftyxHV82Nvavb8s+F3pZUox1oUBw\nBDjQ0Tmsv4UfuYvAk9zFRqe5tNRtq4n/gEXyFmfGbPXrZviWebJcCO/rABfH\nYYD0Y763BPbFUCedpmqUTX6rUzkpou4pwSXQCeI79HY7M3tSMIlOwfb2eMNT\n8WNaML52Unmrmn8AV66E2zeqNwDOI1IqKPwUp20G3r1Yc2pi/98FhxmmToVO\n9nRc8iLl0q8lAD0211AsE6dHAduuaCap4U76pk9+zrwaNqAlnxwcddx+BfMM\nEnqMRwK2xLlRUY9Q/zym0K0PCd0VyehmVEFdFUy1EXDjyImXKZgT82Dlc67T\n994EnhVEEbpUB2+NsgS5wqfGkzZJv2hImvWGi0ahq8e/4jSNyrfd918bp+gS\noUQEPVu2rwjaFZktSZZahQdNP3qzYCdqg/oG4tcgXz9mQ1uz8NjTIluUkXgB\n8kHw\r\n=wcED\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHpRu7h1FQwa9sEaXTeuY7KGFZUUMuICGsdy01pmYErgIgIw/DkPLAjWJ909q3jWa3UwTMmP8+ZVpHFAGOglLigV8="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.6_1557170163664_0.01083871193072894"},"_hasShrinkwrap":false},"2.0.0-beta.7":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.7","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","update":"git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run update && npm publish ${pkg:+@npm_package_module/$pkg}","message":"echo ${pkg:+@npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")","prepare":"npm run build"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"431747cd0e4af2223316b2bc2c780f990e2f56c6","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.7","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-E8MQcqdKL2VtC+go2VWtGm32W7N96mLU0vhD+TbQZ8eEgqnNBJaxlQ+FTvvv2q5rQo51y+zdzopg+wA0c7IlRg==","shasum":"5ee16af1055d4678a059623e98e369b6dad4d665","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.7.tgz","fileCount":7,"unpackedSize":89103,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0VstCRA9TVsSAnZWagAAX+QP/0V6PsECukM5i+KvjCBk\nt7544iwmBJOOQFPLU9SlKXlBLjvEPczBw5Wbv2MyeK+3U05q8N9hDCJ4JN9N\ncSzz/v231Hjofw24ft0/kSV0jOWAiruEuqYQi2oH6ckAz8XAMtPe10ulsdB5\n04fw5NnNJfEVfNrJPxpMwWhK+iZDXGZd5gnn+xGqGWDIUyP/cQP3EVdPbzs9\n7fmdUS3EcHCWTZJcRUmRkKOHHvPzSXgPv3Z7iCXLftrQfWorsE2LwXOPuRkb\nW6faS+wI2ljmy1XcmiRmpsDSDBTMB0MV8JPuQ7gbAEfmtkrcdI5jIXtxnyUR\no9v5xLV5eSEtlrdeqQ+uOp1wPO7JZQXkQyjDXUceaBhPdsoDJ7d3Axf6XAdB\nc1SwTRnaSVpH+MFcxGgtxErIJtaqpbMaYQPecbagyf3E9mFmJ7Ew866vCChf\nHjqY+HftHGU3+PJQuU+BFMMTXX73zuxtZKzoGIDnOq2/GCMzTsK45kgbWYot\nsFQ3KjwtwXfhfaDqzVJHvzqvPDianJiuQeHB7/RlpClI3jilyenCXO2FlJiy\nZFSeeMlATzSE9ditIrTK2UowJUdKzXWEB9roFfLHWINqu5YLNqD3ItDgOnxY\nMnS5tTDCUGus4HMYufXk10P+0Xp1SaMKdJDwshGGQYD6XV12QlCzVk1tKe4G\ndz5e\r\n=4dsx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDp4MNg1s8lA1IeVC/ofHfAC36vNU79wMF6JXlw1w4dsAIgTW0O9JVmvA5PwHsMPxMd3oFNUv8PQXhz22BBw1ldX6A="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.7_1557224237041_0.3364661588744895"},"_hasShrinkwrap":false},"2.0.0-beta.8":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.8","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","update":"git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run update && npm publish ${pkg:+$npm_package_module/$pkg}","message":"echo ${pkg:+$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")","prepare":"npm run build"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"5c38521643385a973cf9bdf14187af747fded478","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.8","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-hKKaIUyQQ63IRoRm68SK3ri5zfRYwyJ2PvJF4eXi3MymWZGZIp1o7Iyb4RS7nJzya1bSh5/eoYxol6B85p31bg==","shasum":"06deb7dee0d1ce4a15728ab460e9eb07277a9738","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.8.tgz","fileCount":7,"unpackedSize":89103,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0V26CRA9TVsSAnZWagAAUBIP/1pa3GJzA1xrBH7ZJ6xz\nD3xFc7UI3KXTirK9oupHh7/sl8/AKuk0XnlolDd764U5oezkxvDpDB2FrFAY\nNOYVL5E0/mAGY5B8UszG+lgYbtF5U0Uf6FeSpJp11qJTG+kSOssLgkE6sVFX\ngNblFbv6lFEVPxlYVyd+H/EtB52PanKdtyHQxL8mYBROI28mASaTFgrZKVS8\nPE6F5CMgoN2xNx7GZI/F/zefqhzsGtnR266HNtKZBwXQmvC/oTGH7lmQxZJP\niJ5iku3Y2tJWDwM4tCX09OZZrBQ5jzsMq0w4wv064PeCB3F6j+DLnKEgtRO8\nlYJX2Ga7QTQ4h/QVPbDcaZh3Ew2sHoX+DpOj/rmylfbb6Vz8CvEyy6f8gyNc\nDOmuv2j3kPY+RaeTw6y4fGDbrb7HBx4qvwxdeFYsK/B4Q2HkwAHdpEcqX4nN\nJQG/B+WDD4wwO/7l0Rfe0TJpsqtZzB9NuPky2ZEsFgIz+mTyyqFzJpvHfe7v\nlx196VLX9HHIuB5Hcopcq2pJWBBkqLO1CqHcxWMLBMVwsVSsmsHZrqXfm3/m\nLL5rzgS+pLp4ZasLe4FNAdpBhxNdqr+F3OJ6ImWF9AC1mLc635vV0i+giDFf\nTxwDXeyY9c6o+neXQh3vyFHZDTJwdc+Iekc0NJ/nA3XqFiKJKCx/Kaq78FlB\nnFjC\r\n=6ffu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2rPDWgbvJDaRsrrud/Bj4fZ6rEl0SmNTIvZTbX5XkMgIgP9nRqqSgBLMOsy1eSZyJwVC0CWSLOq+de9DhQEDTpPc="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.8_1557224889910_0.2705032037481694"},"_hasShrinkwrap":false},"2.0.0-beta.9":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.9","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","update":"git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run update && npm publish ${pkg:+@$npm_package_name/$pkg}","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")","prepare":"npm run build"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"30d9b21001b66e3655266ddb7f445184f80d18da","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.9","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-sgKL4C4oYiz81FxnpL/MnatOhdxq/dCrmZ9yheVCBWXyPcR2gGI7oJ5+9Exyh0aLbuxYlWK6su0k9KAfzSCyAA==","shasum":"61a995486ae567f405ed5eccb578c2c58dee0dec","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.9.tgz","fileCount":6,"unpackedSize":87182,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0WC3CRA9TVsSAnZWagAAwB8P/1ar6VrZIKDEeXRWvG1e\nXjBtG+epaarbqC2rdHzBgOYnwDX2rDbyrxM/NvPDSwSQSEFy2HUVhd8+2C7j\n2FkAJHtyQJHkiWu8EzLFRyfyks7kW/WPPDB4kg/A6b2AHYNpfM5BehP+Pkyk\nDFP8dh+JVYuIvlC5WY7xeR87Baqrhs6VOgG52IYZYRRDGtA8LACF4S8FazZy\nzfIqdludSNcgE+6Y+4RviPtFeMeuMwbgZwbxCAFGkS+dPYRHWoLUPQtqTLW8\nlO/adVhfGQZ+0yQoZX255J3E0xOdJ9RCCbnCbzOmEQ35yCMRF5aiGQ2wYXSC\nwuA+mhR5nTRzpm9d3W552DxUNjeZ9XYesLOHxlNrWFL3/G2sblHpnw3zOSI7\nvGutRlTPXNpAdzmyYmcAWodgGqma3nS8Ev6D1xUTCS6wzb51WpPSLVfv3yEV\nLF5FgFXfEHN9SPJR0wm9+4w40wJsAqWe5eaXJrm0RufaBIU5NKpZN9p+BnpY\n6LcxRjxxDX6WYAl8aT2Cz4T9ZCLFnIgYtP4z8zHYh+mHLTH223spKTyVTrLA\nYYoxqy0H/zLa5vwgQQ/gkJGAEtRrRkOj0U18M4YgCiARIzAlDEyzbUertrMd\nSy6NO1MQEX47ptCSHo4XLzeuLBELbgIZSVHovGWeaaDw+nAGivQ7txsNJu3G\noGf5\r\n=tPpM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC8xMg/XBtuMbOPHoXwUwQEt2Bz3DjSDznqqvrKK1SCgAiEAhbJjMG4oqxv//vvJHSZuzE66hsshjotnxLcs75hlaRQ="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.9_1557225654870_0.23264378008872688"},"_hasShrinkwrap":false},"2.0.0-beta.10":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.10","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","update":"git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run update && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")","prepare":"npm run build"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"bd326d9af8f639b4fbcfa78958c613e7640f79bb","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![Codecov](https://img.shields.io/codecov/c/github/jorgebucaran/hyperapp/master.svg)](https://codecov.io/gh/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.10","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-GjHGks4FA9GMdvlKoLH40MCXf7Zla4wWg/y+oLMK76786TyvnT0GVtl1q8v0sHqYwPysQyl0IDmYUgZ/WHEJkA==","shasum":"ba4722b8569867a8f569d7c66e7abbaca416c35c","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.10.tgz","fileCount":6,"unpackedSize":87192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0WK/CRA9TVsSAnZWagAAGnkP/3L8ci0S4IadXUKQJTmB\nYTJVKMFaDhWM/mkOGM9aOdE9nqXEKBRGu5KWldNMmuE8NIAQemrb/7bLULZt\nuyvw4bSlsGUMvJKsEVK030u+yO8VnWl0tDX02H67daEdC4LwtirUAwDQOvCr\nmpZDY62gnuQ6ndsYK8GqbWVzF+/eh2hQ/OtrJIBXKGNeBjKXOPdZEC56E9yu\nNerVsc06Wrc0GWPUj2gXo14cf65s16TB/9dpwfgi58fQl9N1PcVB+Gtgt0RV\n8QJo/PqvIPT5NlqNMP6aD1jOD/KfielMO/Yfa0V10hDh8v+4kihR12/FgZNV\nBvtID3fsy4oed2MbhgD+xshf14UAtmnV6ZwPpwTeVC8nK9+Wx0esDNDfSSwb\ntf5r0jVX0q39o0+AUGgBw9Cj9rdaDW5Bz1dOowBI0Jfg5n+ieQJ5n9+YzqEw\n8z885KJMx0wLimHh24tVte1MhF2Xk2nv+hv1226Xi4zYLGrsqATvF9T0pxw8\nHJ8w3NEi0Vk7SA5X8M7efaijp43Sd2gEGHxeUs3XIdCdSjRqLAaiu0RcdxJT\njolNG/52EoMG7zu6/sTHCpQPl3vqxh8NxZLRYe/i58xwQRLDEfOwactWmaqz\n9y0bgHhxq/6CHK7U36hYSs9EVTG34waDGiIk8BO7OC//LoAbU/FON+yHw0OB\npdz0\r\n=K3VE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmZofPPNdTzcPFJeY0F9229Egmze/zREwgDte+3EBNQAIgQc7a3+hgjaFzyipVZlkhyf/DCgLceSJZ/9hWhI+tu/w="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.10_1557226174356_0.6409403661792894"},"_hasShrinkwrap":false},"2.0.0-beta.11":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.11","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","update":"git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run update && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")","prepare":"npm run build"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"gitHead":"f55bfef3809829ac6a1fe6657b7e7d815502ddd4","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time]\n  - [Mouse and keyboard input]\n  - [Implementing your own subscriptions]\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i <a href=https://www.npmjs.com/package/hyperapp>hyperapp@beta</a>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using the `Math.random` method to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example our of convenience. You can read more about [generating random numbers] using Hyperapp effects later in this guide.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <main>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThis is the last stop of our fundamentals tour. If you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nWe've covered dispatching actions in response to user input, but sometimes we want to react to something happening outside of our application. How do we subscribe to global events, animation frames, clock ticks, or events that aren't a direct result of user activity like location changes? Did the user resize the browser's window? Did the physical orientation of the hosting device change? Subscriptions allow us to listen for such things.\n\nWorking with traditional event emitters requires complicated resource management like adding and removing event listeners, closing connections, clearing intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions are plain objects that describe a connection to an event source. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use a function to create a subscription of the type of event we want to listen to. For time ticks there is [`@hyperapp/time`], for mouse and keyboard events there is [`@hyperapp/mouse`] and [`@hyperapp/keyboard`]. Need to use WebSockets for real-time two-way communication? [`@hyperapp/websocket`] has your back.\n\n### Controlling time\n\n<!--\nThink of subscriptions as \"virtual DOM meets events\". When our application state changes we compare the new and old subscriptions, compute their differences and rewire the underlying connections to match the desired state.\n -->\n\nTo subscribe to clock ticks, we'll import the `tick` function from `@hyperapp/time`.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n```\n\n{{\nSubscriptions are described using arrays. If a new subscription appears in the array, we'll start the subscription. When a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n}}\n\n```jsx\nconst Tick = (state, { time }) => ({ ...state, time })\n\napp({\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ]\n})\n```\n\n{{\nNow let's put it all together. There is a fair amount of code, but do not worry. We'll go through it all!\n}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { tick } from \"@hyperapp/time\"\n\nconst timeToUnits = date => [\n  date.getHours(),\n  date.getMinutes(),\n  date.getSeconds()\n]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, { time }) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <main>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </main>\n  ),\n  subscriptions: () => [\n    tick({\n      action: Tick,\n      interval: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\n{{\nBreak it down.\n\nSubscriptions are a way to think about event streams whose lifecycle is determined by changes in our program state. Similar to how the view function visualizes the current state, the subscriptions function describes a plan of events you wish to subscribe to. In the previous example, we subscribed to clock ticks for all eternity (or until the browser crashed), but we can turn a subscription on or off as easily as we can show or hide an element in our view.\n}}\n\n```jsx\n// Next example that shows how to toggle a sub on/off\n```\n\n### Mouse input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Mouse from \"@hyperapp/mouse\"\n```\n\n### Keyboard input\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport * as Keyboard from \"@hyperapp/keyboard\"\n```\n\n### Implementing your own subscriptions\n\n```jsx\nconst subFx = (props, dispatch) => {}\nexport const Sub = props => [subFx, props]\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <main>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </main>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nconst preventDefault = action => ({ action, preventDefault: true })\n\nconst SubmitForm = () => ({})\n\napp({\n  view: state => (\n    <form onsubmit={preventDefault(SubmitForm)}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.11","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-OXrl4yRH4WQ22xvO5bXVpsr37CcGskFqz6GfaUotsKxZQ0nDimCaKoM3gwEeJZDFhk9RWKX9xeNqs4Me/TSpbQ==","shasum":"5cc05a5b7cdf90819f5200b9886dd9e2d7cc7af1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.11.tgz","fileCount":6,"unpackedSize":87090,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc0Zf0CRA9TVsSAnZWagAA9QMP/3QtL5vFu8IMEHKR6GSr\neglLXYlLGyF0E67CzVttdIPGpiYeKLv5OBvTahz5g3q5b+EsOpt/PfcQcQMv\niAJ7qOY7drdm+ppv+6e+aOKdscDTAB+d59KxokUi1rU4W5OaUxa9nkM/15gq\neHvA+WpIWZSdNOtmufdedCX8g34M8SxgiT1UR7JWmtl4ustlt6J39CggRaA0\nltddZV/VHdFsuy8eWhR6lkH16ACxeOf+1j8Qf9svZGfRBl+9IM1Cb4yJRk6R\nTKSuLkyCBfXkjpYUcn8kVevqT1OzTGCfUx7S6r3HNNdMafn8fLzejuq4O2Ti\nmuxL976x/2w60mn2bPB2bQqK5YJQQVlM8rSTDgUDXK+r5/xXSDGuJmo7RHsE\nkDmNlvpDHxitkRth6o84mnUhL8XLIvo23Aws4Oy4tjJc2yevRlsChDyU9sXN\nOtWEFep27Pxy6cqm5IRCzoXNVP82rxZjpEGg1nGJE7n0bG7yzyJvy3v5GJos\nwz5RqiQBrnhvxC0DSy1vlFR67zF+HIOv5eVuL1CtrhNtS2bxlqWZjlBFsHsU\nyyVabLJKvwGImG2I6/kTojSJ18USRUlp5KIiIF1wOa10Zrul4uLflOYv05sy\nKcy/1AnW5KJZD0oW7ApOG08HIqUQcNQOeok3tMKlJiYNmIL5+VN1AtSfYEia\nR/Fi\r\n=IU7X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG9td0/N2kLRB8lM1ldH13GMhg12Vr0Y4h2CtkSyy/UNAiEAiXroHbI3+aFQUSE4kynzqDUMqyGmJj/OhgMTOVY7EoM="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.11_1557239796189_0.9587829930411682"},"_hasShrinkwrap":false},"2.0.0-beta.12":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.12","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^3.17.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, clean, and tiny foundation.\n- **Declarative**–Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions]()\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM]\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects]\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go. Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you still haven't.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html], [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sounds appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`] for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously], we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if you're goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. these modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. we coulve chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { preventDefault } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [{ ...state, otherStuff }, preventDefault]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"740fafe8fd336fb55ecf5f0f2964d8cc17f09e7e","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.12","_nodeVersion":"12.2.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-2W4w8nB5tStaPfVAj70yvzOMejOJUzZPzic+MWkpK5GNiJlFreKqXsSZjOnc58KeVakFeQ3h6kDajgU/bln2SA==","shasum":"8e52a1b82ba94c82ed4d05217abc4371a5c0c42c","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.12.tgz","fileCount":7,"unpackedSize":91266,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc2x6ZCRA9TVsSAnZWagAABj8P/3YaOdUtCBMJFnAEtOgD\n9myx4Jp2DACpETDY/CJ4APsinyPr3wSER0AYLW3Xn2YqYddVmdikyGMJhYbz\nXzcnPptXHU1bgAPX2JiEklaqFu0d2h66dWsEQeRJI9J7s6MJwKneZR3YCdmr\nh/GjiRvgkK26dauyx/dONiy12zkTyKYBVRHJBA3EiMQMrsC/l/afVnLhXKHY\ng4QwYN/5+LaskAdFmHCj2sd9+N54eplMIFs6dAGgA/398Va6LInD9AR8F6t/\nCqLFOCit+WagvxsBnFrON43xz/8goUcNZqeMZl6uN4fFqeSkIjWWrLV4DY49\np7CfZh9+ZG0tLm/rr1zh7YjfUymwLMNbpG5YRyfKUsgIZ7tZfKzcIZ92Vsit\nBIPkRdQtaIWzS5XK2HtQ3wRFVQlj6QdPpQwEHgAewJZf4Ep4hYrkjc/akBrm\ngjS0/l+/6UegkUytYSNvNWHrkoKvzBUrseI713UUUv5ESdEFXRLBREtphfY8\n76RaSZZrptY+o9yMvGCqT0x4KpLkuO18k1TULJ7oYPXnvS2a7ruonuo+F/iz\n4Sv9XxIy0si4LrZ0U4Vakl2Ip308VKpLvfV6wqMKhuw6DOVMICRhmxwuQ8fl\nAbR9Hm+3KVRMp7kObqrn7X9ZiFfaD5pJkmUKqauZp0JYwTAzIwN82ZFgsnEv\nGp41\r\n=8+4i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTs1d07xWKolrZP+WFhtfydqaOMkqSoqT8hGDpc3odZQIgcV48uwtaSwS/79OmhtwwuCSHEsQlG/0t3/8+Awg5Ed4="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.12_1557864088522_0.980104763761098"},"_hasShrinkwrap":false},"2.0.0-beta.13":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.13","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify && npm run nodeify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","nodeify":"perl -pi -e 's|\\({}\\);|(typeof exports==\"undefined\"?{}:exports);|' ${dir}dist/$pkg.js","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"gitHead":"db3db4b8c49685860be8dabec85b5fb391dd89fd","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, and tiny foundation.\n- **Declarative**—Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go? Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.13","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-om1KzMqlQ6MDZ++lMSE12YzHA0kRgdMB1y5uwoBJX552NxmSYg8oyfetkvHYexV7VTgBYM+g9kINXHUBTTByzg==","shasum":"f9d0bb749764128a97c132ac9cb1e9e841cf5275","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.13.tgz","fileCount":7,"unpackedSize":91704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7CzECRA9TVsSAnZWagAABKoP/2AFBBN3Lbez1X22JlQ7\nj6oeUiPVWMM40n2oBVXMr8f07O5osMu+/xZSWd/qmmslk5iyZX5i8y7TiX99\nqfknRKXgCCWMkGphhF7MXeeDZy5YwWRcwd4ytzdbWDuDSBieJdr8qApuwluz\nNTOFarOPR9TXxu03syeoSpDAo4AjH3SATuwcYWYpXYhKl/ILGig+04OVfxyW\n8zcSDqfMinjHhH0CvEmpitnLkp2vlZ4ldJv1aCcFhcvp6+0C9fY65NdcPhrd\nAIeim7joCCq1AI6L0hLCJmmYKBMFy8nX+K3NKtVNVovvOslpfoRH5qXMTobp\nnvskGK50vadHDKRdiuyacaVi2ulqOHsjVVghbTqBTQaUMiTY0E8nFvhifxRm\n52HtJJD6cwTV2rRmlieNgrLqYrC3dd/R7b6zNBEN6jX0cFmGRZDmlBUCMExI\nRgtShwlPFLMggm1LMy0d+q7IgG/bcSMdi8GebvSjk0S+3vSAzyP+exXZ3ETl\ns1kBENYTd8stP7NZrqS5imRPxu1rc/c5V7Fxyf9O1x67Vn5R8svyPMa7rZWp\nEjlIpW0idiHsCcRvwmq7Ll3Zv5pFrua+y8bW/7S/uJxxQQRFHOzSobB2Ng9U\nA2Y3pIcU7L3he9UzQV9zIqkxRRfw0Ev3kBUa2Ecg6lK6VrkS0JCAAowrODZ2\n1aNp\r\n=vLu1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICgfxMCa2POTv/P2gumNidhVpmUCGO4beS5BHNlp1SqhAiEAwtFJIYRglLUItc+n5OKvX4TMoDDfbo9XglF43SJaqk8="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.13_1558981827213_0.16019417039520145"},"_hasShrinkwrap":false},"2.0.0-beta.14":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.14","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify && npm run nodeify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","nodeify":"for file in ${dir}dist/$pkg.js{,.map}; do perl -pi -e \"s|\\({}\\)|(typeof exports=='undefined'?{}:exports)|\" $file; done","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, and tiny foundation.\n- **Declarative**—Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go? Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"692111d72d2343f431d8c953ad47ae78ac3ae357","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.14","_nodeVersion":"12.2.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-uwZks6fhh1mdQcJKBbEDuQmcd2yKL4WJ2uh3OsZwyIYuC0x413k5UTc6dCoyjHUyFeh0tjMCKvurPbgc4+KI+w==","shasum":"a054d85d5af748457bbe7a155e3a143e1e31ca98","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.14.tgz","fileCount":7,"unpackedSize":91774,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7NkHCRA9TVsSAnZWagAAOZQP/RIm0mTPuksW7mCXUgsc\nSQJhPdsttrNYhc5iRQ7YJjzxAsdVJafpmx23RaTouySDRoJBXiFQQKBZNc7B\nz+v2Cdwa5HfxHojGHpzCck+0xk5sBov7IjShYkHWJSdUS9nO/G0hf75VdAFv\n9Ha9Q8P7VTNj/BZUqHE45PLO0FIgt/9sG36QqjKtW/UvVoaOAHDmEbknk+y+\n88uJsy4+c/5TDFwzsNSExgYcPN1vZiIzMWNKynBWSeI4MNmUYfhSbVionZYX\nG5TuGjjrFekb4slgLzI9c2j1Ja5pptq3mh2NR4YUzfwMYNPIzSzzTrCOZ/Wn\nt1VgO9U3msASZIIlpwQKk2G+KkbEmhEr33pE7mgeKw+jBJ+YbWTOKP6dag9B\nEOPImJx5qucrwmv9pzSqK+YoFILdyfhY/HzdstXsXl7bFqPUNE13BUVvbmbX\nZ8X+BCymQJNoDXemIps7rp16EpABqBg7PEtMuTDJOTkiUqeUTtcVXBWZRkZh\nKs4pmPgUIb507ZLIlLD9krkSlwp/T19J0mMGnQLLE/IN6fk3SKL3c1YeLRU+\nwzO8J+hk3sj4yHth4XIhtKk+Jt4k7W4/YIQAHXZEIrZYYtbkwUkeTDZYkNXp\n7+fNeI3EJ56n1nExl32JfJHuDo4/9mR+LeyzZSMed07xqtalk81HAP7a1Fs1\ne1Tn\r\n=dZag\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBkx4+t1FF7cN9UOPYumlH5htcdke9hiFbAVM18IkdkAAiEA/JonJ3NjJYyJVlzzeGwAg6mRI3FgFFVfNcxZz3/gqeg="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.14_1559025926427_0.2921256402357766"},"_hasShrinkwrap":false},"2.0.0-beta.15":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.15","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify && npm run nodeify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","nodeify":"for file in ${dir}dist/$pkg.js{,.map}; do perl -pi -e \"s,\\({}\\),(this.exports||this),\" $file; done","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, and tiny foundation.\n- **Declarative**—Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go? Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"489272098742450161db216dfc8c60dbb54ef801","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.15","_nodeVersion":"12.2.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-wU03H+FGontatb8y68Ja0otLM66hMjMo8ARVkb2uWIJpf10aSZTyJhmFcqzANJW6qGlUiJNAcfs7rqs8APrHUQ==","shasum":"0a3005bb025872d3992b5908e186f9faa8369a36","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.15.tgz","fileCount":7,"unpackedSize":91701,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7N3VCRA9TVsSAnZWagAALuEP/1chwF5zTa/W4JnEQGZ2\n74wrfeAxipDd7sK7kJGHTJ7XkIXoL11DFWnUQ2ARUj+ALbvJkfccCZoYNDfA\nnjvHaplbPOoWdKs0H2Yv0MVOE1XyttaQNcNaBPw6lRqfn5sGVmhyrpcXVojc\nfdosAIQxtlQHMJXFS8E5pn5Ew8IwZLzzluUyGVpn2XhpViymjt0qHHfuaTwS\n8GjqSmnEvLI9LkWsAzrvFFXsFk9DFCnotxnIWdQbV+vxETrjfLPb1sxRaYYW\nNBKdZNfT79rciD3wIQ0w2xgocMPaC6Zv9gqZGS3dm66Y8mvslg8WQ6/soma4\napUGdRGVJETK5Qmxa5UYLgCApn61sQvVjhl0cCxCVtBQXliB7VGpPbX12/eb\nVRdN0KEBz2Tb5bjMX7obdtB1c7mXQsFDY+cbxs4gbXIMUVqqTwMTCKlcfDCL\n5QFeP1h5pvr1H5ZOKHrMYAQsg+vn+P/4808cbTrlejcotvJovKyTCXH7BqJu\nM/NBAtPuPRQzEcMVGpTjdY6eDstm41/UdCanFzSzei86oPWkyrA65Uldmp62\nKJxJcX2Smja8xukTf/dwthyM6ym17bXsiOhDTcJzIdcZsGfpfXTET1gB4j2d\noF7rtsZkGEgecWYGb8qR4ch9wcPH1HMKZc1euNUjUG84LTpHUArWjLC2sg2M\nnZaI\r\n=KNXl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDBpZjKnBExH0gIqv2k7ZwRK1ImceemQcO2DNOdkoRltwIhANl1+JRC3hx1GEtYxfBaHP3wCKjDREaLQl6lnEi8hA8k"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.15_1559027156656_0.7185541407947946"},"_hasShrinkwrap":false},"2.0.0-beta.16":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.16","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify && npm run nodeify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","nodeify":"for file in ${dir}dist/$pkg.js{,.map}; do perl -pi -e \"s,\\({}\\),(exports),\" $file; done","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, and tiny foundation.\n- **Declarative**—Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go? Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"6faa45f1cebd3fcf27d941e3dd5dc26825bf33d1","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.16","_nodeVersion":"12.2.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-I/CBzn2OqCfyaVtsG6MMfmDbyh30vq3RmIRe7nJhdL298wtQgTVY2egM7Xru1/RN08D6ailqSSK1KDdnMxKN6Q==","shasum":"d759b291962df5383c0a0e4044f42529d933cd59","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.16.tgz","fileCount":7,"unpackedSize":91664,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7N6QCRA9TVsSAnZWagAAU/wP/Rzf0s6QK51F1N8+72cR\n4wpnlr08AyMgaCjtGiXcr0teesuJ5Gg7pAUq+iGNKLY91SYW+6Py0H2XUdPP\n2oPykgRBtysdorUWbvhLcBEAy+WEe1ZN7ClFfCRrvHWS9RuohhypHAGd3T1G\n+gSexwJB+HpznVzrfPCOd7KUOMan/4IXbBurA20O66MfDDfH8f337EN41vtH\nuausvTXIurtZgptAFR41QugMlRgB3jv/cMY02hy1xUUXYcNXfpQP6Eb/I0j1\ndFuR5LDJdeNahbu/7QwIMrjlKj2MvngezOsEsfYwsBDz2jYtXue4w/DV/W6w\nTHOJUNxPIfKAw33Xjh9sTE2CkpEGnc6ZWfE8ZLgaITuu5a4C3IxNGvrzyQxv\n0dd+U0nHlMIaACGBpTwxZqkeFkDg4XZZqPHENto/YHDerAv74G8Aq0KPn24O\ndq8/IONge3PsdglPGdZudiK4eSEQCPYsDs8DdecKxHwtfAycQXjhLxCGxJx+\n6RmjjUnefv0yEHCKV+JYHlCSGqkA4lZvshkl3doz8fGcM3ry7t/AF6tPCMCn\nrzm4eVI2gh7bXj1Sk0J8FNH15lfRqrcUdY3fvSgcOnnfqIlkibKIFkTR1tBy\nILWc9oRFexiCCvQmxwGgx1tTge2yopGmz0XiGYFYG/+zBreMcQsqsaWgn3YQ\n5ya6\r\n=4loc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAlZT0YhACzeGefn7OfDkYUnOMqF9QArCLfM1vMBdE3jAiEA0xskzdzMUG+5LW8eKJrVojY6Sk3W1BCmE7ZrsEQYzxs="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.16_1559027344165_0.052952543626050286"},"_hasShrinkwrap":false},"2.0.0-beta.17":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.17","main":"dist/hyperapp.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run nodeify && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -m -f iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","nodeify":"perl -pi -e \"s,\\({}\\),(typeof exports=='undefined'?{}:exports),\" ${dir}dist/$pkg.js","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, and tiny foundation.\n- **Declarative**—Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go? Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"46473662678ddd4fa5dff2b955826c9f531daa3e","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.17","_nodeVersion":"12.2.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-hYBwjeIC/3u035KJf0/Hf1ntL9nSUTZoaB7wssDPqSc0onM8kAtm8gjtiCf9TWkiKk/O19aAv/3Z6It+W0JvOQ==","shasum":"ab17e877a7f01e93b80f4dfef1b4e2e944637da3","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.17.tgz","fileCount":7,"unpackedSize":91756,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7ODECRA9TVsSAnZWagAAoKYP/jt+MoUJY0oH4VZxTnvQ\n7XStM5Vo5ywWU3FPD47sHYOR0HyEf5EjjpiX1UwsoHxW402zJvL4DeZNO5q3\nTDXdxkFRNhUovM7hC2Me6xt3O3ZMu6t+kbTdp+TlT0nK/84Xq/tdmlOieBBi\nzLeEIqZqoMJ4WvUgi59M4KNca6bFHRkB6UXd+vxQSij+FK7zMHS7AG2nVv8R\nsr7NTAv1I6SEZv0JGCQ5+sFK2JwDpauha1Enf4Hbu+05s3nA2gCdfHo2yYYf\nIF8HeLudx6S6WuNWoU8ZoWSegMV3WYlvyQP3+hJl5KF1W9RG6pGsk1qVvm/7\neTevg9G8ALZ6CUXF8YIHL0Bosf8szf5br6reZ0Q6ToDC/HulNLxN08q6H6+1\nXsNUtHbhQ4ky9U6hZwV7B2xlRE78sZzO24QbXSTr47Kkq1f8gCAKhb+wBPtM\n75osx3cYtwajeFziVSh3G5p9pqSrWjHsqPyhEAUU26ZISZk03AVJYft3bXa8\nFa4BTC+sUdoL2kIZuz1OuqBBASHv4XuZfoAo30Em8wrIIDHu0x8AHwhchUYh\namG4sr/uXmPOxafHCbrNimP6TkdzyTtUtGqexwPJ5nX4RVRSfBrgetUYf+13\nUQlyUOe5fwEirW7EgEqMiMDS0WRxJ3TMbfM9FweLmiyLEWY7RTs+5hMc1vrF\nkRMd\r\n=gy/F\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcyeKjn6lWcTgJCE6B0aCrbVjIG2XzYVsFYWYFinwLIwIgGrgwlyD4EVAdOkaAll2bHdmkiRDQEQJqNILCvVdJR5Q="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.17_1559027907585_0.4883620691035844"},"_hasShrinkwrap":false},"2.0.0-beta.18":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.18","main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n> 👋 Psst! The documentation is still a work-in-progress and may not be perfect. Please be patient as we work on it. If you think you've found a bug in Hyperapp, [create a new issue](https://github.com/jorgebucaran/hyperapp/issues/new) or [hop on Slack](https://hyperappjs.herokuapp.com) and let us know.\n\n- **Minimal**—We have aggressively minimized the concepts you need to learn to be productive out of the box. Immutable state, unidirectional data-flow, effects as data and subscriptions—all combined into a single apparatus, and tiny foundation.\n- **Declarative**—Write what, not how, and Hyperapp will figure out the best way to update the DOM as your data changes. Declarative user interfaces lead to highly testable and predictable applications—you'll never go back to DOM traversal and manipulation.\n- **Standalone**—Do more with less. Hyperapp includes state management and a [state-of-the-art] Virtual DOM engine that supports keyed updates, functional components & view memoization—all without extra dependencies.\n\n[Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Did you know that maintaining and developing this project is a full-time effort? If you love Hyperapp, please [support me](https://patreon.com/jorgebucaran) on Patreon. If you are not comfortable with a recurring pledge, I also accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran). Thank you! 🙌\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp?module\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground].\n\n## Getting started\n\nYou want to develop feature-rich, scalable browser-based applications using a functional paradigm and thought you might give Hyperapp a go? Let's see what it can do. Along the way, we'll explain the most important principles and terminology so you'll be ready to tackle the rest of the documentation. Before we sign off, we'll even walk you through setting up a minimal build step and a local development server using a JavaScript module bundler.\n\nOur first example is a counter that can be incremented or decremented. The goal of this tutorial is to give you a taste of how Hyperapp works, not build a real-world application. You'll learn how to initialize your application state, wire actions to user-triggered events, and render HTML on the page.\n\nCreate a new `index.html` file and paste the following code in it. We'll break it down afterwards.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp?module\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onclick: state => state - 1 }, \"-\"),\n            h(\"button\", { onclick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nLet's start from the bottom and work our way up the HTML tree. First, we create an empty `<div>` in the document body. We want to take over that node and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block and need to get help, check out the community support resources. Hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen writing actions, wouldn't it be better if we didn't have to think about events at all? Our current strategy may work if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp offers payload creators.\n\nFirst, let's rewrite `NewValue` to receive the new text value as a payload instead of the event object. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that receives an action's default payload and returns a new payload. It acts as a filter, transforming a payload before it reaches its destination. Here's how we can grab the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nWe use it when dispatching the action in place of the custom payload.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like we can use a payload creator here as well. First, let's define an action for this.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"07570f9a432d41ff1fec3ba62b33319908315167","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.18","_nodeVersion":"12.2.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-l6hXXU5P/2Oe0iULOTQkA2oPGx3IDrVCXDChVCUbKpB7yKapsuNAvfHYOh8V2HS9k6P7TQQrbGcIUSqWMyAwXA==","shasum":"592fb341328577dda26f167829a1d486dfc6521a","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.18.tgz","fileCount":7,"unpackedSize":91515,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7QSJCRA9TVsSAnZWagAAI44P/0tDmKiHmsuGF8SOUdPB\nQLTvga659oG+FbGQd2t8H5e+R6RfS4Cgtuc3Fksd0HOapbIAF0D5o6xstpit\nL3UNoPTMqPJOnbC05ym1j8loz+awgWFL6X/WsnvlBkrG5biFmKU3kI7POYsO\nXyu+ZzamJOCHDqc2Ru6QDs5VdrJVIJ73pXuSipw2lmsLpruTPuVM/IGSRx5Z\n0KfIvDF8NsgE7F7p0f2LIZDRs2+weWA6Yy6WvJx/mIm+fV6sOZy5+YOIEgOS\n01KA/Hjnd18G3WD4wHUNKsC0XG/ekgGEXFP+1CPnbLDoCSh6s/WudqTDX4HT\nQv3XkWvUl81yuFOQYS6PNaPiWfE5IOUNTx63oS42stAo41jNtWDqQJoSs4Yp\nP4r1rd6ggPGS53EqZIpOK9ikp526t2fyJNg8NmeGluUxiUrvKs1SsJUbhJTF\nqYBFhF7K0u54FPN1WVxviC1+azmoTA3f/GSMjUy012s2O5SFWmVEVtSOUtIG\nMvViFQW9EZ1sCkawG00Oq2RyyC8So1RgNghE7yRakM1NXE5ecZs83qJeaGPd\n/JYwfFrKSKL4WfGKz4+fBgj9MIW3nMzzU5NZ/KB7AjWFWQJJaZgFN7pEK01L\nc6lW3FVyqLqAiDurvnZCs6GWM/vTtoO1lrCfnStmTnfUSrg+t0gBTRaLkKQk\nWb37\r\n=JKOX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGoC98r9boeL8UJzlhytlwWCPO59ZPpqaiER8DyM5s0XAiEA8ppgOuavGR39L0yvc0Tuit/aedNgh5rqCgY8OI2gTbM="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.18_1559037063765_0.709410461187127"},"_hasShrinkwrap":false},"2.0.0-beta.19":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.19","main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"gitHead":"8df28fc15350e270292f04bfc5bf1ec89125ba66","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.19","_nodeVersion":"11.14.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-jxhRNR0kECecChHJr1b5uBgR1onlp1iKOZuUvmdWhi33J9FGWPptAdgxLfdDwiF947Jrb7LGOveHQbaz1bQ0eg==","shasum":"2a091150059061b5a901c6842ccf903bc4a55168","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.19.tgz","fileCount":7,"unpackedSize":90686,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9qL3CRA9TVsSAnZWagAA7wMP/iUkDX+7n8LsF5f8LZZC\nQonP7XGAsM/LneMHAt0o2S8q8trRUWu3wOdpxQTwqNrVDd1VwSmDQ17/QsPn\nvwu9ILxjrDeFAC7izW87FcByNOkcyK0wMrQBZ08lQbcUBIyXhEIPfQ8xJvvY\nT8AtNo9ZsdXsuD/qhURF4Oj9/t43sfxugM4hqzuvPRv1N+AykDmb75adtHX4\nayRlR2wPfbm8UlJgb4yBclTz4+BqoHtQkouvxkFbVFj72IsUNZ0ezOK3NLCx\nxB9vTpnl6UXc4bd+UJ2QfSConYT3IUoS5IYLRr5Z34dC+6lUEZwNA8VtFn8s\nXtbOf1pI5EF7rtJAXpRNtWEnmeZY7j9qVVjLmGHXIhDhCxhXFB5cb+jEBvG2\nsMEqxq7yTRaoPDU+nq+lDnP4nLe115gbaVRjcLADDLww3RV9SwF9/D1XD1Or\nGRQkLSjy3uLQmRUtR+TV/K+Ku0uEz9mQFgAifS7uTNpr4zu5RDyd5fsv/DnK\nCyMj5BWKTOSvq2V/YA8Pb4Ma58Zq80EVPByzoQiafEgf7e82LL9d/4PK1CzN\nyi+wDM8sUjyWjvjghBMtJHrZ78jbx46xrUgg0ctzfJ5c5a25i1NS7xeTcR29\niXEjKGSR1GKCB/XYHGxpXHDP4QiJqHorrx0sCZz9WR/HdykHG2Lr8lUYnGNb\nIk+7\r\n=uWsb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDk7bn8Cwp2AiZ4W+Yva4PwUwGKxzdVcxw3y/4Vc1/qwAIgLEbiN4BZYqESb8tmCyOwNR1QiRP1WJ/P2lJClq+TLx4="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.19_1559667446648_0.5797996861474686"},"_hasShrinkwrap":false},"1.2.10":{"name":"hyperapp","description":"1 kB JavaScript micro-framework for building declarative web applications.","version":"1.2.10","main":"dist/hyperapp.js","module":"src/index.js","typings":"hyperapp.d.ts","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.js.org","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","declarative"],"scripts":{"test":"jest --coverage --no-cache && tsc -p test/ts","build":"npm run bundle && npm run minify","bundle":"rollup -i src/index.js -o dist/hyperapp.js -m -f umd -n hyperapp","minify":"uglifyjs dist/hyperapp.js -o dist/hyperapp.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperapp.js.map","prepare":"npm run build","format":"prettier --write {src,test}/**/*.js {,test/ts/}*.{ts,tsx}","release":"npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"},"babel":{"presets":"env","plugins":[["transform-react-jsx",{"pragma":"h"}]]},"devDependencies":{"babel-plugin-transform-react-jsx":"^6.24.1","babel-preset-env":"^1.7.0","jest":"^23.5.0","prettier":"^1.14.2","rollup":"^0.65.2","typescript":"3.0.3","uglify-js":"3.4.9"},"prettier":{"semi":false},"gitHead":"486dbe262c2e44f489eff14d0f814e386a5a3843","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@1.2.10","_nodeVersion":"11.14.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-6htzCy/Y9QiSXyUGgZhfTqW0NtK7uMlaGS2t/kARJifu5vR4FjMcfC/5lqVs2mLSZ6GdKLEPsMZOVBpHz5X/qg==","shasum":"2198d71047ac5c7e7a801036f3e80d64dbe64ad1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-1.2.10.tgz","fileCount":8,"unpackedSize":62113,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9qikCRA9TVsSAnZWagAAfnkP/23eV3IWqtF13D+rxDF5\nlghpsLr0JSrTjbur4MFPXFUoc+Kaf2k1P+BSXEKGWazZL9w6vdZ1IqDjuqwM\nkZ8/Ze6p7433zRmBYu6Gxupu8DMdlFFqYXEP3WXlmR28gZgJlpan4Mx802j0\nExzaMe0u/4zCwGvd7RxS4svaSDaYlAdtunFxDN8b2nLINaQq9aXjwHR+GVMK\njJZmIuB1wwVe84k3BU5xadVUs/csH11BFcsGXbQUgM4FTNxn/1sZsuyvficx\nX+dLfMbuxf462Qi7p9TGKdU1VC0eHcIxoaVbx6o2dFVbWOfy5CL1BAUigyfB\n2eN0Sm6aBTd6K8lUE/fqMolPnEVKIiwm9CBrDo4LHzdR9Dop5dwq6u8lX+kz\ns1hY0Dk6EoMpZh4OtBXjgQfBNPdUqWHFQiFQNBpY+UUc7MAMjHHfwLvqcLd/\nbYhiXpSQSIt2M3FQk5KhBNcKqhKXWJlH4BQGFTRPiMYaVn1ShlvrFSwT76Wl\nzv93gsaD9pOkj5o/FOf0sgt8RQDAOEcn5ZEpg7Rt7J9NTCMy/PvmhNKH1R0a\nAqhiR5rLB54oa2mb3Avb/Lw8X9kBhoSGKDTEFGYd2B2XWprcLoHI+mHDP+2U\n5fJBaA1cDc01IB0X3cW6J8uY114v1VZuzjTd+F2PiT58lN/41JQTvK/5b973\n21se\r\n=k7mk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC79RY6z8vbflR2tgDhjENNK3HQyFwwPnCuoDG0PZbdCQIhAMdVCVpNj3Evm02c1WZMWsy82h4wbsfVhfIeWxguyVsC"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_1.2.10_1559668899306_0.7471187725864801"},"_hasShrinkwrap":false,"deprecated":"The Times They Are a-Changin. Please upgrade to Hyperapp 2"},"2.0.0-beta.20":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.20","main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"gitHead":"13c58682be6ba5e45389071319679ce12fea53e8","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n- **Do more with less**—We have aggressively minimized the concepts you need to learn to be productive in no time. Views, actions, effects and subscriptions are all pretty easy to get to grips with and work together seamlessly.\n- **Write what, not how**—Immutable state, effects as data, and declarative subscriptions—we got it all. If you want to develop featureful, browser-based applications using a purely functional paradigm, Hyperapp is your choice.\n- **Batteries-included**—Hyperapp includes state management and a modern Virtual DOM engine that supports keyed updates, components & view memoization out of the box—you'll never go back to DOM traversal and manipulation.\n\n> [Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Love Hyperapp? Please [support me](https://patreon.com/jorgebucaran) on Patreon. Not comfortable with a recurring pledge? I accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran) too. Thank you. ❤️\n\n## Table of Contents\n\n- [Installation](#installation)\n- [**Quickstart**](#quickstart)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground](#).\n\n## Quickstart\n\nIn this section, we'll walk you through your first example: a counter that can go up or down. It won't be a real-world application, but you'll get a taste of how Hyperapp works. You'll learn how to initialize your application state, wire actions to DOM events, and render HTML on the page. Before we sign off, we'll even set up a build step and a local development server using a JavaScript module bundler.\n\nFirst, create a new `index.html` file and paste the following code in it. \n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onClick: state => state - 1 }, \"-\"),\n            h(\"button\", { onClick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nWe want to take over the empty `<div>` in the document body and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll try to help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\n<!-- Immutable state, unidirectional data-flow (state transitions via actions), effects as data and declarative event streams (subscriptions). -->\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen implementing an action, wouldn't it be better if we didn't have to think about events at all? Our current strategy may be sufficient if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp has payload creators.\n\nFirst, let's rewrite `NewValue` to take in the new value as a payload. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that allows you to transform the default payload into anything you want. You can use it to filter the event object to extract the value before it reaches the action. Here's a payload creator that grabs the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nAnd here's how we use it when dispatching an action.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like a job for another payload creator.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.20","_nodeVersion":"11.14.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-fZOZ+cl8vVvHDcuEMVhWRn4Glb5jHZo0sELV4lQ/F7RbeaZq1EEBAgf82P9k54yuwxRAU+2vdkojtefFuIlp9w==","shasum":"afee4aa12fd07c00a5628d101f82ab3d47a725c9","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.20.tgz","fileCount":7,"unpackedSize":90686,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9qqcCRA9TVsSAnZWagAA7V4P/0dVfm1wgXbhTKl+ko/c\n2v/ECECDqNugVmJEGpBMHncQRc4a/eYwm4k7w2T2kjx1fH3pDqCD5xwGktwf\nYnO68P5Ny3HykZ+YDSJLQPzxuGPItTnY63vtb8xzoANA1GuiGyXA4mPi0e5V\neL25ecTH4khOf2TG87XAthdc0fNuTidG8KfKrxHIpLhM5cPwkGDV2i+RUdYJ\nNBtvIbKoHQ+I6qfJa22CrH9PhTQqI7mNMcwhtgoUiIBeZrhHiEQ7iy/SmeQx\nueI/cqPWeLIFskn8mC4F2HZ3tiJpvd9ngyPIYss/idO8YaY/rvjR5uNqmSh/\nOktW/3zNFsWnC8D2M5ATmlPojCDjp7WxIhCtBXZ8VbaOXbndKUqlBATMLwud\n6nM0Tz1aD7C7UER57BDmmwD3hDdw3pxMdCKRfZfvH4TFEcQx7Q8aKVVve7ih\noeE7If3G/5JfTeUw0GhRMKa0i6V5b7V68XLtfYtbfrDn0sn72e2UXoaJx7LJ\nLi8vq2TdPo21SehzvBCN8GfTuga/Hy0Wy4Um2ZU03Z8ljHkUd4B+IwpvT/kG\nAvIezkGcdL9/SZSz5eqmQx38bCgSX5n7x0vX9jkPcESF9AtJbr8vgqlmM55u\naus000/WTO7m58V4xAbDz13hTYKtpLzcFaikKFi1rxZGPtpPHsjN/xPubYXy\n38Uo\r\n=3iQh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDYWlUE8BlVqKRMOScSjVdt1zZsaQzsBHxuQhlwZKsDLwIhAOr3989uOCN+6znkkOV9TMJNo8zHBlzLY8fEfpTrFwU/"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.20_1559669404228_0.10501314551860408"},"_hasShrinkwrap":false},"2.0.0-beta.21":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.21","main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"gitHead":"cc965dc9fc5ee8176515657f4a14c343d138aa82","readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n- **Do more with less**—We have aggressively minimized the concepts you need to learn to be productive right now. Views, actions, effects and subscriptions are all pretty easy to get to grips with and work together seamlessly.\n- **Write what, not how**—Create dynamic UIs, run side effects, and subscribe to event streams in the same declarative style. Hyperapp is your tool of choice to develop purely functional, browser-based applications.\n- **Batteries-included**—Hyperapp includes state management and a modern Virtual DOM engine that supports keyed updates, components & view memoization out of the box—you'll never go back to DOM traversal and manipulation.\n\n> [Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Love Hyperapp? Please [support me](https://patreon.com/jorgebucaran) on Patreon. Not comfortable with a recurring pledge? I accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran) too. Thank you. ❤️\n\n## Table of Contents\n\n- [Installation](#installation)\n- [**Quickstart**](#quickstart)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground](#).\n\n## Quickstart\n\nIn this section, we'll walk you through your first example: a counter that can go up or down. It won't be a real-world application, but you'll get a taste of how Hyperapp works. You'll learn how to initialize your application state, wire actions to DOM events, and render HTML on the page. Before we sign off, we'll even set up a build step and a local development server using a JavaScript module bundler.\n\nFirst, create a new `index.html` file and paste the following code in it.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onClick: state => state - 1 }, \"-\"),\n            h(\"button\", { onClick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nWe want to take over the empty `<div>` in the document body and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll try to help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\n<!-- Immutable state, unidirectional data-flow (state transitions via actions), effects as data and declarative event streams (subscriptions). -->\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen implementing an action, wouldn't it be better if we didn't have to think about events at all? Our current strategy may be sufficient if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp has payload creators.\n\nFirst, let's rewrite `NewValue` to take in the new value as a payload. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that allows you to transform the default payload into anything you want. You can use it to filter the event object to extract the value before it reaches the action. Here's a payload creator that grabs the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nAnd here's how we use it when dispatching an action.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like a job for another payload creator.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.21","_nodeVersion":"11.14.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-aJbModQ+v4vpBusLrpFdNd0n+1arRVkvnCa18oJcA4zcyRM1OL8T2YAxNsLbE3kuPOZ2cgb7vs6FaSfDgYFWhg==","shasum":"57aa0883f4ffbff46ceb39520de5ed0cfa24548d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.21.tgz","fileCount":7,"unpackedSize":91439,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+BSKCRA9TVsSAnZWagAACd4P/idLPUlb479sFaoWxycV\n23X48lPAFz+0eYklc+UTeeBz9twCnfmOToiXgJQqxFkPPQAqKPZ8/42oqCxa\nD6NIpajkZqEVzEWt0w+Z/YRFyHlq0JaKMIeBZYMNKIPepZFDU3qisg53gAzZ\n7oMOncfpmO3P0YSt6XuCMu85ENMKssDV2YUDkLsAIEcSWXxZG/VNI3VI0tKD\ntipcLXmehneKKIyHIH/p4dUulFlwbkUqjEeYDDRAWvClS0Q04j2wAI+zHz1E\nvTpmdh/4qCxZxpupIZVKnFdCpvqsrQFPQaKmtvkYVxqzDbXnKTOcymSMqY1V\n2rHapgCeVtExZ/Rh+z28wEgM14qz09Qc7edwoWw8VpafLR8roPWxYX0Talf6\n1iIRQwgt+4GJc20euq6eqcCm8bIAbM6befDO2qZUfewGKQED4oM2QgTEgddc\naEWND+BJKEsx/kVTOM0BK+6PJ/dEII56nredCDWBus1VCxK8QGo2E7kiH0gx\nGIXMiS8FV392VqOXWPTTYxoAj2YoU1GGVBGTuWw1YlwokZnDVcF4cDUpAYAv\n5JEr1N8kp0knQMSNYA5Pbl1If8sTu6/lRZvxAUemfXxbt0COoSIhNF2YkG57\ne0n9STeejeYueXSH5ZIR8rThIfpSLTUK2R2PcVEC2LejPV1oCmkPkUeNe9WL\nJaLg\r\n=oFae\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSOVIlMepF2tsvwumHL3rickKwl5PimAeL67jDvuU2cgIgRnTrAuLg6EkLbXKGLMrgyeUDj0D3WeyxpzmA/Hc1TCY="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.21_1559762057543_0.6727873299157956"},"_hasShrinkwrap":false},"2.0.0-beta.22":{"name":"hyperapp","description":"JavaScript micro-framework for building web interfaces.","version":"2.0.0-beta.22","main":"src/index.js","module":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"exit 0","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"rollup":"*","terser":"^4.0.0"},"readme":"# Hyperapp\n\n[![Travis CI](https://img.shields.io/travis/jorgebucaran/hyperapp/master.svg)](https://travis-ci.org/jorgebucaran/hyperapp)\n[![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.org/package/hyperapp)\n[![Slack](https://hyperappjs.herokuapp.com/badge.svg)](https://hyperappjs.herokuapp.com \"Join us\")\n\nHyperapp is a JavaScript micro-framework for building web interfaces.\n\n- **Do more with less**—We have aggressively minimized the concepts you need to learn to be productive right now. Views, actions, effects and subscriptions are all pretty easy to get to grips with and work together seamlessly.\n- **Write what, not how**—Create dynamic UIs, run side effects, and subscribe to event streams in the same declarative style. Hyperapp is your tool of choice to develop purely functional, browser-based applications.\n- **Batteries-included**—Hyperapp includes state management and a modern Virtual DOM engine that supports keyed updates, components & view memoization out of the box—you'll never go back to DOM traversal and manipulation.\n\n> [Check out the examples](#examples) and [follow Hyperapp](https://twitter.com/hyperappjs) on Twitter for news and updates. Love Hyperapp? Please [support me](https://patreon.com/jorgebucaran) on Patreon. Not comfortable with a recurring pledge? I accept one-time donations via [PayPal](https://www.paypal.me/jorgebucaran) too. Thank you. ❤️\n\n## Table of Contents\n\n- [Installation](#installation)\n- [**Quickstart**](#quickstart)\n- [Help, I'm stuck!](#help-im-stuck)\n- [Fundamentals](#fundamentals)\n  - [Initializing the state](#initializing-the-state)\n  - [Rendering a page](#rendering-a-page)\n  - [Dispatching actions](#dispatching-actions)\n  - [Handling text input](#handling-text-input)\n  - [Putting it all together](#putting-it-all-together)\n- [Subscriptions](#subscriptions)\n  - [Controlling time](#controlling-time)\n  - [Listening to global events](#listening-to-global-events)\n  - [Implementing your own subscriptions](#implementing-your-own-subscriptions)\n- [Effects](#effects)\n  - [Talking to servers](#talking-to-servers)\n  - [Manipulating the DOM](#manipulating-the-dom)\n  - [Generating random numbers](#generating-random-numbers)\n  - [Implementing your own effects](#implementing-your-own-effects)\n- [HTML Attributes](#html-attributes)\n- [Techniques](#techniques)\n  - [Testing]\n  - [Hydration]\n  - [Navigation]\n  - [Working with Forms](#working-with-forms)\n  - [Using external libraries](#using-external-libraries)\n  - [Animating elements]\n- [Optimization](#optimization)\n  - [Keys]\n  - [Lazy views]\n- [Examples](#examples)\n- [Ecosystem](#ecosystem)\n- [License](#license)\n\n## Installation\n\nInstall the latest version of Hyperapp with a package manager. We recommend using npm or Yarn to manage your front-end dependencies and keep them up-to-date.\n\n<pre>\nnpm i hyperapp@<em>beta</em>\n</pre>\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import Hyperapp in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry, modules are supported in all evergreen, self-updating desktop and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp\"\n</script>\n```\n\nWant to get a sense of what Hyperapp is like without installing anything? Try it in [this code playground](#).\n\n## Quickstart\n\nIn this section, we'll walk you through your first example: a counter that can go up or down. It won't be a real-world application, but you'll get a taste of how Hyperapp works. You'll learn how to initialize your application state, wire actions to DOM events, and render HTML on the page. Before we sign off, we'll even set up a build step and a local development server using a JavaScript module bundler.\n\nFirst, create a new `index.html` file and paste the following code in it.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp\"\n\n      app({\n        init: () => 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onClick: state => state - 1 }, \"-\"),\n            h(\"button\", { onClick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nWe want to take over the empty `<div>` in the document body and replace it with our view. Maybe your program is within a broader application, in a sidebar widget and surrounded by other elements. That's fine too. Hyperapp gives you absolute control over where the root element of your application is rendered in the DOM.\n\nThe application starts by dispatching the `init` action to initialize the state. Our code does not explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a representation of the DOM known as a virtual DOM, and Hyperapp updates the actual DOM to match it.\n\nHere's what the virtual DOM looks like, abridged for clarity.\n\n```js\n{\n  name: \"div\",\n  props: {},\n  children: [\n    {\n      name: \"h1\",\n      props: {},\n      children: [0]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"-\"]\n    },\n    {\n      name: \"button\",\n      props: {},\n      children: [\"+\"]\n    }\n  ]\n}\n```\n\nWe use Hyperapp's `h` function to create virtual DOM nodes. It takes three arguments: a string that specifies the name of the node; `div`, `h1`, `button`, etc., an object of HTML or SVG properties, and an array of child nodes. Describing HTML trees using functions, also known as hyperscript, is a common idea in virtual DOM implementations; the virtual DOM object specification may vary between libraries, but the function's signature stays the same.\n\nAnother way of creating virtual DOM nodes is using [JSX](https://facebook.github.io/jsx). JSX is an embeddable XML-like syntax language extension that lets you write HTML tags interspersed with JavaScript. It's syntactic sugar for pure, nested `h` function calls. The trade-off is that we need to compile it to standard JavaScript using a specialized tool before we can run the application.\n\nIf you are tagging along, create an `index.js` file and paste the following code in it.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  init: () => 0,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={state => state - 1}>-</button>\n      <button onclick={state => state + 1}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe'll use [Babel](https://babeljs.io) to translate JSX to `h` function calls. First, install [`@babel/core`](https://www.npmjs.com/package/@babel/core) and [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx). One is the compiler, the other is the JSX to JavaScript plugin. Then, add the following configuration to your `.babelrc` file, creating one if you haven't already.\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\"\n      }\n    ]\n  ]\n}\n```\n\nFair warning, if you see JSX used in this documentation, it's purely a stylistic choice. If you don't want to set up a build step, there are compilation-free options such as [@hyperapp/html](https://github.com/hyperapp/html), [htmlo], and [htm](https://github.com/developit/htm). Try them all to find out which one works best for you.\n\nNow, open the `index.html` file you created before and modify it like so.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nFinally, let's put it all together with a module bundler. Bundlers take JavaScript modules (or fonts, images, stylesheets), and combine them into one or a few files optimized for the browser. For this example, we choose [Parcel](https://parceljs.org) because of its low barrier to entry. If you prefer [Webpack](https://webpack.js.org) or [Rollup](http://rollupjs.org), refer to their documentation for usage details.\n\nOnce you've installed [`parcel`](https://www.npmjs.com/package/parcel-bundler), go ahead and start the local development server. It automatically rebuilds your app as you change files, reloading the browser window for you.\n\n```console\n$ parcel index.html\n```\n\n...and you should be up and running. You did it!\n\nIf something isn't working as expected you can always [look at] the source online to see how we did it. Experiment with the code. Spend some time thinking about how the view reacts to changes in the state. Can we add a button that resets the counter back to zero? How about disabling the decrement button if the state is less than one? Let's work on that next.\n\nPreviously, we defined actions inside the view function. This is inefficient, as it creates a new function every time Hyperapp calls the view. Anonymous functions are also awkward to debug since they don't have a name. A good rule of thumb is to create a function for every action in your program. Don't hold back, they're cheap!\n\n```jsx\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n```\n\nAn action can be any function that takes the application state as the first argument and returns a new state. Notice that `Reset` doesn't need the state argument to reset the counter, so we ignore it. Actions can also receive a payload, but let's not get ahead of ourselves.\n\nTo indicate the user can't interact with the button, we'll assign a boolean value to the element's `disabled` attribute as follows.\n\n<!-- prettier-ignore -->\n```jsx\n<button onclick={Decrement} disabled={state === 0}>-</button>\n```\n\nThat should be all. Here's how our program looks now.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst Reset = () => 0\nconst Decrement = state => state - 1\nconst Increment = state => state + 1\n\napp({\n  init: Reset,\n  view: state => (\n    <div>\n      <h1>{state}</h1>\n      <button onclick={Reset}>Reset</button>\n      <button onclick={Decrement} disabled={state === 0}>-</button>\n      <button onclick={Increment}>+</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThere's still a lot of ground to cover, but we're off to a great start! In the following sections, we'll learn how to use actions to their full extent, handle text input, submit forms, create side-effects, subscribe to global events, talk to servers, manipulate the DOM, and more. {{By the end, I hope you will not only be able to create great applications in Hyperapp, but also understand the core ideas and patterns that make Hyperapp nice to use}}.\n\n## Help, I'm stuck!\n\nWe all get stuck sometimes. If you've hit a stumbling block hop on the [Hyperapp Slack Room](https://hyperappjs.herokuapp.com) to get help quickly, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll try to help you out.\n\n## Fundamentals\n\nHyperapp applications consist of a single state tree, a view that describes a user interface, and actions that describe state transitions. Every time your application state changes, Hyperapp calls the view function to create a new virtual representation of the DOM and uses it to update the actual DOM.\n\n<!-- Immutable state, unidirectional data-flow (state transitions via actions), effects as data and declarative event streams (subscriptions). -->\n\nIt may seem wasteful to throw away the old virtual DOM and recalculate it entirely on every update—not to mention the fact that at any one time, Hyperapp is keeping two virtual DOM trees in memory, but as it turns out, browsers can create hundreds of thousands of objects very quickly. On the other hand, modifying the DOM is orders of magnitude more expensive.\n\nIn this section, we'll take a deep dive into the data lifecycle of a typical Hyperapp application as we build a to-do manager step-by-step. We'll look in great detail at how we initialize the state, render content on the page, and dispatch actions. Finally, we'll discuss how breaking down our view into functional components can improve code reusability and readability.\n\n### Initializing the state\n\nThe state is a plain object that contains knowledge about your application at any given time; for example, a blog needs to know whether or not a user is logged in or how many posts they have published, a platform game might keep track of the character's coordinates on the screen, vertical velocity, direction, and so on.\n\nOur to-do app will need an array to store to-do items and a string to watch what the user is currently typing into a text field. Each item will have an id and a value. We also want to know if the user is editing a particular item, and a way to undo changes if they cancel the operation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      {\n        id: 1,\n        value: \"Go outside\",\n        isEditing: false,\n        lastValue: \"\"\n      }\n    ]\n  })\n})\n```\n\nThe `init` action describes how to initialize the state. Think of it as the entry point of the program. Unlike [model–view–controller](https://en.wikipedia.org/wiki/Model–view–controller) and derivatives that encourage spreading the state out across different components, Hyperapp's state is consolidated in one place.\n\nIf we decide to start with more than one to-do items, we're going to run out of vertical space quickly. By creating new to-do items through a function, we can reduce code duplication and automate generating a unique id for each item using a base change algorithm. No warranty of any kind is implied, though. Use at your own risk.\n\n> Using `Math.random` to generate random numbers is a side effect. We're taking a pragmatic approach to allow for side effects in this example out of convenience. You can read more about [generating random numbers] using Hyperapp effects later in the documentation.\n\n```jsx\nimport { app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  })\n})\n```\n\nWe have an initial state, but there's still no user interface to display it. What will our program will look like? In the next section, we'll learn how to render a page and look more closely at the virtual DOM model.\n\n### Rendering a page\n\nWhen describing the content of a page, we use the `h` function to create a virtual DOM. A virtual DOM is an object representation of how the DOM should look at any point in time. Hyperapp calls your `view` function to create this object and converts it into real DOM nodes in the browser.\n\nA virtual DOM allows us to write code as if the entire document is thrown away and rebuilt on each transition, while we only update the parts that actually change. We do this in the least number of steps possible, by comparing the new virtual DOM against the previous one, leading to high-efficiency, since typically only a small percentage of nodes need to change, and changing real DOM nodes is costly compared to recalculating the virtual DOM.\n\n<!-- prettier-ignore -->\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"article\", {}, [\n        h(\"h2\", {}, \"What's Hyperapp?\")\n      ])\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nWe also need to tell Hyperapp where to render the view. Usually, you'll have a node with an `id=\"app\"` or `id=\"root\"` in your HTML for this purpose. You can use any type of node, even a text node. If the node isn't empty, Hyperapp will recycle its children instead of throwing away the existing content. This process is also called [hydration]. We'll discuss it later in the documentation.\n\nLet's use what we've learned to render our to-do app with Hyperapp.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () =>\n    h(\"div\", {}, [\n      h(\"h1\", {}, \"To-Do\"),\n      h(\"ul\", {}, [\n        h(\"li\", {}, \"Go outside\"),\n        h(\"li\", {}, \"Wake up earlier\"),\n        h(\"li\", {}, \"Learn a new language\")\n      ]),\n      h(\"input\", { type: \"text\", value: \"\" }),\n      h(\"button\", {}, \"New Item\")\n    ]),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf HTML tags in your JavaScript sound appealing, here's the same code using JSX. It requires a build step, but JSX tends to look like regular HTML, which can be a win for you or your team. We'll be using JSX for the rest of this document, but you can choose whatever works for you. Check out [`@hyperapp/html`](https://github.com/hyperapp/html) for an official alternative.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\napp({\n  view: () => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        <li>Go outside</li>\n        <li>Wake up earlier</li>\n        <li>Learn a new language</li>\n      </ul>\n      <input type=\"text\" value=\"\" />\n      <button>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nExcellent! Now we have a user interface to work with. Next, we want to populate the list dynamically based on the current state. [Previously](#initializing-the-state), we learned how to initialize the application state, and we know the `view` function takes in the state, so let's put the two together.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\napp({\n  init: () => ({\n    value: \"\",\n    items: [\n      newItem(\"Go outside\"),\n      newItem(\"Wake up earlier\"),\n      newItem(\"Learn a new language\")\n    ]\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <ul>\n        {state.items.map(item => (\n          <li>{item.value}</li>\n        ))}\n      </ul>\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nThe view is a way to view your state as HTML. The text field is synchronized with `state.value`, though, there's no way to update it yet, and by mapping through `state.items` we can turn the items array into an array of `<li>` nodes. There was no need to mutate the DOM manually, the markup is entirely declarative.\n\nEventually, you'll want to break down your view into reusable components. Hyperapp components are stateless functions that return virtual DOM nodes. Their input is the state or a part thereof; their output is the markup that represents the supplied state. Components make it easy to split your UI into chunks of content, styles, and behavior that belong together.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item => (\n      <li>{item.value}</li>\n    ))}\n  </ul>\n)\n```\n\nLet's revisit our to-do app requirements. We want to add new, edit, and delete existing entries. When we're editing an item, it should also be possible to cancel the operation. As it turns out, we already have everything we need in the state. If you look at any to-do item, you'll find `isEditing`, a boolean flag set to `false`. We're going to use it to toggle a to-do's edit mode. While in edit mode, we'll show a text field, and buttons such as Cancel, Remove, and Save.\n\n```jsx\nconst TodoList = props => (\n  <ul>\n    {props.items.map(item =>\n      item.isEditing ? (\n        <li>\n          <input type=\"text\" value={item.value} />\n          <button>Cancel</button>\n          <button>Remove</button>\n          <button>Save</button>\n        </li>\n      ) : (\n        <li>{item.value}</li>\n      )\n    )}\n  </ul>\n)\n```\n\nTo render the `TodoList` component, you can use it as you would any other element in the view. We've left out the state initialization code for brevity.\n\n```jsx\napp({\n  init: () => ({\n    // ...\n  }),\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input type=\"text\" value={state.value} />\n      <button>Add</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nHyperapp components receive all the necessary state from their parent components, or in this case, the view function itself. Unlike the view function, however, components are not automatically wired to your application state.\n\nWe have a state and view to display it, but still no way to interact with the application. There's no way to toggle a to-do's edit mode; inputs and buttons aren't functional yet. In the next section, we're going to explore actions in detail. We'll learn how to respond to DOM events, and update the state, propagating changes back to the view.\n\n### Dispatching actions\n\nActions describe state transitions: current state in, new state out. An action doesn't change the state in-place but yields a new state. We can dispatch actions in response to DOM events like clicks, mouse moves, key ups/downs, and so on, using the [on-event](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers) attribute of the target element.\n\n```jsx\n<button onclick={Add}>New Item</button>\n```\n\nWhen the user clicks the button, the browser sends a click event to the button. Hyperapp intercepts the event to dispatch the specified action with the current state and event object as a payload and uses the return value of the action as the new state. At this point, the state and the DOM are out of sync. Next, it calls the view function to calculate a new virtual DOM and [schedules](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) the DOM to update before the next browser repaint, minimizing expensive layout reflows and further repaints.\n\nHyperapp's state is immutable. You initialize it, but you can't change it like you would any other object. Instead, changes are presented by creating a new object based on the current state; for example, here's the action to describe adding a new item in our to-do app.\n\n```jsx\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n```\n\nNotice how we use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) to shallow-clone the state and merge it with the updated properties, creating a brand new object in the process. When adding a new to-do item, we join `state.items` and `state.value` into a new `items` array, and to clear the text field, set the current `value` to an empty string. Creating a new array to add, update or remove items is a common pattern when working with lists in an immutable fashion.\n\nImmutability doesn't imply that the state is unwriteable. You can try to circumvent the state transition mechanism, but that's never a good idea. If you mutate a property in the state, Hyperapp doesn't know what has changed, potentially leading to a DOM out of sync with your state and unwanted side-effects. You've been warned.\n\nBack to our to-do app. We've seen how to add new items, but how do we remove an item without mutating the original state? We know that every to-do item has an `id` property. The solution is to use the [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) method on `state.items` and create a new array without the unwanted element.\n\n```jsx\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n```\n\nWhat is of interest here is how the action receives the `id`. When we want Hyperapp to dispatch an action with a custom payload we use a 2-tuple action-value pair that consists of the action and any type of data we want to send as a payload.\n\n```jsx\n<button onclick={[Remove, item.id]}>Remove</button>\n```\n\nAnd for context, here's the new `TodoList` component. We also wired actions to the Save and Cancel buttons, and to each to-do list item to toggle the edit mode when clicked. You'll learn how they work after the code snippet.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input type=\"text\" value={item.value} />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nLet's take a look at `ToggleEdit` first. Why is it used in two different elements? It's essentially a switch. The state needs to know if we're in edit mode or not; moreover, we're trying to make any item editable, that's why `isEditing` is in the to-do definition.\n\n```jsx\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          lastValue: item.value,\n          isEditing: !item.isEditing\n        }\n      : item\n  )\n})\n```\n\nThe gist of it is toggling `isEditing` on or off based on its current value, and saving `item.value` in `lastValue`. We're carrying a copy of each to-do's value at all times, which we'll use to reset `value` in `Cancel` shown below.\n\n```jsx\nconst Cancel = (state, id) => ({\n  ...state,\n  items: state.items.map(item =>\n    item.id === id\n      ? {\n          ...item,\n          value: item.lastValue,\n          isEditing: false\n        }\n      : item\n  )\n})\n```\n\nIn plain English, `Cancel` updates the item matching the supplied `id` in `items` by setting its `value` back to what it was before switching to edit mode, and sets `isEditing` to false to switch edit mode off.\n\nIf we look closely at either action, we'll notice a repetitive pattern: map through an array, find an element matching a given `id`, and update one or more properties in it. Wouldn't it be nice if we could refactor that into a function we can reuse later? Fortunately, we can.\n\n```jsx\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n```\n\nThe result is less, and more readable code. A single glance at `Cancel` or `ToggleEdit` reveals what properties are changing in any given to-do, without getting bogged down in the how.\n\nLook how far we've come. We can initialize an application with some state, visualize it, and dispatch actions to update it. Give or take, everything after this point is building upon the same ideas. In the next section, you'll learn how to handle text input, and access the event object and element that triggered an event. Hang on tight! We're almost done.\n\n### Handling text input\n\nSo far we've seen how to dispatch an action when the user clicks on a button, but how do we update the state when the user types into a text field? Text fields are inherently stateful—how do we prevent the application state and DOM from getting out of sync? Let's find out.\n\nTo capture what the user is typing into a text field, we can assign an action to the oninput event attribute of the target element. And by setting the value attribute of the element to `state.value`, we guarantee that its internal state always mirrors what's in the state.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={NewValue} />\n```\n\n[Input events](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/input_event) fire not only on every keystroke but whenever the value of a text field changes; for example, by dragging text to or from the element, by cutting or pasting text either with or without the keyboard, or by using speech recognition to dictate the text.\n\nLikewise, the onchange event occurs when the selection, the checked state or the value of an element have changed, however, for a text field, this event only fires when the element loses focus, whereas input events fire immediately on every change. [Change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) are useful for validating forms as sometimes we don't want to display errors until the user is finished typing.\n\nNow, how do we grab the changed value? The browser creates an [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) for every event, carrying detailed information about the event at the time it occurred: the type of the event, the event target, etc. Hyperapp sends this object as the payload to any action wired to a DOM event, allowing us to update `state.value` with the current value of the text field.\n\n```jsx\nconst NewValue = (state, event) => ({ ...state, value: event.target.value })\n```\n\nWhen implementing an action, wouldn't it be better if we didn't have to think about events at all? Our current strategy may be sufficient if not involving a complex payload, but at what cost? Actions tightly coupled to events don't encourage code reusability; besides, destructuring the event object can become awkward. To tackle this problem, Hyperapp has payload creators.\n\nFirst, let's rewrite `NewValue` to take in the new value as a payload. We'll figure out how to pass in the value in a moment.\n\n```jsx\nconst NewValue = (state, value) => ({ ...state, value })\n```\n\nA payload creator is a function that allows you to transform the default payload into anything you want. You can use it to filter the event object to extract the value before it reaches the action. Here's a payload creator that grabs the event's target value.\n\n```jsx\nconst targetValue = event => event.target.value\n```\n\nAnd here's how we use it when dispatching an action.\n\n```jsx\n<input type=\"text\" value={state.value} oninput={[NewValue, targetValue]} />\n```\n\nSimilarly, we need to handle text input for every to-do item while it's in edit mode, as well as send a custom payload with the action to identify which to-do item the user is editing. Sounds like a job for another payload creator.\n\n```jsx\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n```\n\nAnd here's our up-to-date `TodoList` component using it.\n\n```jsx\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n```\n\nNeat! Whereas custom payloads allow us to send dynamic data into our actions without cluttering the state with intermediate values, payload creators give us full control of the data we can pass in, reducing coupling and improving code reuse. We have all the bits and pieces we need to put our to-do app together now. In the next section, we'll wrap things up and present the entire program in all its shining glory.\n\n### Putting it all together\n\nHere's the fruit of our work. Everything is in one place to help you see the big picture. In a real-world scenario, you'll want to split up your code into modules instead to reduce complexity and improve maintainability. Check out the final result [online] for a potential way to organize a Hyperapp project.\n\n```jsx\nimport { h, app } from \"hyperapp\"\n\nconst targetValue = e => e.target.value\n\nconst setItem = (items, id, set) =>\n  items.map(item => (item.id === id ? { ...item, ...set(item) } : item))\n\nconst newItem = value => ({\n  id: Math.random().toString(36),\n  isEditing: false,\n  lastValue: \"\",\n  value\n})\n\nconst NewValue = (state, value) => ({ ...state, value })\n\nconst Add = state => ({\n  ...state,\n  value: \"\",\n  items: state.items.concat(newItem(state.value))\n})\n\nconst Update = (state, { id, value }) => ({\n  ...state,\n  items: setItem(state.items, id, () => ({ value }))\n})\n\nconst Cancel = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    value: item.lastValue,\n    isEditing: false\n  }))\n})\n\nconst Remove = (state, id) => ({\n  ...state,\n  items: state.items.filter(item => item.id !== id)\n})\n\nconst ToggleEdit = (state, id) => ({\n  ...state,\n  items: setItem(state.items, id, item => ({\n    lastValue: item.value,\n    isEditing: !item.isEditing\n  }))\n})\n\nconst TodoList = props =>\n  props.items.map(item =>\n    item.isEditing ? (\n      <li>\n        <input\n          type=\"text\"\n          value={item.value}\n          oninput={[Update, e => ({ id: item.id, value: targetValue(e) })]}\n        />\n        <button onclick={[Cancel, item.id]}>Cancel</button>\n        <button onclick={[Remove, item.id]}>Remove</button>\n        <button onclick={[ToggleEdit, item.id]}>Save</button>\n      </li>\n    ) : (\n      <li onclick={[ToggleEdit, item.id]}>{item.value}</li>\n    )\n  )\n\napp({\n  init: {\n    value: \"\",\n    items: [newItem(\"Make a sandwich\")]\n  },\n  view: state => (\n    <div>\n      <h1>To-Do</h1>\n      <TodoList items={state.items} />\n      <input\n        type=\"text\"\n        value={state.value}\n        oninput={[NewValue, targetValue]}\n      />\n      <button onclick={Add}>New Item</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\nIf you made it here, congratulations, we built a minimal, fully functional to-do app from scratch in just a few lines of code. We left out features like marking items as complete rather than deleting them, filtering, searching, and saving our data to local storage, but you should have a decent grasp of how Hyperapp works by now.\n\nIf you're up for the challenge, try implementing one or two new features; for example, it would be useful to cross-out a to-do to indicate you've completed a task without removing it from the list. Also nice to have is a button to clear the entire list in one go. Sometimes we need to start over to see things in a new light.\n\n## Subscriptions\n\nSometimes we want to react to interesting events happening outside of our application like subscribing to location changes, or the current time. Did the user resize the browser's window? Maybe we're building a game and want to hook into the browser's natural repaint cycle. Subscriptions allow us to listen for such things.\n\nThe alternative, working with traditional event emitters, requires complicated resource management like adding and removing listeners, closing connections, clearing out intervals—not to mention testing asynchronous code is tricky. What happens when the source you are subscribed to shuts down? How do you cancel or restart a subscription?\n\nSubscriptions describe a connection to an event generator. Similar to how we use a function to create virtual nodes instead of writing them out by hand, we use functions to create a subscription of the type of event we want to listen to. For scheduling recurrent tasks there is [`@hyperapp/time`](lib/time), for listening to global events like mouse or keyboard events there is [`@hyperapp/events`](). Need to use WebSockets for two-way communication? [`@hyperapp/websocket`]() has your back.\n\n### Controlling time\n\nLet's say you want to call a function every second or so. Maybe you're creating a turn-based game where each player has an allotted time to play. Usually, you'd use `setInterval` or concoct something with `setTimeout` to defer calling a function at a later date and keep track of the timeout ID so you can clear out the interval; for example, when you want to pause or resume the game. But what happens when the time needs to change dynamically? In some forms of chess, you have to add a certain number of seconds to the player's clock each time they move. Working with time will be our first foray into the world of subscriptions.\n\nWe're going to build a simple clock that shows the current time. You can try the [final result here]() before we dive into the code. When you're ready, install the [`@hyperapp/time`](lib/time) core package. Then, import the `interval` function into your program and create a new subscription as follows, specifying the action to dispatch and the interval delay. Unless otherwise stated, time is always measured in milliseconds.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst Tick = (state, time) => ({ ...state, time })\n\napp({\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ]\n})\n```\n\nThat is all there is to setting up a subscription. Hyperapp will dispatch `Tick` with the system timestamp as the payload every second. Behind the scenes, it uses the browser's [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) method to dispatch the action at the specifed time interval and [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) to retrieve the current time.\n\nThe `subscriptions` function takes in the current state and returns an array of subscriptions. Whenever the state changes, Hyperapp calls this function to calculate a new array. If a subscription appears in the array, we'll start it. If a subscription leaves the array, we'll cancel it. If any of its properties change, we'll restart it.\n\nHere's the rest of the program. To spice things up, we've added an option to switch to a 24-hour clock too.\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { interval } from \"@hyperapp/time\"\n\nconst timeToUnits = t => [t.getHours(), t.getMinutes(), t.getSeconds()]\n\nconst formatTime = (hours, minutes, seconds, use24) =>\n  (use24 ? hours : hours > 12 ? hours - 12 : hours) +\n  \":\" +\n  `${minutes}`.padStart(2, \"0\") +\n  \":\" +\n  `${seconds}`.padStart(2, \"0\") +\n  (use24 ? \"\" : ` ${hours > 12 ? \"PM\" : \"AM\"}`)\n\nconst posixToHumanTime = (time, use24) =>\n  formatTime(...timeToUnits(new Date(time)), use24)\n\nconst Tick = (state, time) => ({ ...state, time })\n\nconst ToggleFormat = state => ({ ...state, use24: !state.use24 })\n\napp({\n  init: () => ({\n    time: Date.now(),\n    use24: false\n  }),\n  view: state => (\n    <div>\n      <h1>{posixToHumanTime(state.time, state.use24)}</h1>\n      <fieldset>\n        <legend>Settings</legend>\n        <label>\n          <input type=\"checkbox\" checked={state.use24} oninput={ToggleFormat} />\n          Use 24 Hour Clock\n        </label>\n      </fieldset>\n    </div>\n  ),\n  subscriptions: state => [\n    interval(Tick, {\n      delay: 1000\n    })\n  ],\n  node: document.getElementById(\"app\")\n})\n```\n\nNow, let's say we need to hide the clock. Fair enough, but how do we clear out the interval? We don't want to trigger unnecessary renders and waste browser resources. By using a boolean condition we can switch a subscription on or off whenever the state changes and Hyperapp will take care of rewiring the connections for us under the hood. The main takeaway is: we can start or cancel a subscription without having to keep track of an ID or event listener, just like we can show or hide an element in the view without a reference to a DOM node.\n\n```jsx\napp({\n  subscriptions: state => [\n    state.isVisible &&\n      interval(Tick, {\n        delay: 1000\n      })\n  ]\n})\n```\n\nThe [`@hyperapp/time`](lib/time) package is not a general date/time utility library. You won't find constants or functions to format, validate or manipulate time and time zones in it. It has one purpose. Make time effects and subscriptions available to Hyperapp programs. To learn more about this package, visit the official documentation with the link above.\n\n### Listening to global events\n\nWhenever you click or move the mouse anywhere on the screen, press or release a key, scroll the document view, or move across a touch surface, the browser will fire an event you can listen to. You can react to the browser's window or tab losing and gaining focus; for example, when the user looks away, you may want to cancel an expensive subscription, pause video or audio, and so on.\n\nIn this section you'll learn to respond to mouse and keyboard input, and sync up with the browsers natural refresh rate to create an interactive game. Even if your goal is not building games, taming the mouse and keyboard will be useful when registering application-wide keyboard shortcuts, implementing a drag and drop feature, and detecting when the user clicks outside of an element.\n\nLet's start off with a couple of questions. What are the current mouse coordinates and what key was pressed? To begin, we'll need the [`@hyperapp/events`] core package, so make sure to install it first. Then, import the `onKey\n\n```jsx\n```\n\nTyping practice\n\n```jsx\n```\n\nSnake/blockade.\n\n```jsx\n```\n\n### Implementing your own subscriptions\n\nThink of subscriptions as orchestration for events or virtual DOM meets event streams. Or just a declarative API on top of the browser's imperative event-driven paradigm.\n\n```jsx\nconst fx = a => b => [a, b]\n\nexport const Sub = fx((dispatch, props) => {\n  // Subscribe\n  return () => {\n    // Unsubscribe\n  }\n})\n```\n\n## Effects\n\nWe run programs for their side effects. Likewise, we want our programs to be predictable, easy to compose, test, and parallelize. JavaScript's single-threaded execution guarantees that operations are atomic; two functions will never run at the same time, and we don't usually need to worry about concurrency, deadlock or race conditions (at least not the type of race condition caused by interleaved multi-threaded code), but we can still shoot ourselves in the foot by uncontrolled, indiscriminate use of side effects.\n\nHow can our programs be pure while conversing with the outside world? Rather than setting a timeout or making an HTTP request, an action can return a description of the work that needs to be done, and Hyperapp will figure out how to do the job behind the scenes. Like the view function returns a specification of the DOM, but doesn't touch the real DOM; an effect describes a side effect: creating an HTTP request, giving focus to an element, saving data to local storage, sending data over a WebSocket, etc., without executing any code.\n\n{{TODO}}\n\n{{\nEffects are not built-into hyperapp, instead we need to import modules that produce the type of effects that we want. These modules encapsulate the implementation—the part that tells hyperapp exactly what to do. In this section, we'll walk through concrete examples that show how to use several Hyperapp effects to create timeouts talk to servers, generate random numbers, manipulate the DOM, and much more. Finally, we'll learn how to create custom effects and discuss when we might want to use them.\n}}\n\n### Delaying time\n\n{{\nInstead of having JavaScript execute a function immediately, you can tell it to execute a function after a certain period of time. We could've chosen from other more realistic examples, but the timeout's minimal api surface makes it a perfect candidate to introduce effects. Let's start with (example description) that demonstrates the gist of the idea. First, we'll import the effect we need from the `@hyperapp/time` module. Next, we'll create an action to (do that thing). Finally, we'll initialize the application and start the effect at the same time.\n}}\n\n```jsx\n// TODO\n```\n\n{{\nUp until this point we've used init to describe the initial state of our application, but like every other action, it can return a 2-tuple state-effect pair. Think of it as a sequence that describes what the state should be and the side effect we want to produce.\n}}\n\n### Talking to servers\n\n{{TODO}}\n\n```jsx\n// Gif Search\n```\n\n```jsx\n// Currency Converter\n```\n\n### Manipulating the DOM\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { focus } from \"@hyperapp/dom\"\n\nconst SetFocus = state => [state, focus({ id: \"input\" })]\n\napp({\n  view: () => (\n    <div>\n      <input id=\"input\" type=\"text\" />\n      <button onclick={SetFocus}>Set Focus</button>\n    </div>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Generating random numbers\n\n```jsx\n// Roll the dice game\n```\n\n### Implementing your own effects\n\n```jsx\nconst fx = (action, dispatch) => dispatch(action)\nconst Invoke = action => [fx, { action }]\n```\n\n## HTML Attributes\n\n{{TODO}}\n\n### class\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const ToggleButton = ({ Toggle, isOn }) => (\n  <div class=\"btn\" onclick={Toggle}>\n    <div\n      class={{\n        circle: true,\n        off: !isOn,\n        on: isOn\n      }}\n    />\n    <span class={{ textOff: !isOn }}>{isOn ? \"ON\" : \"OFF\"}</span>\n  </div>\n)\n```\n\n### style\n\n```jsx\nimport { h } from \"hyperapp\"\n\nexport const Jumbotron = ({ text }) => (\n  <div\n    style={{\n      color: \"white\",\n      fontSize: \"32px\",\n      textAlign: center,\n      backgroundImage: `url(${imgUrl})`\n    }}\n  >\n    {text}\n  </div>\n)\n```\n\n### checked\n\n{{TODO}}\n\n### selected\n\n{{TODO}}\n\n### multiple\n\n{{TODO}}\n\n### innerHTML\n\n{{TODO}}\n\n## Techniques\n\n### Testing\n\n{{TODO}}\n\n### Hydration\n\n{{TODO}}\n\n- Hyperapp will try to hydrate child nodes instead of throwing away your server-side rendered content. Hydration recycles existing DOM (usually from server-side rendering) rather than create new elements.\n\n- Hyperapp works transparently with SSR and pre-rendered HTML, enabling SEO optimization and improving your sites time-to-interactive. The process consists of serving a fully pre-rendered page together with your application.\n\n- Then instead of throwing away the server-rendered markdown, we'll turn your DOM nodes into an interactive application.\n\n- Hyperapp expects server side rendered content to be identical between the server and the client. You should treat mismatches as bugs and fix them.\n\n### Navigation\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { location } from \"@hyperapp/location\"\n\napp({\n  init: () => ({\n    location: location.state\n  }),\n  view: state => (\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      {state.location === \"/\"\n        ? Home\n        : state.location === \"/about\"\n        ? About\n        : state.location === \"/topics\"\n        ? TopicsView\n        : NotFound}\n      }\n    </div>\n  ),\n  subscriptions: state => [location.onLocationChange],\n  node: document.getElementById(\"app\")\n})\n```\n\n### Working with forms\n\n{{TODO}}\n\n```jsx\nimport { h, app } from \"hyperapp\"\nimport { preventDefault, stopPropagation } from \"@hyperapp/events\"\n\nconst SubmitForm = state => [\n  { ...state, otherStuff },\n  preventDefault,\n  stopPropagation\n]\n\napp({\n  view: state => (\n    <form onsubmit={SubmitForm}>\n      <label>\n        Username:\n        <input type=\"text\" value={state.username} oninput={UpdateUsername} />\n      </label>\n      <label>\n        Password:\n        <input type=\"text\" value={state.password} oninput={UpdatePassword} />\n      </label>\n    </form>\n  ),\n  node: document.getElementById(\"app\")\n})\n```\n\n### Using external libraries\n\n{{TODO}}\n\nMaybe you've run into a situation where Hyperapp alone isn't enough to do what you want and you are under a time constraint or need to step outside the boundaries set by a functional paradigm. In this section, we'll learn how to integrate a third-party library with a Hyperapp application.\n\n### Animating elements\n\n{{TODO}}\n\n## Optimization\n\n{{TODO}}\n\n### Keys\n\n```jsx\nimport { h, app } from \"hyperapp\"\n```\n\n### Lazy views\n\nImmutability makes it cheap to figure out when things are the same. It guarantees that if two things are referentially equal (they occupy the same location in memory), they must be identical.\n\n```jsx\nimport { h, Lazy, app } from \"hyperapp\"\n```\n\nPerf overhead you say? More like perf benefit!\n\n## Examples\n\n- [7GUI] - A GUI Programming Benchmark\n  - [Counter]\n  - [Temperature converter]\n  - [Flight booker]\n  - [Timer]\n  - [CRUD]\n  - [Circle drawer]\n  - [Spreadsheet]\n- [TodoMVC] - Helping your select an MV\\* framework\n- [HNPWA] - Hacker News reader as a progressive web application\n- [RealWorld] - Fullstack Medium-like clone\n- [Starter Kit] - Everything you need to start building applications with Hyperapp\n\n## Ecosystem\n\n| Package                            | Version                                                                                                 | About                                       |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------- |\n| [`hyperapp`](.)                    | [![npm](https://img.shields.io/npm/v/hyperapp.svg)](https://www.npmjs.com/package/hyperapp)             | Hyperapp                                    |\n| [`@hyperapp/html`](/packages/html) | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg)](https://www.npmjs.com/package/@hyperapp/html) | Write HTML using functions in Hyperapp      |\n| [`@hyperapp/http`](/packages/http) | [![npm](https://img.shields.io/npm/v/@hyperapp/http.svg)](https://www.npmjs.com/package/@hyperapp/http) | Make HTTP requests in Hyperapp              |\n| [`@hyperapp/time`](/packages/time) | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg)](https://www.npmjs.com/package/@hyperapp/time) | Time effects and subscriptions for Hyperapp |\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"7f2ae319ea6dbdd48318a9bbbaf671fe52cb4841","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.22","_nodeVersion":"12.4.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-vs+uG4LXKaUgw6mOjB/PfkBD8WAsBULJNKXIHgjP2sdB8CRXUiCJM2BEtSIXkW0OvqHDMRaFbeo6oHi+W69JNg==","shasum":"2e5ab48e8ab5718b83823ceb42bcdf60defd7ad2","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.22.tgz","fileCount":7,"unpackedSize":90841,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+lPkCRA9TVsSAnZWagAAdGcQAKTwkWt/xy4ArLQU/vvJ\nzZJxwALOnnveeeM4zoFo3frvO/VdWf/PGRkZkszUH9NKgDEyLng/XWVXN+Ml\nffV9ZCCJ5+8l7vtgICwqHPi0ssF2faTpSExNEOvfbgmGm9wzL4fZr2D5VyPI\naJXMFfqGDeigDk3PTkoeG/RqgwwT3yosmzLRHcKnbZpJTred/MPcjMM7Fg/Y\n78K1U/4KR+tIhC9LnqAjfyKhpA30FeJpE2ojahlUfMxukPd1eNEhCkzcoxog\n5wUN7rQynhGNnj/94hFhtR+rd/PgfLJih+Gc/5heZWyUOLis1TZirwBmLU7m\n9RYvmslYY4+WFmpngqKsm8SfxhFVuDxpxKW7AWnNDOwVMLkf7uYh353IX8Be\n7WokElkjfwaQd36Go5aXI6n0VSMkFrSv/I64N4sT0hE+BqwV68LRm7z8M1f+\nZUf7P5XP5tiMPF3HtEDzbNPVvukr96CDfAX+laW1Jel6MgOy0OcTlJnjUH23\nzln3tbiuAAKD/OdE8LAqkKzdNhK1APX3CjEVb78ShuEfSlD6j1SFtNfiEBOe\nFCHN4I+jwcMJkPSUAWWYqczEZ8RqeLnQurPnAvn/tkXi7vxmnXGDJZcAu0r7\n7RhtWg+RW7UGJvNcwjm/BhUeelZ+CLpONXy4gcGQj2/ZgyfcP3wmZDibd2Pj\nxA9b\r\n=3Bfz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDl8jewwXMs52FV4POd/4W+TctBg+tJBTB2e3UCSa0AkAiA/Xg5LgxfkWNzqGzWgd6CXH+YTsyObsnN0zVjz181/MA=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.22_1559909347346_0.6519479789159253"},"_hasShrinkwrap":false},"2.0.0-beta.24":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.0-beta.24","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://github.com/jorgebucaran/hyperapp","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"^1.70.0","terser":"^4.1.2"},"readme":"# Hyperapp [![npm](https://img.shields.io/npm/v/hyperapp.svg?label=&color=0080FF)](https://github.com/jorgebucaran/hyperapp/releases/latest)\n\n> The tiny framework for building web interfaces.\n\n- **Do more with less**—We have minimized the concepts you need to learn to be productive. Views, actions, effects, and subscriptions are all pretty easy to get to grips with and work together seamlessly.\n- **Write what, not how**—With a declarative syntax that's easy to read and natural to write, Hyperapp is your tool of choice to develop purely functional, feature-rich, browser-based applications.\n- **Hypercharged**—Hyperapp is a modern VDOM engine, state management solution, and application design pattern all-in-one. Once you learn to use it, there'll be no end to what you can do.\n\nTo learn more, go to <https://hyperapp.dev> for documentation, guides, and examples.\n\n## Quickstart\n\nInstall Hyperapp with npm or Yarn:\n\n```console\nnpm i hyperapp\n```\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import it in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry; modules are supported in all evergreen, self-updating desktop, and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp\"\n</script>\n```\n\nHere's the first example to get you started: a counter that can go up or down. You can try it online [here](https://codesandbox.io/s/hyperapp-playground-fwjlo).\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp\"\n\n      app({\n        init: 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onClick: state => state - 1 }, \"-\"),\n            h(\"button\", { onClick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nThe app starts off with `init` as the initial state. Our code doesn't explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a plain object representation of the DOM known as a virtual DOM, and Hyperapp updates the real DOM to match it whenever the state changes.\n\nNow it's your turn! Experiment with the code a bit. Spend some time thinking about how the view reacts to changes in the state. Can you add a button that resets the counter back to zero? Or how about multiple counters?\n\n## Help, I'm stuck!\n\nWe love to talk JavaScript and Hyperapp. If you've hit a stumbling block, hop on the [Hyperapp Slack](https://hyperappjs.herokuapp.com) or drop by [Spectrum](https://spectrum.chat/hyperapp) to get support, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll try to help you out.\n\nIs anything wrong, unclear, missing? Help us [improve this page](https://github.com/jorgebucaran/hyperapp/fork).\n\n## Stay in the loop\n\n- [Twitter](https://twitter.com/hyperappjs)\n- [Awesome](https://github.com/jorgebucaran/awesome-hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"8576b51f13f43bee54f5a5a9679af4d708d40354","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.24","_nodeVersion":"12.6.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-6SWvIm7xBzVOc5iGTcIar61mRIsCX7pJyynhZQh9slpcIxYZlz3Y3Cx3HLMNFnwEMKitbc3fE0EUsiv3gQtq/g==","shasum":"5d0cc1f96758995cab2ea4b7190f8c47581955b6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.24.tgz","fileCount":7,"unpackedSize":44873,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdO1G2CRA9TVsSAnZWagAAv/QP+gLpYt7cvE8HX97ybTXG\nhgTfEAuCZ24cBzU43u7nN2aUAeAMUfRc9KmJCNytu8d/0RcwEdErwzCcIR7C\nKplcO+3KK8Ho2CC2Y7TZXhOZZSpDWi2F4L56+Z47n5NfMZGf98C7RtCQ/cKf\nHo7uy2Ln+rXTpmUzNw+gxEgpD9qpN0soh4Kh0wkmkowljXbdSy/5lYsQyh/6\navM68axOfxOJ33QG0/RGw2mgEeCSjhLodj0YG+gPqtsmGGJX5lUr7L2PAaH+\n9DwAWPdDpXQGlW3DZbrbtaljT/g2wVuzJtyQ7xwivP/NekDHkF1ZH90Vkqci\n5pn8YPgET0WwM5gLr4/QrVbTtYgzfR3Tr4Zd0ewUKspso8qKheAeMqXXpn2f\ngrqFH3oLjMtzCN++ms0nC4nTLgBezMjJyAKM3GuiA16HcIix0VrbogxktCr/\ncngEeUsMtgJiuNI8j7qsZnvZpsqDDb5z55IlPR0BOXlHqaA6v1DMaLIVMg5d\n9B6GB9jYgUZCPhJn3uGZC/Pa7hTOdrQ4g0iNa8MYAVGJF2OR2IVjPwCNL9OR\nEX/pOb8hazlg0Xt/DbMvgc89F3bFYnJg8UmFMpr4TGzkMAHB3IleDIA8XKRa\nnPW2p0j49HhNg1VrF1pnaDpFHMBGHLbloqrnA26jrgFpsKVRHFHBhrz7HdvR\n5yG8\r\n=kCe6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAkm/JArfo01zIgwq10lmmAp6zpNnS4uU0twRCsTNQpFAiEAxdvLAvpuWFO4ldjQiVYRq5zbzVPc0cQYzloLQuNAlm0="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.24_1564168629733_0.9263581208215923"},"_hasShrinkwrap":false},"2.0.0-beta.25":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.0-beta.25","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"^1.70.0","terser":"^4.1.2"},"readme":"# Hyperapp [![npm](https://img.shields.io/npm/v/hyperapp.svg?label=&color=0080FF)](https://github.com/jorgebucaran/hyperapp/releases/latest)\n\n> The tiny framework for building web interfaces.\n\n- **Do more with less**—We have minimized the concepts you need to learn to be productive. Views, actions, effects, and subscriptions are all pretty easy to get to grips with and work together seamlessly.\n- **Write what, not how**—With a declarative syntax that's easy to read and natural to write, Hyperapp is your tool of choice to develop purely functional, feature-rich, browser-based applications.\n- **Hypercharged**—Hyperapp is a modern VDOM engine, state management solution, and application design pattern all-in-one. Once you learn to use it, there'll be no end to what you can do.\n\nTo learn more, go to <https://hyperapp.dev> for documentation, guides, and examples.\n\n## Quickstart\n\nInstall Hyperapp with npm or Yarn:\n\n```console\nnpm i hyperapp\n```\n\nThen with a module bundler like [Parcel](https://parceljs.org) or [Webpack](https://webpack.js.org) import it in your application and get right down to business.\n\n```js\nimport { h, app } from \"hyperapp\"\n```\n\nDon't want to set up a build step? Import Hyperapp in a `<script>` tag as a module. Don't worry; modules are supported in all evergreen, self-updating desktop, and mobile browsers.\n\n```html\n<script type=\"module\">\n  import { h, app } from \"https://unpkg.com/hyperapp\"\n</script>\n```\n\nHere's the first example to get you started: a counter that can go up or down. You can try it online [here](https://codesandbox.io/s/hyperapp-playground-fwjlo).\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <script type=\"module\">\n      import { h, app } from \"https://unpkg.com/hyperapp\"\n\n      app({\n        init: 0,\n        view: state =>\n          h(\"div\", {}, [\n            h(\"h1\", {}, state),\n            h(\"button\", { onClick: state => state - 1 }, \"-\"),\n            h(\"button\", { onClick: state => state + 1 }, \"+\")\n          ]),\n        node: document.getElementById(\"app\")\n      })\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\nThe app starts off with `init` as the initial state. Our code doesn't explicitly maintain any state. Instead, we define actions to transform it and a view to visualize it. The view returns a plain object representation of the DOM known as a virtual DOM, and Hyperapp updates the real DOM to match it whenever the state changes.\n\nNow it's your turn! Experiment with the code a bit. Spend some time thinking about how the view reacts to changes in the state. Can you add a button that resets the counter back to zero? Or how about multiple counters?\n\n## Help, I'm stuck!\n\nWe love to talk JavaScript and Hyperapp. If you've hit a stumbling block, hop on the [Hyperapp Slack](https://hyperappjs.herokuapp.com) or drop by [Spectrum](https://spectrum.chat/hyperapp) to get support, and if you don't receive an answer, or if you remain stuck, please file an issue, and we'll try to help you out.\n\nIs anything wrong, unclear, missing? Help us [improve this page](https://github.com/jorgebucaran/hyperapp/fork).\n\n## Stay in the loop\n\n- [Twitter](https://twitter.com/hyperappjs)\n- [Awesome](https://github.com/jorgebucaran/awesome-hyperapp)\n- [/r/hyperapp](https://www.reddit.com/r/hyperapp)\n\n## License\n\n[MIT](LICENSE.md)\n","readmeFilename":"README.md","gitHead":"cb7c253fb2a7a2c3ae70c8c8a7b7328edf626b7f","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0-beta.25","_nodeVersion":"12.6.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-iXTi6Bnw/RL358Vsx6tKp9fnxzxSwpjZvKwBCi5K6DX55PA+JY6jiSBqOcpEgoBVQDfG3NaAOx7HCEyQ38B6yg==","shasum":"eaefee435ac2689a0331dada51dab5979a75c6c1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0-beta.25.tgz","fileCount":7,"unpackedSize":44853,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdO1ZoCRA9TVsSAnZWagAAFDYP/3K5L0t67REmynEf6BaT\n4bmTiK7pN1Mjh3Q9irEgIO01iDMpLlzgPwJpt5raR0uPxFYQgMhT8fGAnXTI\nxrD+giPkEZZLKQ6h7EMrwd6FtGnQPkouYZxKjQ1n4Rej+2PS7oSKuK1L7GZ4\ntRO3SgXjtIyZFwjKPCrXMRxQbC/jvkCxxAhKFBCW4CzqhZoI5nbQ0QgFt+/G\nXF+jsjBBFl0Qkg8QzGw61rIAtrNdLH0/AW5/0cjgzbgEoTwTtOJheLYuyFxQ\nA2iWj6wWtcD3Cdo7cyCGImRbMw0FqsqWusxblIacxoNr3Lu7TL1m9AVOPQ7d\npUjY8JAt9iHgs6TnSlnw9Ib4bFlO369aabvZzYT3kXonOTOozObw54Vzdxu5\nPU9hPiM3z250URDcARf6Hg3VMEOvExHlGNg9UUVVmJHl6Bt7poXx2sQlm0+M\nv5OxfCWPlsqTp2mGij7x6D+oaSJZTRGcbJ4sBe3Ylxv2l1GN87teMr2GC19j\nwTqR+09LlBj+FjJsIOBCan3aW9PsqKuCr3LvT1cVR+K+nWuTXphi82gf16ps\ngsHNM9JdDecGHgig90D7hU7wZ/kawvIkkHQ44iKV/wnASJpl9Bi26HDnQ3Nv\niTyn4jRo+HiWHVkFDvr5sogYyHnyKTNajppbhi94/j3Biy1d2nrj9ul/co72\nrVhI\r\n=rt1p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5W/ewzoUw1eIQqvLSYU4TRelsEP7mZCWtSgT0VeUHpgIhALgQEqUAhDOn5ZqKWo6eVVr2LiYhEJVD+SoHtaEa1wcs"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0-beta.25_1564169832009_0.7447833015130509"},"_hasShrinkwrap":false},"2.0.0":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.0","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"^1.70.0","terser":"^4.1.2"},"gitHead":"6fa24d3267894554fe3809eba337eaada47776b4","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.0","_nodeVersion":"12.6.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-WiXOnHUH4sf483oGH3MECI5YfHhqQSVoNHd/vV2WOBH/+BEnRh3l8oWaJvix42ajIJq4I9mIAzXP+ncWBCV2gA==","shasum":"f635231fbc4a9f02867df98d433656d0faceced4","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.0.tgz","fileCount":7,"unpackedSize":44845,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdO1p+CRA9TVsSAnZWagAA+egQAKDZnP82DfsZlrKkWpo3\n0k2R3IIR7I5CzhYwD52ernk4fkfJNW5xl+JN1VbSt+cyNFluZHndlinoUEID\nTQUjqacf0vr1cEi1gJQhORnixCh2oeBitMK2MvOqHKhOWJssbhHJdZX2ccI5\n/gGYxyUG15wkxQ7Dq6wPebEd01U7lCa4sn95KTelFUA7EKXHom0fP7nkPOXW\nTq7dKWpTtRAeFg4qiGgX/ZtqwBrtgR2KS48g2F84ZLtSsWxUCXiOUu1Q3DO9\nWD28yOrritKmbQUcPSNCs4JxIADDM6jvmmvLRiYtcU1prb6hwv7ofi+XA5+p\nkS6MppTSb1YWoorVi8iB7WiQJPjzUws7jahJPYn3NKOxZ36c3HCYFOl09Y7z\nYekHvsIcEMn9Jb1uR6glCqOvOygGFPJHaQG3pzoOVB0lPOyYgt/fA0p+VFZ3\ndgT7wcEgbFzP0FSfM1MrumWO3b3f69VBPP4do83Nj0uymg9b5zE2p5EJeXag\n3OzHFOqz3R0SPAnmQypAKNtDaynlQk7AuFdbwu7kimUhNE+nvcMub2HgjT21\nB3U4KJZKEt9SpoVd3NJf5+8SgsVQ22RFY073BUCg854YzKGDt5NpahoZ3bN5\nE4POOtwNRRtmoRFsNV5EUWQQFUylI7Dcz5li/UdzxXdqt18IPSUMNbh6bNQx\nqChg\r\n=Yv31\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIExTe/n+zhCvPaXTxyjZeiqvSKamU3J6n2QMl+KnqmOXAiAOGmtuByf66amCBkkzlu5AWn1GlfihOatyZjihAm9TaQ=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.0_1564170878179_0.665971569201707"},"_hasShrinkwrap":false},"2.0.1":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.1","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"*","terser":"^4.1.3"},"gitHead":"a0942dae7c0cabab49994d99b6fbd347b587ca8b","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.1","_nodeVersion":"12.6.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-ckAF95l04Eld6hVGlq48FIcFNRTCyvMJtKqNoaCu9fiSXPOKv6pq7QQe5Lvnlt28IcMiFu10cKlX8J+xDVpRbQ==","shasum":"34a9a0ded0c18c979a6ddcb15633c616da91c905","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.1.tgz","fileCount":7,"unpackedSize":45040,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdR6bPCRA9TVsSAnZWagAAh2wP/iQcxFXOzXdxrh5vqF5v\nrSgLvE2EmssGXPEnG/lLnMTvbjGVuATQREcxsQUSKupW3whxmzQ+eP4T6BON\nu79hDd68JNq6ebPo2ZeeG6zDvEKPdBUfdLGELI+p+BjT7Ph0E3Mes/1R2sWt\nEdrhkY14ff6p9fNLHYXMO8OgSs29GUxU7SOHkopD4nzAH8qjaw2QgumOUprc\n8RibVkGuHsSiHqm1G06NbzYiRcueLDZNOBDYphN+kG1j85Qfyt+Q9SROziKB\n+/PIBoHqvDC1xqKQt4KSYJF1YI8A+5rIUJ5tXk94BVEa6/uIqQYxBalW/vou\naTIZzgRzDhNTICUCkC1X+v9zyOTOEVrXZrfeeOS/dmGZms8tCITmwfTnqNae\nVchAVdH10acBbUMK3u4sxrbLH3/QCccbx4ce8Pca1voJiXUp5UIupLNpw9WO\nkXBzxvjdYshGr0/qa5AjuJx+m4LHhPnbSyVPFvX1/uxGsDJxWryR0NrVWrLJ\nyNjDo85l8RWKHC7ykaRlGSjKkwkpdGAB2j5F2I6I7shUQcs8Hc0kJ4ttmOLX\nyLlPDpboZn0QEvva/XlaR8Rfaos3s3r4SeDpAQ+PsN7ulAtVpmQV/wmyDGnP\n+VdyUVmV25494LrqOy3Rh7hT03h5EpAE+U32tYmAh4U9pYV14ijFCXi/KpbW\nBClX\r\n=jyHU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDoVLDmxBIluWmjQDRcBl6MSx4/ElWackEdZ28WVmwObAiEA8IpmW+ql1FNWwKHU6NljXWJpaFQ417Cr0+6KG5FOyQY="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.1_1564976846915_0.2302589579144767"},"_hasShrinkwrap":false},"2.0.2":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.2","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"*","terser":"^4.1.3"},"gitHead":"8b6eded68c99f300d52e292bdf1945d8b285a0f5","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.2","_nodeVersion":"10.16.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-geuoUHkrAQdn1JwMTGH2E0yCOxitJaL/KRL3D8cate+AexA++S9c7kwXLDqIkYjBjU/Cb6NIVHlo4dgpaiGhzA==","shasum":"1d39e344a70041e28ed24fa110bb8d1f3eece635","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.2.tgz","fileCount":7,"unpackedSize":45375,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdnx0HCRA9TVsSAnZWagAAJG4P/1Ci8G+LCTJ3bJRszF2i\nXx1pNjOVPDxmBQmwr2QJc12B7QBB/8ZhqS/UQ5FUjtQOBo7tynfRUCYzt68z\n+ECSlVYcmRrisvIVxynQQ4CkKJxW5M61kTllhPiKOlE88QtZvEWkpwiNBla5\nkItRgKuHBmOWuzHQ065GZ3kZGRiltoSYfx0ysCQbfSnr2Rtve9N8Hy4PdaIZ\noQeTM8pdeOATv+9f2JmBsUV54V4/nmdHVrx8hTIqUBxRegoD2ff3rcVCPMhU\nOE5+7+02D52XreiOdmX6D4RgJugSXZNFEK/ssf5l1kzcybTrB6BjcjwT/h+X\nDUuypEmXzqBGghG0vB+ca/RUJSMRAhrLGeB7ji6SgjHMSej/Mnc4gk54LPb6\nQ2FGRR2qKqV+1iWMa3ISsAv6izmYcX9jlmzHV9BxNippceiGAmGyHZHpJqvI\nmgj1vzAae1FiG4x+ItoJsMs5X1LCE88XNtRTtOstXpk3pnDcumcvy6HvXKvg\nqQwM4BK5iwdCOr4EuoL+5zSRoMucT3xiWlnj9RLPfQJChPug/KOBo2b5NLtF\njqRl13l7htZED4knAbQLb0+o0R07gDkEP6Q//gLAQa5l3U23FWvTgmVq/uHs\nOMN4/OlD0y7YOOObsPZk9ZnN1DiCwNwAClX95AvSpKDhrVYm7w4l6WyarmNY\nEieE\r\n=5RAz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHcboV0CLxF//UiZJcbU0j0YSk4h0WloH8uPZAsiAZYEAiB9swe0qrj7lEfRnjCtpg0du7p1y8953WyGvfvTmFtJAA=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.2_1570708742231_0.11039062945364031"},"_hasShrinkwrap":false},"2.0.3":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.3","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"*","terser":"^4.3.8"},"gitHead":"a97d414419e1a51eb44e635f5df850eea11fd90f","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.3","_nodeVersion":"12.12.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-SiTeX3kYK8ggjNqAAnyi2QRUHRCZ87L35pn66LevbI+TLp1wSsruKd1BD6c82s5ve9L503/HwQtpdTA0f5Wk9w==","shasum":"15000a828fcd680ab04256a312e63b2caea99a4d","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.3.tgz","fileCount":7,"unpackedSize":45338,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdoryhCRA9TVsSAnZWagAAd0cP/jrolxp9HM8lE/j6Dw1J\n46+lKKAEos4VENVqxjos54Ho2pKTQqKj3h1KNb7s/8oCMinKncJPgqyHO2+1\nVjc9SY/CwB352JVm4ygl6tSJzb9hvvcmwP5ArPVEzhdpO6YUd9SDDDludzMr\nakZRix73hfWEAZhqdQgBL9N2CvbwgjDb8NE5KmvZKRU7zbQqln057h9iZCMp\n4BuEt28w/vDH8M+WuB5KiEG6kH0YzRqMyLmUjnI8YIIc5jQGlH9pQsgzvVZY\nq1Bagbtl4mp9HvyQVVLTXk+RySUp5hLs8en3KUbWZE7CuQUZi6mQ4ZHnPN6C\nY0SoF8i7JFQxoi/KmQU0HsKaEcO5hggsM8hrLghIP1WYFLam95BXmhS7j0ol\njWTjDUyA06vSobEiStNodpi2jVVIgBoUA0scZIdMcWP8W7PalAR0sZy9ztvb\n071dUd5KE7zfEAj0SgpY+osRMmrWowCHcLT26RhfUznnBzTvGvTQUMSePUjY\nYeT60hdGfAfnRqWTOiyOmcnSF0z5p6QK7FGpu5t7/IdStGvgoucXUpJOSHTV\nYhTUUd8C2g+5lbemJW6BXRyWo+Z1toKnFTpjaszj5AoUb7iv0majNXZPQAoe\nAPXAolJePPH3gopmfieJvgkdhrqfB7amF2AtvXDJ+wADjDv7NpB1SfBgQIgZ\nTdZw\r\n=5WuJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFcHut0FmhqtWVTIf6AN63Dz03auz5/6qmrpqF9gHyonAiA6KBeuRPMWeinh/AqLCcKQnYln0GYoM86qbVFcbhP26g=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.3_1570946208989_0.6012806716649619"},"_hasShrinkwrap":false},"2.0.4":{"name":"hyperapp","description":"The tiny framework for building web interfaces.","version":"2.0.4","main":"src/index.js","module":"src/index.js","unpkg":"src/index.js","browser":"src/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","virtual dom","vdom"],"scripts":{"test":"nyc -i esm -r lcov testmatrix test/*.test.js && nyc report","build":"export dir=${pkg:+lib/$pkg/} pkg=$npm_package_name$pkg; npm run bundle && npm run minify","bundle":"rollup -i ${dir}$npm_package_module -o ${dir}dist/$pkg.js --no-esModule -mf iife -n $pkg","minify":"terser ${dir}dist/$pkg.js -o ${dir}dist/$pkg.js -mc --source-map includeSources,url=$pkg.js.map","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+lib/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+lib/$pkg/}package').version\")"},"devDependencies":{"esm":"^3.2.25","nyc":"^14.1.1","testmatrix":"^0.1.2","jsdom":"15.1.1","rollup":"*","terser":"^4.3.8"},"gitHead":"1d84ec916578f2adc0aa9cbe70b6b9b1fa74a548","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.4","_nodeVersion":"12.12.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-1S0KIsyB97S/hH84GkuYjH/hmpnNQ546x16o+W7g/PnszxRPudJlwwGBKKnaRVL7x+dyevvuX4XLH67FooEt4w==","shasum":"0be1bdfe46b28c73677adc408ce3a73f79cfd03f","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.4.tgz","fileCount":7,"unpackedSize":45256,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeLrqaCRA9TVsSAnZWagAAwf4QAJbm6nG+dUgwgq9xsJlE\n3DP3ZywCIGEWkCv/a1lklyyRWYJXu9Vew/QjEwVhX/X4kvaEHEvtNnbAdM5I\njwlc2l2g0UoZJwzpYi8GigtFojrcSnW4dUZ6FifSFIW6CryR4vX9r5s5TxTO\nCFq8yF+lKIrEpLweFJ+oVXOvUH1y6tLhIeJtf7nb7XJ0Sdip4PA/YjlJ3Bd8\nkr4UYq8R8zI/4sNDEs0rmO3ZBDmDCniY1BexTZGN9UrdjeALQomKTX4FtHmg\n+KRJ6+V8xkuSg+bjQkug9Rfz+r3C0l4upHpPbcHyipD9S/IovX3Td9imx9rg\nmR/Yd2nrnCTkdeBOtMQDkSLBb3ayV/5Gny/0VFolNbtHCVRqk06gLwAu052+\nS+q72N5xd1cFU6BN8X/qdn5upJvsrCikQzX9bBHhrBXVHkP9iXQf0F/m9tyc\n960Qn0WPlKk8G/a6YSXrQooPohyN1X02yHDpbSHQ4dxrLT0CjiDffRv1rCHi\niipJA3ydm3jvBB7iG57qbYeVQfq0/+mtPyQeLtIDh+ABlR5ie3Q6dohuBNYG\nCvXtn72I840+k8ILyFyIoPviXiX4uYXPsF0uxJdaOYMc+wS/q6pLqaM2BXqV\na5WyDxWp2hUQNxFzxzzxd7KVsUoz8LFCfhSZc1EYztde9mOqv1OzKhX5+sbS\nVrbP\r\n=Y7Mf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcBgCKhqWoZKFWpVkIDM0abUjehvdd0Eqv5kuFFy7PagIgHIcF5vJOeUCAbP4st0fepgCTeKFj/SBNTjTTFpsQaaM="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.4_1580120730333_0.3751195848524356"},"_hasShrinkwrap":false},"2.0.5":{"name":"hyperapp","description":"The tiny framework for building hypertext applications","version":"2.0.5","type":"module","main":"src/index.js","unpkg":"dist/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","vdom","web","app","ui"],"scripts":{"test":"c8 twist test/*.js","docs":"cd docs && npm run build","build":"export dir=${p:+pkg/$p/} p=$npm_package_name$p; npm run bundle && npm run minify && npm run unpkg","unpkg":"terser ${dir}$npm_package_main -o ${dir}$npm_package_unpkg -mc --source-map includeSources,url=$npm_package_main.map --module","minify":"terser ${dir}dist/$p.js -o ${dir}dist/$p.js -mc --source-map includeSources,url=$p.js.map","bundle":"rollup -i ${dir}$npm_package_main -o ${dir}dist/$p.js --no-strict -mf iife -n $p","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","release":"env msg=$(npm run -s message) npm run create && cd ./${p:+pkg/$p} && npm publish --access public","message":"echo ${p:+@$npm_package_name/$p@}$(node -p \"require('./${p:+pkg/$p/}package').version\")","postinstall":"echo \"Love Hyperapp? Please support me on GitHub <https://github.com/sponsors/jorgebucaran>\""},"devDependencies":{"c8":"*","twist":"*","rollup":"*","terser":"*"},"gitHead":"936eed793cbf2f466f1c97f19ce6ed9028fd456f","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.5","_nodeVersion":"14.5.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-j8podwsQAxotdLnBxCIjA4FD1ZzmSOUo1P4A2Q5SXod1ob1V90xYYNMwI9vXHx3Y3Fd3uJNB0zV0Xnd4HPQzlg==","shasum":"37f258d7603eb6a91d2a0cde1b9ad3f25153fe3a","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.5.tgz","fileCount":10,"unpackedSize":65969,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfDe+TCRA9TVsSAnZWagAACwwQAICbo+iIpHDQIUnKlvPX\nU7Uf9xEPvyudi4IpbwF+smpn+D866Yql/cNZLormJlPecIxhNZ3JMbGkUgJL\n812EbmCH3rVmLHSJdfbxN+arz508GKy4Lsv8TyIM+3hRbjC9vhh3nDDPlllQ\nKXyk0mlQO0bWaFvZt/ePpbdxlFsaClUqCjlWrsqMYo9xnGUqE2F14MwM8yqF\n3fuBy8IkH/P4CfiXoKDljF2qy9aVaUOTwbtWQXCbCBTUgFop5MgOtNJiBRbk\nd8F8TCz4d3O2fVBMqT0TZRUdvmd9njg0sZ+z3Og5BuFIbE79862fTXQ2Vh68\nxcH2vb6Y0Y2PQjqyyzNiURXgyxCo5jNHcyeEOS7wkI9MOG/GdRAv88q3mhqE\nX0v/zN/fFmSS05LbgHz0RoW2WutOcR32gROyJjRmU5VvQ+Jv6RDYfM6fHvNl\n+vJupmfys/vCzKTm+34JFpigSyKgK5AGltlHadAaPtz8auICzr5hDLb0T1iz\nBfQX4bXX985iKWZh2CLJjHRUP9l6M9/S8mKxrNwnXr4b1LQkBQWUdqmCq4F6\n9EFNBnN0+UBp1WgPtdQU62GoWQEzHiyPE/3lzg/1hU7B2CBfSIR4lBL0S3tr\nLO9TU3c7K+b5oyJvygT9QuglaVCB/SBbkVp38SdwZaaMQPeg3dnTHngjkS4Z\nrT91\r\n=/MeL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCiqSdqVfuVQ0/xcZ3TQ74BY1EXgawKmJSxNgwhikaiHQIhAP8tNtxMhZ+CpBFfOyFFYseHGLhKOFg52qmaZ8LcLaW+"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.5_1594748819021_0.2171778840838514"},"_hasShrinkwrap":false},"2.0.6":{"name":"hyperapp","description":"The tiny framework for building hypertext applications","version":"2.0.6","type":"module","main":"index.js","unpkg":"dist/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","vdom","web","app","ui"],"scripts":{"test":"c8 twist test/*.js","build":"env dir=${pkg:+pkg/$pkg/} out=$npm_package_name${pkg:+.$pkg}.js npm run minify","minify":"terser ${dir}index.js -o ${dir}$out -mc --source-map url=$out.map --module","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+pkg/$pkg/}package').version\")","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+pkg/$pkg} && npm publish --access public"},"devDependencies":{"c8":"*","twist":"*","terser":"*"},"gitHead":"a0b8f9e6c306f7bc0004dbb3566519041d8cb00c","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.6","_nodeVersion":"14.5.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-Kr145qAsIa5JNxrEay2UFBT6sanqZv2vL6Mkg9wjY9F+X/YX0ss2Xr7b9rLSFWzsnsh8ICzIAf1t3MOE4SO66g==","shasum":"84f49c632a229bb0cbc370322efd6f8c7adcf2e5","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.6.tgz","fileCount":6,"unpackedSize":29594,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfESZECRA9TVsSAnZWagAA7Y4P/judZ1EAXduYisihgOmf\n6fzUVnEKS6jkXc8qrUAxRLBUBxuYWbALAxG4DF6bV7HfWiKN1H/E2Zr8JH8k\ntM2QG6+v97LyR8wLwRXGGj8YqlADNSjwc+91YNZnkjvNeXrk4eExgEttWjEG\n/D48tUIJHz/M43cQ8tgjdeGHGwAx05DD+cIWlxI7eOi4ekn5INmffu+/4CYl\nyOz+btIw5VXsn5Db5RRtnqiGQXRvwzK1hKUib0BHqT6z/RN8OoaavarTpK3C\nycfd6Oa1WEStR8q5tUJVz4xqsOxJzuBZPpeYBHwcirFi9CTpgCYISJylL5M3\nj93h2Tm9jdpg1B2e8xqrQtpFKaFLqp3VgvaBH94X3r4DQwC0ZmwdakG1d8Ca\n2OZIcCfa6y+UZlGywuvW5KDfPf5ydQ0+HG8igJnhCGI7PnkWg1PIBpVxzOL0\nuR3NckV7Xn0IG4KMhTYXg5lw/Vmi4JjaVOhKP7YBZ/uIPg/Zpbm5woSOa2Rg\noSIK69PRTx2hmtgQH3fSnLgxyNRoFAjalA8sQF0XBu+qeECtEU6t8ews55Kg\nDKDxgf8emXPpMylpeLsZgtApJRPSt5JKgqHZqpIepVjQ54hO/QyBf6mr2P4i\n4peM/3TpoQXsGu7js3H1cThhV3e279x8/6YuRwyZjUPhpOUf9JOWPQMhmt0z\ns5It\r\n=u0Ma\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEK5NUPB0uEini8swt7YgJHA1JdchFGPpjK2bVYbVjiAAiAtgttQ6OPWqBzKimzijM0XrAeftQRe6RdXidP0MLqnVg=="}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.6_1594959428140_0.9530454416238863"},"_hasShrinkwrap":false},"2.0.7":{"name":"hyperapp","description":"The tiny framework for building hypertext applications","version":"2.0.7","type":"module","main":"index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"keywords":["hyperapp","frontend","framework","vdom","web","app","ui"],"scripts":{"test":"c8 twist test/*.js","build":"env dir=${pkg:+pkg/$pkg/} out=$npm_package_name${pkg:+.$pkg}.js npm run minify","minify":"terser ${dir}index.js -o ${dir}$out -mc --source-map url=$out.map --module","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+pkg/$pkg/}package').version\")","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+pkg/$pkg} && npm publish --access public"},"devDependencies":{"c8":"*","twist":"*","terser":"*"},"gitHead":"ee6671a089603a03ae3fcd1bdab3438c7cb98bdd","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.7","_nodeVersion":"14.5.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-Frx699txgsrw0TscpDXg04OgnOeV1Ds8ZADdkZ7yqb6hqL3vNNkEX+tGE81uFb1U00+j31xqZu5NdYedWrcfjA==","shasum":"8535176fa8477f96d9a04e219226cfb70efb28d1","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.7.tgz","fileCount":6,"unpackedSize":29566,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfESaFCRA9TVsSAnZWagAAnEwQAJo+Biw8hoChMRzMstGv\ngAoxeMz8i1b0cTgD7suy2tgkFhuErFnqtpN2gUrSr/KOgF4yUU89m6v74aq4\nBiq/grm74K2LtdyQrb7ju6FkU+Ss3TmY+GVZgYDoBYDGZZQ7oh/2bZTEzFrl\n4BSwnoSF7Qpg1KzD7Wz45D+hUXdU9UFYXY7vqfKYiJkK+29iAOmrqZ00ZNz+\nUv+xOrC/9gppREyEXwd376g//14FukbSGKF3jaFeVLkukNMKXXM+PjstYbWE\nYJgw2KFZwQPnh284TykcFwHxrW8nzuLRWZQHdkMTTmENsQNZeQY1laWKnXDN\nZyiIT/X6CWhRrQVNQzxbF7ntK03thYXYKQ9EfvrcBtznLkoEn08jfNRGdIIz\nF7s+zxURxvmUcg2NutQboqhaDxcyBEsT6VqSeHXC7Gd6l/Im7rLviluS6ouI\nVunsi5k6x33fhX0+TfRjcwX7qy2nFu2Nzgt+qxtR1tmqEKEmV1fIByjYJiUv\nnzDsh0AkfA79s/fHyC/TbLiHglJRSKBlth/ZzJBn2mqHuJyO+MHqXgfJ4R9j\nK9+TTMi8vcK6G//IGrVJ+3NAPnTviWUf7CAON/KwTrEaUNAHjzmTVEy6k+vf\nMdDkLXa3CSath4yI+AHEvTza6PAz2MNcFM/kdZTc9bzMMkLk0V0o1KYI4xyK\npi+g\r\n=uGD6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCDpvg/FrmQMADoMuzJWmbw93UHboxuxDHi5D6/Y7xlugIhAOdonAN+5oeP4mU4d4RahbwspiLsQYGlmj3ob4R1+Mmm"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.7_1594959492715_0.05712600164664883"},"_hasShrinkwrap":false},"2.0.8":{"name":"hyperapp","description":"The tiny framework for building hypertext applications","version":"2.0.8","type":"module","main":"hyperapp.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"funding":"https://github.com/sponsors/jorgebucaran","keywords":["hyperapp","frontend","framework","vdom","web","app","ui"],"scripts":{"test":"c8 twist test/*.js","build":"env prefix=${pkg:+pkg/$pkg/} out=$npm_package_name${pkg:+.$pkg}.js npm run minify","minify":"terser ${prefix}index.js -o ${prefix}$out -mc --source-map url=$out.map --module","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+pkg/$pkg/}package').version\")","release":"env msg=$(npm run -s message) npm run create && cd ./${pkg:+pkg/$pkg} && npm publish --access public"},"devDependencies":{"c8":"*","twist":"*","terser":"*"},"gitHead":"746f168d762b6e3abaf6e76e2bc295bcd08352d3","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.8","_nodeVersion":"14.5.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-RZxmJ3G4VcR23RZfmK6U8KR7wHhXrbXAhKvjQuyg/kAv1bEIymdxUsrJAwtfXj0aasGU7CDQP70Gb2KwfxgJ/w==","shasum":"6509a88ce21c43c6c51b98d40ca71e5b8e7b46ef","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.8.tgz","fileCount":6,"unpackedSize":29635,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfETgfCRA9TVsSAnZWagAAXsEP/jescrwSlvbhTySversh\nV498E0zOm6fN82ZAn6HdO7nMPc4f3qN094T0vCuO1WlFGtAhQmDUlvHTbYbl\ntAOiCkhhhaVjgnWACWw4Shm1O+tJEImh95v1beeTrXOwoKj75d3wFyETMy9g\nCNufCFK4eqVUKe25Ij2InxwzTQbw2dVr/ZRoumz2FjcoXxOxA2/WhCKTiaja\nMH/RDtqN8IHZao2sdD5TBTz3oWCEuWLw8jqqq8VxKHdBthk6GWymdhQu2laU\n/xoTIePvdQK8vpidLCr989HPZz0gm8KMc5ZYECdmaCwbbe7Bdaw4JWaglbdm\nah88DT0jsbrAayHfO0EoLHmFWoQoolmNXXLV06Eb9+Te5IQ8f2or8KZv/T3K\nKgtWSOFL0gNVPgfnhySj6gDOFyPiDxXZjsWUo+m65+tJN6/+eV0sUMXP12wV\njq5gcORaaM7PytxShmFq6vKeYiVZZR9kadgCe38EwVCpejLHIIyCl99T/YQs\npC/bSnhne/VDV7QPzodAUKTtQS2qj74dqRobcDc1JruqX5a8ZARJUkWLFvYI\nluriHrPZi51APt8dCUDUYYolw2HMaPIT6QifrEIz7s77bubYUlGSFmenK0+7\n47bnlIDLJvMRw8HmYYVRkY2Ry9J3uHpAiamNrTmLUxFBoACMZkyej2UPmmZN\nQ6R0\r\n=GHej\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCVRR4OwrtZr5MsqoQVnYkM8LgHMlerAqhZyApR9VIJrgIhAJqgkjHTJDWF3HMcLcPyVg5y+ng1Nw0UIObr40F3QTii"}]},"maintainers":[{"email":"mail@jorgebucaran.com","name":"jorgebucaran"}],"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.8_1594963998868_0.2615417284055426"},"_hasShrinkwrap":false},"2.0.9":{"name":"hyperapp","version":"2.0.9","type":"module","main":"index.js","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"release":"env msg=$(npm run --silent message) npm run create && cd ./${pkg:+packages/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+packages/$pkg/}package').version\")","minify":"terser ${prefix}index.js -o ${prefix}$out --mangle --compress --source-map url=$out.map --module","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","build":"env prefix=${pkg:+packages/$pkg/} out=$npm_package_name${pkg:+.$pkg}.js npm run minify","test":"c8 twist tests/*.test.js"},"devDependencies":{"terser":"*","twist":"*","c8":"*"},"gitHead":"f4fd98da84762e2f2350696c14df486ca7f33634","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.9","_nodeVersion":"12.20.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-ZAB564TnZG7DizaPvQS4qQisUV2W59jy18FGj4o7Il6bCZ/jPo1OhaOj65FxC1afTSjEDbMq+OPyHfH+74/l+Q==","shasum":"332c2f5c5724b03e026a98fa2ef24c58f7f9348a","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.9.tgz","fileCount":8,"unpackedSize":81729,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCbAVCRA9TVsSAnZWagAAXa0P/15Ro2K+732xgI/aG9Lj\n8UceZ1tOlkdHpXdmI/6SYQ8l26zFfcOzSXo5yJ6kk+hq6R+JrdTrEcoe1kkG\nVdy8ji7FUro19u75agFvd96HjimNprKXN5YaBk5wYseNSTOWpjexltp0bmmT\nra/gRvm44QMhWzJYRBRMM2iZgADLNC08ZR8XgddPaR/4ndh+AkUXSg7NSjs/\nZfmOLwrHqC6PMExtgNzuvWo6gIkx0xm4X/OGtg+qD2D9+2XraCyB4vf4E/Lz\nVZmeIY9Jyy/KrGr54oOOtViaEJqmeHakH3R/2FionaOaTa06QknJ+2eEwFbU\nhj+yWdN1UFRtAPGvbN877FaS8OYeoNIGB6qVQkPaJOSn+ZQuWSe6EI8dQJAS\n+pLVIEekx3s0zCkwx4JbDo3szZoiz6hoeCorFH+AqCIK/4OVSLf1xuBl/Vrd\nAYvc9TWGbnHplqJB8QckxM2ASRM8GIHLRNqnlC5XED61m5L1w0didR1iAINm\nz0D4vqtQlrGJulHt9GQTDHFJiB1vl76MnazWvRA7UbgDUyEiS74TK9OThN/O\n+bX0HhVxUhBJkwAk/RXWFSXaam7MQDcwT2DvRbQ8oNK5UQCcq+876gbSQAmn\nWbiXx+wjk1C1iuMRq/tzd6ikIOXQRFOyL5J8jI4LwCq3IFPzGSTPF7oB8FJV\nMHD/\r\n=fU9N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFKXW5EhoWT8oPWJDBplfoRl/ugBv3/YqEXII1biif0DAiEAj2bmERqDhMGi0zX+TcFXpLBBsvz5LfNgMstQLsabFbg="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.9_1611247637317_0.5544783965970388"},"_hasShrinkwrap":false},"2.0.10":{"name":"hyperapp","version":"2.0.10","type":"module","main":"index.js","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"release":"env msg=$(npm run --silent message) npm run create && cd ./${pkg:+packages/$pkg} && npm publish --access public","message":"echo ${pkg:+@$npm_package_name/$pkg@}$(node -p \"require('./${pkg:+packages/$pkg/}package').version\")","minify":"terser ${prefix}index.js -o ${prefix}$out --mangle --compress --source-map url=$out.map --module","create":"npm run build && git commit -am $msg && git tag -s $msg -m $msg && git push && git push --tags","build":"env prefix=${pkg:+packages/$pkg/} out=$npm_package_name${pkg:+.$pkg}.js npm run minify","test":"c8 twist tests/*.test.js"},"devDependencies":{"terser":"*","twist":"*","c8":"*"},"gitHead":"cca8d111c8a9938a63c6eb6f458f8fc1d6d4fb41","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.10","_nodeVersion":"12.20.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-FiK4aM1dzVVQ9vOmVNgNjf6CDxiQVEGlf5m+WsN+2GsJb3kQR/8NEyHcZgfnSURKJCOoMguy7182csxWhEkngg==","shasum":"1111265074cba4f3f27b05d93df07165ccddc630","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.10.tgz","fileCount":7,"unpackedSize":31367,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCw3VCRA9TVsSAnZWagAA/CYP/jna8zFhAnUjbV7/NjWL\nWMYE6cPYSpxhD1AaqSuPCf/jzT/eykLCKmOqxbyamyALQ3PYjdxV5VeYM0Lh\nj6j28gPy2deLgJXoK60/lSA6E11uVA8MHw18aZyF7V8bFbh5y4rLimP15ISG\nUFJsquBRgRm0uS3+wGmcL7X00FBo2jjupayM2YCYEQuyzRa+6zAPipMS+X6I\n5PdSCn+wPLc/vdKigjmdsXfqMMWi5rG/slHfp7vcTarFkqnq3nbAACyn2ZZR\nSstdNHFnNE4XB6CPaG0KE+v2KheOZmqVKilQmy0L0FKNbQgRwuDxCTVshGHr\nnRWh8P3wH/bzxuZ4qlzZUD5Yrf7noyxfWYFW1bbjjShU+GlrSXd4Xa8jXf8c\nn5OwJWFMuTNPXkgkZLrU2u1RbUEuSzm9Yg5yA/BHn7AHErDPF8vVfTfuz9EI\nNSpMkkbLfF1epWx6DR91q1pTTnIErg0IoqoNW8TGtXQFYvMa6uGn4EgYeaky\nnP6DKSA88KmNtDrVVBdLLypWq5VkuJiSAhgSBSjxNks3/plNw5tD1oXQEm7/\nfEOOZOU/nu2ADGc8nqeNKkEb5Y7V9J9LZxzriCZYUP9Lr/0H1HmTjNTf9R0n\n4Quz83OqDwogbpxd2M5YVJx+Jrqok0fQ7HIv4fvW0L8YFmv5l0hjFfia3eRC\nbZkd\r\n=erxV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDT81LB1B+ngu79C6jX8dYh6glVia3DSz1ey4fUkmxWwAiEA6cnhZC8lKYJUSUoW2FwRTwQQ0H+QJuQLsH5e3TGaG7o="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.10_1611337173213_0.3771224410122418"},"_hasShrinkwrap":false},"2.0.11":{"name":"hyperapp","version":"2.0.11","type":"module","main":"index.js","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"release":"tag=$(npm run --silent which) npm run deploy && cd ./${pkg:+packages/$pkg} && npm publish --access public","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","which":"node --print \"('$pkg' ? '@$npm_package_name/$pkg@' : '') + require('./${pkg:+packages/$pkg/}package').version\"","test":"c8 twist tests/*.js"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"8336d65fab727967cd4c25a4b049756197dfa90b","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.11","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-Y/Fq33isMfq5nho208Ov+rB7DnrsCVYBlAjNucaUAdCNxPAr3FxuyPWTqqgGoiepDAZAreU2TwiSUuCd4N2l0Q==","shasum":"89909e61f4d3da1ed76744918e3d1185b3acca87","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.11.tgz","fileCount":4,"unpackedSize":19244,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgD/VACRA9TVsSAnZWagAA5DwP/2D6q4F79YNSUHmb8s8x\nARVU5HDUjP629Pl53jCVQH/UmvPLYNyo3/GkTDBKEykJkTiwUaZpJhPs2Vwq\nSU8gkzNkG43Ft4Vnxp1L5sqZEsfkpAHNzgNBbcUM9nmSd3N6CqR/RDmd8SQH\nli+KeRE9osGMOj8IkQ8F/VNOg/Nsu89Sf8a+xu/zkv8VpPyitP8fk9OqRd0j\n4u9br/bTxpJhD5UqlTZeglutwsGz29jbnpAfTerhutnNMGp9bD3rYKIkCvlh\nb8OsNPcVISdp2Mb4LwrPuW1SolRLS3MkZPm//wD777vvagysI4BzlY/V3GHa\nOi6xX7rXyWw01z2fCww+KPEV0DLRxLZuriF9cuVIy0ZZ2tph0t3JoNWbzEaK\nWo4AwWsF5lcGdZABQwfvuAgYiXnJFE6XK6uN7YL9i6YCQ7pwamd9XXhE7Izq\nvrcZG7sIMMRC0uo6SVgIVAHvbeUZg2QNhMatWfvmBWufDK9mUoVqlBksOGOk\n7Rgev1D0Lx1GxbfK99L5g18YTTtm3/PTwOF2hd9hqWY1Bl/a43FTd6yzy2nM\nqn9Dbafqvb2RiDQyG8g7wsLt/UoOSw2JLChUB3sHcEXQOqR7CtzUaMG+w69Q\nfqe+gqI1sAYpuUYMtvTWGfsPOslYI4kQg2OUWPWuvGa+xR+nZO9QMOnOdc1h\nd5w0\r\n=n/3H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmCwVHQMOnn5PCXbHzEIkvRWEmlLUT9E+EA5GGc7fepAIgezQbYTJ5T7qNKK1vDTlre4Cju0pTDL/Dh6sQR3Rt/nA="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.11_1611658560275_0.7048883101410877"},"_hasShrinkwrap":false},"2.0.12":{"name":"hyperapp","version":"2.0.12","type":"module","main":"index.js","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"release":"tag=$(npm run --silent which) npm run deploy && cd ./${pkg:+packages/$pkg} && npm publish --access public","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","which":"node --print \"('$pkg' ? '@$npm_package_name/$pkg@' : '') + require('./${pkg:+packages/$pkg/}package').version\"","test":"c8 twist tests/*.js"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"db151dbb089a1e6574236dc9340c049dac65e563","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.12","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-kDwTunVPE9Lw8HIt7K4vNwEz2xBKhRUBYh4fiXUcZPtFEP6Pfe41bsNbbIO9a5NbI2IeTOwfPrQpTQxQC493MA==","shasum":"0198158bf1257a07b9249a07cf3feb9accc7c698","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.12.tgz","fileCount":4,"unpackedSize":19228,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgEG/oCRA9TVsSAnZWagAADnIP/A/xunu56zzLM79m7+R0\n5ww6ArPAP0gxoUe7u2FvAshGYT1x9B5PWxk3mza9UW/3XykZarcqNb1W0goI\n9xj31EI7Kt8kfcxtsK6B9R/UhmE5HFsqCuTY+fIteLweXijLoi8lqAIJYeDF\nQB0auAFq37UTxM/S+jK+VEuPbiJcaD6K1M+5Ai2kgGcNMME6Jl/BFab3gVZL\n9aFtsbhySMdCxR/VGbDgPEnH6Dik7llt4nI3bAPcDnUZyWBClDg1GHt1vZr9\nQ034XacNnS/KNaeksxHW5PZ5rZZHXxUdHWifRQeWdHX1PhYOTGauAqhOq/7Y\nNU0AptA9FQDanL8IOpqp8oDLf6WCMpBgHTHhvmRYy4uwN1gky4yJeBpFCJCI\n9Nj1W87VmGqvyH99cOS6itulDcT0CwH7Q7B4exy4V4gk+hHJIFIidC/2tsAm\np3X3JiaJwFeQR126Kt4o6+LRGqYYV7R+BxQEMd7OMmXpbRosLTxmz75UhcbJ\nQfg7syoV5MgcxCF2jgA9lbbzarysY3LS6hJ/Gt8JXpq0WcCZD7EaLOTGbZXD\n2zhrOjpB41772dgsTQKxxqiIRzSwPxjGmUmijLq2QhrGrOY9zK6ATVZvkT1R\nfa7G8vBZnApwtg4Xiy4fiHVPd9UTbU4rfzS+9UNZLpn80EWzAYbmqinqY7p1\ngkKG\r\n=5hMv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAUFnVqPVV0evgxBzL15WO3s+qphq6tvkcmYeZ3i5rYgAiAAqY8Wue/BP7pNIvRPhAzI0pFUKoH+OS3Epp0u4M42hQ=="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.12_1611689959652_0.7164375235322888"},"_hasShrinkwrap":false},"2.0.13":{"name":"hyperapp","version":"2.0.13","type":"module","main":"index.js","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"ef7af06246d6b261b778b60e3f3a64f7cbbc94bd","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.13","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-59j0ho1vTH5nrcJ0QHJmcOeW0ZfkWLG+0A3OkFITu76Z93KEe2q3HOXVtOGq4ISb7ru6VrsNFDWsvSvrhojjzw==","shasum":"d55e9b239c5321b04d25c553e2abb2a8c3726bab","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.13.tgz","fileCount":5,"unpackedSize":22339,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgatn0CRA9TVsSAnZWagAAR1AQAKJGnUAUebSd/k1mNasG\nyCP6JLaJJLiaHDP7P3ICg0f6inRQfx9WUYet6eSQCPa/5N85Unm1k+nIuhuT\nd6bg5iJ13HjnjRzeqYRC5guc7r8pK7HSngwwFQV8NzCbrdvdLXbwgouuy0Pa\n9Sh1h0tS22rQi9h1qohWDhuDBMveZesvoAT6WoPvC44TG+hJpmiEV0VLtxCN\nHtfdAXHCoJKQFSc8hQSPleGRY1LBqw3JGSO6W8NQ0iJxgcDatG0iWRP+XQTC\nRMUrj2mC5ZbNwVK+51qR/nj++OHQjDThpx0XyIAvHCsBrtwfkxjrKTsrO6FS\nnKBWaVrY5P+eb8JAFt4ljJ7yytowyZF52Jpx2jQXVg1pFNFJF8PnXHjhjvyG\nfyxjJ2vKa96o6euUKT9POnD944sljQjKbfggZmrZYBsIJ+XCsaTuCccIWxOf\nTnBdxzOoSBeLle17FxpedgICoAooRROz+nCM/XQrZbqRC7AIppojPZvZvnZ/\nianPlwr3qxtNPO4IPtzyoqf7O5j9AN5gyjvDb4fwKSIS7MneM/5rDy41IlEY\nfNrYB9trf67WNb+6+exzqvD2upOuZ8TsavphYLIniPkV90bUzSSrOC4jvW+1\nZdYZ842IkzzX8Ve89eDUxNPvdlisTOOt2C6MoINIPgLQIqVBevARdnPKz5Ic\nTYbP\r\n=d0Bf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAcHhS2Ksz07j+gYhP5ZFMDHGtfCCGefz0xn+BzUmRjyAiEA+aRL5rGA7Y8O2BRwbFM+NEoSrkx1POb2w+HUiBV9lmY="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.13_1617615348040_0.029144085800586694"},"_hasShrinkwrap":false},"2.0.14":{"name":"hyperapp","version":"2.0.14","type":"module","main":"index.js","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"d4814c18e1de0f1329677f1d40adecafb613c500","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.14","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-MsyrbzEZtQx0sPp126buy1paPN60ENTOiB4thSpbS6Nz9gPDzHb6SPEYyZkmz/3QTdnmZyQI8fck3oVYGG4CIQ==","shasum":"58d0d86ae491fd5a09267b74489643ccfe29025c","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.14.tgz","fileCount":5,"unpackedSize":22338,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbc6cCRA9TVsSAnZWagAAbXwP+wQm4sdV48/G8xB5nzk7\nAOfAwHlJX8YtuxMXdrbQEV2sIf0C1AH1S1Up9ImJvgudqdSMuseSKXhLc5hZ\n9Y11CNsg8GOvFic+qn/mGO0WvZWvBq2hCqZ3lX48fKbfwn1FoenRvA6lHYYt\n41nkZaIpRN8luoNYjeXrqbmdEYc0qtPsUSYTUArq6G6yy6+fhYyqlP1RVTr/\nOAkICtjIWPnd3tuDQIlp137lo8ApB7IjrgiARCI/MT5fJGdh4EBKG1AAJgPU\n7MkmqdOntnoRA+vKSkcC6Ffv+Uz5aJA4f3CDBnJ3OCGHdE0ejN8vaBu4603C\nRYYOjeFiZxcYZAooc02cE7rOc6kVZAliUON9FDUjrhUfCft8t6grh6FIwFAW\nk4cjmIcQEg3VlFrotF+3lKFn/wZLAdIqrXlgLLohWAN3F1PzPXq7SDrELB3Z\nWB1J/npCRTh0uPmDpXBji0FdeRR/ZNX1zxs1CCBq1maLDoqNbLP2/j89oBaH\nT1JLbXsgcnnVzjI4je6ism9qfsI+n+jQ1HzLZk1I8q44bphnfMB+wE3Okqo1\nU7XFR4CIyawKbzyil6ZHVx3eKYqVUVfJSczwuf1FfxaClp7PqZTlddZ+uQr/\nTXgjE3qQyvnT85qlRxStFVwEM76jkemB4a1xwLighevbGQlWUMt6SawYo/91\nARm8\r\n=whis\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCNLg0lzQJxuyn+vmK50EzYXeOpBwOeSwmjBr3MzgV5fwIhAKXKYYUfsLO2LHcSAa0OyN6V8WoGHANTa4w6mVlbEPLj"}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.14_1617809051625_0.41645560880234456"},"_hasShrinkwrap":false},"2.0.15":{"name":"hyperapp","version":"2.0.15","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"32d7713e83c4609cc22b052d31e9dad45f9db80b","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.15","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-jvT6VDnXeK/5qn3VSdnNfQL7JXrwcDG4PLBz0BiomwuV4IoeaFTUJ9ezbDb/4NbKrWZOv722VNqsBDHOB6gFXw==","shasum":"7b4c967ce9b230eec34314fb49c2c07bf992539e","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.15.tgz","fileCount":5,"unpackedSize":23471,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJge8YqCRA9TVsSAnZWagAAix0P/1qeheDxDN2VWM1DwtUF\nisj75Zc50oqxhK52LuVs4Nf2eTtvyNj52ze8ingsaYNkDrEPQc4un0vpJuHM\nyJopbrx3GuuGzFCAh5TohifBJRyM+3NoCabShbpFqWQAXA+AeSaE6wvc7sy7\nr4IEvS9j6XSXpzfKMMK7z38Y54aih/gERmalWuc3o22sZrQYGoViBOLR4r6w\nkhD1c9XzgC8SBW5bHH+0DF/Egg/h0jHcXKA6wi4dhD9dsrosh/p8LgR+Mf3x\ntFD14mIFPlaH5X3vTdr+O6mP010M4CtRpTVGQLrx+oQanVhPQc5pRnsNhkOx\nX+g05HZ2gkEDxgHjDgAFfOAdFx1y3CvsBBu7VF4l8ydrd5XVtNggrELzoBhM\nSHw96CdP5Uy6upmAPOJj+EqqEzAmSdhFtIQjR6UQCC8UN5QcNBoe4Bo4BFsR\n3HNX5Ix770RocEFMR6njecTPiG6vhTRb4tSLGDYZNY82AenXXhsMRHHLjJsu\nzXy6cpJH1mSzGlW8vV+76yg6R3LavKAPUC3cYjCO/rk+79GLR6Iw6bUgWsfF\n2EG+NqNlwbunII5K2noTF01M4/+mS9vb0zQeH5jq6Enf2CQxwH1+uiosnJKO\n75ZDIpVICbc/uWfmgKgnPpnqGOtLvlbMTa2zDQdrtOv+SH2Ky0BvupTiflyY\nm8aa\r\n=InDW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDer2kG142ctOVs1qMvhR/SRSrd94mHiUPusz2KAuDSZwIgSfFKHloM7LMcHwrcSlp8pue8fozZGq+Z9AH9cZR8158="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.15_1618724393460_0.365080848518448"},"_hasShrinkwrap":false},"2.0.16":{"name":"hyperapp","version":"2.0.16","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"28e5ee043bdd00676a51a7076a5b342610ab100a","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.16","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-wd3Be3eXo3H0xfTRbZU5fNhDnzAm7KkB7ANRXQdtYLFWgYCtP87ANTEFWxkk+nOA/JAkbgDqzA818bod3cpioA==","shasum":"32589d098f04b5af69b6826c5daeaf505fd76251","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.16.tgz","fileCount":5,"unpackedSize":23555,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJggS4ACRA9TVsSAnZWagAARY8P+wZ9WjjMw7HZXpsLCn1V\n7oFpFZXJ2KXB2Kqx0s3EavZH2R+RcXecnHIWaAy/BnnJR2PqbXhzIX+kWnAf\npc0SuYkTOIhsHZRhGgJ04YxZoEq6OjESykujoRqAe46akeQhBbZy45bOKDh0\nNjnXNrnJhTmOUDTd+O9KVW8WH18kAGSNflu5WLtOKIwsphkSG7F0XCcS283C\nIrRxXoHuF1BabRYRh8/du8GYUS/Mke5NLaQpDvBrCeSDeGbk1e6B9nQ+L0ib\n+DwLUwnEW2n7VRBtg9VUxtgYZD8G0r2CErSYZ3sJgkloGhVI3887SGXs6o98\n1YEH4ZNvn4PcxG5suBoui3gT00ozjI9mbHmsErbTu1JypsFjn6FiK9WvuN9q\nynOZlbYa8JsCFECm0j8EkjNtRpB1r64eT0sZ4e18WtSQNhE3Pk+p8LAIyibS\n461XEUxjrHwwqPxXKwCWeBV6F5f5E+bDmim+8m4FU2I6JTa9I0IqCOE6Xaxg\nvzUxWsvxZCAR33RvVGlesFP7U4qXIwtvGav2K5W4E7//wDSXL9havaxB9i8d\nNEvqMTq+axu3JR7x+NYCf5K4FtfC0vfVevB7N28awkSWCp8JX3U32MdWy/e5\naEz6gUA+XtACKuqs9LCgvlWp36H5OnMv6Z8sLc2rpgNL7ol9XdFjRTS0+hdB\nkPKW\r\n=hlK+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBiU2W4hVTylDRidF6WJzrWXJseZ5xkLKXyvqU7QoQduAiEA62YTCE7KmzA0oyIlZVr/JC/gsaaT+Mygg0xaFZ1cLqw="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.16_1619078655786_0.9077751496747"},"_hasShrinkwrap":false},"2.0.17":{"name":"hyperapp","version":"2.0.17","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"14cc6c4ba64c83703048756fb1065da7ec3a59a1","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.17","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-g/II/k1uXkAXK7Hs9cqP9KvcOa2Wo+PDrUQ59Buj8sLcs3LsDDYfwJTvxQ2G3Cb+iqdL6AWXLQGAH0vwsHHhUQ==","shasum":"3aa75a4a519f66e1cc7bdb33776bac9ce488bcc6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.17.tgz","fileCount":5,"unpackedSize":23439,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJghE6MCRA9TVsSAnZWagAAodYP/2aQVQSeTNlFlfaa54o3\nKEHnSF5xFDQ4ssiA/Z4f8rIyebtRyx+4cYHqyARlfMc+uZxR7oCX3KqKangD\n6V1eWuzS6bhouOHzoafDaWQsUldSb5Z4tx4dEJUT89Z/7LaWm3wbIB2ApRez\nd56TVel5D9cI75jJ6subayOamx2i9kMTKbus7tyMbO8y2M9bgHHrnyMdo16D\nhFIzZj7jQpVVQQostpa6SCuMoKP25YnlOtlhLrQPDYJauFeZ8vuGvqkLYEiV\noGIjVqK8s/6Ze2I7T22LXDNzhIfJuInXu6PN1uHlF9T31lRq4VIrPKnnnkH0\nY+ZADI8HFdZ5cbdR7WnEo+8XtmwfHkSHWYYVRT2eJOBOY7qx5V/s7xNpxUAB\nEyEosbKiJXt2piJpC94LK/vpB1KwxUNPp/52HzoVSQWCwC4xeR0o7xwNKN8v\ngmExGdKXxcUBIeG8A1AeZDBX45ubHp6ihtrDCuA/YU4XjdN75fEnSzoHHfsi\nBvSDAPuGb83s8gHrcfEH1ED44HR5DkrPLZnXZMEwMBMJ1OLx4/mte48iNt/2\n9B9gw5VnbOe7wfpTisU/laOtllIz9oAsL7VGEGk9OvA23G2tljCP1kG4LU2U\nZ241iYe46W9+6YT0Rc+F+6XCfpzOqlfZ2k1wI0I5l390BhXxRY2GxpuYnfvu\npAYJ\r\n=mDBj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBOIcSh7g4vi5t0AxiyLa2tKzMNwTBkjdeiDthIeCLtfAiEAsLrjukQJTRdtdoLgD0ORrh3RIaIQwzWxucxynJLMjR8="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.17_1619283596277_0.18948587994067623"},"_hasShrinkwrap":false},"2.0.18":{"name":"hyperapp","version":"2.0.18","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"865e389f20a1c57b1883c8eae8ead332206c4a89","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.18","_nodeVersion":"15.6.0","_npmVersion":"7.4.0","dist":{"integrity":"sha512-i9NoQtmg9vFy5iQVDlpWRahnJsMn8eb1WrkDXUkytHzxx7IfOdICU6UaZP6fv2FVXPnQSVxxpUo8HT8d5L+ktw==","shasum":"dd709627a11d755b62710fa539fd860e20074735","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.18.tgz","fileCount":5,"unpackedSize":23838,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkekQCRA9TVsSAnZWagAAciYP/iI6DC7kaoxCgJjRrWti\nvSYySCnUjma+Bkm9yffuqvPKi6N6iMBQ9lYaMPTVJf2KXqHVhsm/j/hj2Pls\nO4MafGAV2SGYAlg8Vp1xm6Djmptvtcn7WveIw1jSFjfFj//H1+Fb14Bb/dwQ\n4m+f0l/3/u/K0kK3pZVS3w1WKAH6RCIwFaCdbwZCCr1PTb2aFr793AgCf6EQ\nR8rLPvVSci/C+NV1wLRZlbkyGQN9EdT8bOyjKhzXMZk6rl7Z2FIHZGWOE7gz\nSNPwCnQikgcg9GeFpSuOXhtgLDN5yeQlJ0HODUpy6MgkM+PPdNF6GmNfqaL5\npPnLP1JmQjsObbqKxkx6UEeCdSWFRIPmnYgSHmDphtt5PavIgxDfgcdpr/Rk\nNgZLzNtVXRsMmhNbESgFFefsdUJWEfjiTInnIWnzdaybkKqLEPGEMT5XjDWU\npCYHHksOC4528adZBKHQ1yH91q8izNuxvUKB6/38g8GEiM57xgLKF3cl33zL\n1mdT8aNYMY15UeTDiBVuKZO827kpXrIEbINFn7quVzF9kX+UaaOZorwr/cTI\nEzUgUgsyzTOYqgIUb017s7Y65fKq/6esssJBsee4jDj0+c044NI2mvRJ10ph\nXL7NUy068ekDlRd2C2basbETI9IErzdAYqfodcTKD6yLUeO3ocSsaHMZnUDO\nXo5Q\r\n=r9O2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE+1hagvWDN02oirXA9xq2ysvwKu41wogZeGK1aUGATcAiAMPk8oJKIrv9sC7HrnwY7IW9TJ0tRIloAlkV2G+hEHqg=="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.18_1620175119657_0.21366681609140326"},"_hasShrinkwrap":false},"2.0.19":{"name":"hyperapp","version":"2.0.19","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$npm_package_version npm run deploy && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"dc10f52bb25dd365b4e042f96d9e6588296cc687","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.19","_nodeVersion":"16.7.0","_npmVersion":"7.20.3","dist":{"integrity":"sha512-PdagpWI3gCo8R1oVpoCv/f1Jtleg57Kw5MIcTKrW8cIDKsws4JD8bH4RdopqELQHsrpGMqbmkcBAtbrUq1Vjtg==","shasum":"49e64ca2b8d8f6dd090a57719b584b793339dcab","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.19.tgz","fileCount":5,"unpackedSize":23974,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhLuxDCRA9TVsSAnZWagAAfeAQAIsk8/9np7EWYceixGUG\nVtnyA+0KrR8eiq/MTIzWNWIi+yrv0PAHVYO2fipf6a/mIk2b0n0YD+TAwiVK\nZJEa4HTvbFlz9dangOKOlwviV6x7yhGUG9pGUCbj5GYQ/J0o1Gns1Q7607p1\nN4xJjMu08OwxffHy+t8fm2YOlZ36QS/H1SZ2G/8CNdlCxf79A3OyM9uI20MS\nCY+oBErrp1exHfVdz9B+UVWmJQbUaUxz5qk7dR+0rdgvdJBOpM58cNfArkKD\ndkSLGiwSDsjrhngzw+uGTdCCTuz2/nCfscTOT3PCDE3a73xTg4DC5cGastZn\nZ/3ke0Sj4X/7W/8qGW7Hb02Yr/5FssvnDXIXiaj8DAZO9rwxIYeldw5xcy4x\ntlh8sBeTvYvU2T/t25yb/D9GotuEGrEdqLEA6iMBwiytucleRz17LJuNSp+2\nW/fFAI+63fJG19CE7O9YETqArx2kbBj6AF8bgEJwATQWAeVt3owEKyVo1ndM\nOBQGMW16Yxwcf0nra9YODYtvKyHtu3agvgp5KLBJwqVCnH1au+hStII21T6V\nNmGon8ryBHdkJX0QM2M/jUAictfJWP4458xopLfXbFmNTzasaXoDWzJeQeb6\neYoXh9x85EjeUnfOfCLPlJn7kenZ4f+dvL3y/pq8cDYu1Eg5Hjd5j8YDlDAq\nytR1\r\n=SRd3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCzBBTCXSWUbZqstOgSdBgbRnlmAmkMJ47rT3l67AerfwIgBhKZhe7dhMXp/T0LppK7MkipOK225ug7exYWPSDwVUk="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.19_1630465091412_0.14758474595005588"},"_hasShrinkwrap":false},"2.0.20":{"name":"hyperapp","version":"2.0.20","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications.","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","info":"node --print \"('$pkg' ? '@$npm_package_name/$pkg@' : '') + require('./${pkg:+packages/$pkg/}package').version\"","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$(npm run --silent info) npm run deploy && cd ./${pkg:+packages/$pkg} && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"f9518be1ada51ae993b062eac264efa25a8cd16c","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.20","_nodeVersion":"17.3.0","_npmVersion":"8.3.0","dist":{"integrity":"sha512-Vag0zdLCm0Jf0eJs4TSReQw/ZhDmwgrZ+WSCZsDV+5Fz8z5VgoP+9WUwsQFX80VrHK8C03o/PwXm+SDHwks2Zg==","shasum":"2e1f96eebca239018224e4a356def249d32d73f8","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.20.tgz","fileCount":5,"unpackedSize":27192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhwQdFCRA9TVsSAnZWagAAdIgQAJ/wlH8EBk5kdTt0PrCo\nHyHafYOrjGdZYOkOcVcwTRc+TS3CtXHlb2pz9WM5n83hJ7o543kuhc6jhlQs\nGvby6z9UBSNrJ7bW7BfcUmHNBvCNCPVCHrP/svDpCSZrN5Y5vsyDgiFmHhwQ\nA3OS5NDLK+xVd7kyJOItF37GGK/BhD+GyOZ//CrHkqyP8HGgBqHhk6arrAnB\nnk4fc3Mad2943R2ATDbJ209gnEKYehD04t9GTXUemdCMVDWmV9sKEK3hGvMh\naojlRbCAb7v3aT5HwFfqYWJAx4Mel9pBEVga++PqYXEMYvZ7+ptdy4zyxVbK\nl1ldNCmBhmwLpQ1g4fQkTWJw5n+AiKW/agy3jPtI42hpcqe1BXg7UEmyj4FI\nx5FjQ7npkwh0kHRbagfB9f/agUKYCo8swmH5kwGMlspFF3eFe8316WW/vrCE\nQ8ZFSq2JxqHEiYpe2dKhOZLll4sYZu6ZBglDsiSOeV2izFmKwTrr03rS/ssV\nE+g5DFxe//iQTo5X6amGp9Sr55x35319Nq6nHm6esgLdWbyOLku8NivO5cRG\nGbGhJD+bgJ0gyWPFrE74/sIriUZmZtzAOxdSEMWy/pUWFgK0FWzF3+aOceuC\nyhw3b32PABodQs2M3ljIyONLK0Yr2AKKU17eHW35hV/5z9iTSx/bfBa7SdC+\nEpuj\r\n=egY+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDe0Jhpb89y0Hrd95jH/T5N4kYoQJ7ckhFeeCedUo8sogIgd+r+qW6Tm0wbgSOLQ1XwvM4kdKrmCMD5gQJs7ffDplo="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.20_1640040261460_0.37818637234924246"},"_hasShrinkwrap":false},"2.0.21":{"name":"hyperapp","version":"2.0.21","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications.","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","info":"node --print \"('$pkg' ? '@$npm_package_name/$pkg@' : '') + require('./${pkg:+packages/$pkg/}package').version\"","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$(npm run --silent info) npm run deploy && cd ./${pkg:+packages/$pkg} && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"d672104de55ad2e47bfdc944bfa82a129f828441","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.21","_nodeVersion":"16.13.2","_npmVersion":"8.1.2","dist":{"integrity":"sha512-cGycgw9eWWZPMMYWGLf4xWY1bxF5celLvzP+PX98KzvNvNJmGDN+0TpDeuVPcrhzwH+ybIeag07pU3UQ22VUxg==","shasum":"edb2b891410c35f812e6a631ff8ecee46e217ae6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.21.tgz","fileCount":5,"unpackedSize":27328,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiH2KCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoqEw/+L+hrgmraLcnzPwdVpQjj9kfnFVYixguAyF3v2q1cnZwytjLb\r\nYL1yHvgd0wXq6bkN/RW+jyS7YLte3labSycvoRBhwJ9BWTUzsNUqovEPCCPC\r\n4g+lU0dHTnkxw9HkS921hcYuLl9obGCLaQywXvt/KZNny9MgCG3kXx6rcMKM\r\n6vUrpF/VcQgXVpSpYhgfb2K4J8hdywtvR6thiJwmbAvhLOGEa/PW9BhXpNzj\r\nNjSx1M92vwBkN6bzBxXJVHnX1HU49IAM5L2tJL9xzBW0ZFOHOMMceFojtvLW\r\n0SDSG8RUzwRVzg+3AdinfFbJHJPQKHzj/fcnUflHSFXAgUcvWLnw6NLyV9tJ\r\nHJhr1EJgFZo23FJXNPZQbREMNPSmEAUfjR30OSA/7lDw9Oi4XnEw85B+7gMH\r\njbvyHKzUVovRlmQCHmf+xDiw9+cVajBpcaXoB+ne0j1aOVgHI4YdV+3u5M+J\r\nmKRX/RbN6H7EKXDIqzctMefyuAP5yYfQ61keMKY28Omka7sC7GpjjeHS1bZu\r\neCGzDRn0XVdp+mSk8D+3YH5uRg11ZDhqIsGoYBeFllQlcI6nceBWXCOnlTu8\r\nEF3xe3BHJqLTKrUPVnI3VnxIOVfdZupMMmtwz/3NJioCRvYVZ9xnKMIVXuWq\r\nTjWlkR31Yj7tZn6EXrHLYui3XXD+uyFETQI=\r\n=ff2R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID4+1EWqQ7T+339isBTv+sE+JdgxJZy5asiWGRYDc5xxAiBdGqceRPA1Ynhx1t58YAfrrwQC3O1rs3L0QZ/MA3BmVw=="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.21_1646224001988_0.7302073669226632"},"_hasShrinkwrap":false},"2.0.22":{"name":"hyperapp","version":"2.0.22","type":"module","main":"index.js","types":"index.d.ts","description":"The tiny framework for building hypertext applications.","repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"homepage":"https://hyperapp.dev","author":{"name":"Jorge Bucaran"},"license":"MIT","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"scripts":{"test":"c8 twist tests/*.js","info":"node --print \"('$pkg' ? '@$npm_package_name/$pkg@' : '') + require('./${pkg:+packages/$pkg/}package').version\"","deploy":"npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags","release":"tag=$(npm run --silent info) npm run deploy && cd ./${pkg:+packages/$pkg} && npm publish --access public"},"devDependencies":{"twist":"*","c8":"*"},"gitHead":"876d3f44d0ae601de181714c583a07d83d3472c9","bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"_id":"hyperapp@2.0.22","_nodeVersion":"16.3.0","_npmVersion":"7.15.1","dist":{"integrity":"sha512-3uf9HjnjrhbfykowFNEObZewBEo4DXJIM+9FnGkiR9E4H2eh2f921SzMCMS69X5nN3A7KFfmZc9KCKh/7TQBFA==","shasum":"b12b0be2dc56bd7e7df6dd20780ebfc34010dca6","tarball":"https://registry.npmjs.org/hyperapp/-/hyperapp-2.0.22.tgz","fileCount":5,"unpackedSize":27311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiPi9HACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq7Lg//bEyrBxyKxjbd+64i4MLAg+IZXCSkS4vXj4MI3x+0Y9MAKZPD\r\n2iUd09igFgM40u7pj6nvNc828IRBWEktapEtrkLBMpmaXi+JkVYhA1YBR6d0\r\nufAq3mAt7klF+9Em7EILsTbx57lutFclE4V8ULjtcPMX2IcuzD5xAlNoJwhq\r\nrk5knQkV9FyZONG2wLIwwr9kzMsXCWLAeAppILwhTGqMqRSn+Dn3nFJoLW2/\r\nw4Psmhy3Hkee6TyGnyWIU2tHaGxPoi19lNLG/M67WsFkza4QOhG4l4iE4LNm\r\n3dW2aglgA4D3JOxxnnoqnW/PP7MGwiGrJVbrcZULLxnr1BVFUbSIIKefOtAH\r\ncZ3zXWML7kb62Yykrf0t5EF9ZaDqHVcHRr//60XEyOu09NDp+gJ+8ZSyxXUk\r\nMaeGGwaGc6ifpD+WO+xK+IrDl2XfcQJk3BdeHo0UUSg0feEyvZF5m8mxNMlF\r\nrLyXtAqBoulzn1VLevWQum4JiGAjGoq9yfC1mxbxi5nMuv03mjWj4ByFVGAN\r\n4DrkRT22JQweolbnZqTVe7RFRHMm/pSylXQ4kGg7KKhVKW7jhA4yEGtBcFiz\r\nGS7zEbhgdy8qNStWYCvZVqlSQsGmPe3QazR3mT6WKVwwC+CkU4pK6s2KCm67\r\nmFwh+HMwqeM4KYtUhICwoeLq90DqQiomKtU=\r\n=bjMv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDNz33JAbdpeMadjILXYRTomiM4f27/X/NclhyuOK9ysgIgFVR3xbpLrpdnwm06M/HdfiMDbPKg1g1wQGBrXGJEP8A="}]},"_npmUser":{"name":"jorgebucaran","email":"mail@jorgebucaran.com"},"directories":{},"maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/hyperapp_2.0.22_1648242502961_0.006472870896153893"},"_hasShrinkwrap":false}},"readme":"# Hyperapp\n\n> The tiny framework for building hypertext applications.\n\n- **Do more with less**—We have minimized the concepts you need to learn to get stuff done. Views, actions, effects, and subscriptions are all pretty easy to get to grips with and work together seamlessly.\n- **Write what, not how**—With a declarative API that's easy to read and fun to write, Hyperapp is the best way to build purely functional, feature-rich, browser-based apps using idiomatic JavaScript.\n- **Smaller than a favicon**—1 kB, give or take. Hyperapp is an ultra-lightweight Virtual DOM, [highly-optimized diff algorithm](https://javascript.plainenglish.io/javascript-frameworks-performance-comparison-2020-cd881ac21fce), and state management library obsessed with minimalism.\n\nHere's the first example to get you started. [Try it here](https://codepen.io/jorgebucaran/pen/zNxZLP?editors=1000)—no build step required!\n\n<!-- prettier-ignore -->\n```html\n<script type=\"module\">\n  import { h, text, app } from \"https://unpkg.com/hyperapp\"\n\n  const AddTodo = (state) => ({\n    ...state,\n    value: \"\",\n    todos: state.todos.concat(state.value),\n  })\n\n  const NewValue = (state, event) => ({\n    ...state,\n    value: event.target.value,\n  })\n\n  app({\n    init: { todos: [], value: \"\" },\n    view: ({ todos, value }) =>\n      h(\"main\", {}, [\n        h(\"h1\", {}, text(\"To do list\")),\n        h(\"input\", { type: \"text\", oninput: NewValue, value }),\n        h(\"ul\", {},\n          todos.map((todo) => h(\"li\", {}, text(todo)))\n        ),\n        h(\"button\", { onclick: AddTodo }, text(\"New!\")),\n      ]),\n    node: document.getElementById(\"app\"),\n  })\n</script>\n\n<main id=\"app\"></main>\n```\n\n[Check out more examples](https://codepen.io/collection/nLLvrz?grid_type=grid)\n\nThe app starts by setting the initial state and rendering the view on the page. User input flows into actions, whose function is to update the state, causing Hyperapp to re-render the view.\n\nWhen describing how a page looks in Hyperapp, we don't write markup. Instead, we use `h()` and `text()` to create a lightweight representation of the DOM (or virtual DOM for short), and Hyperapp takes care of updating the real DOM efficiently.\n\n## Installation\n\n```console\nnpm install hyperapp\n```\n\n## Documentation\n\nLearn the basics in the [Tutorial](docs/tutorial.md), check out the [Examples](https://codepen.io/collection/nLLvrz?grid_type=grid), or visit the [Reference](docs/reference.md).\n\n## Packages\n\nOfficial packages provide access to [Web Platform](https://platform.html5.org) APIs in a way that makes sense for Hyperapp. For third-party packages and real-world examples, browse the [Hyperawesome](https://github.com/jorgebucaran/hyperawesome) collection.\n\n| Package                                        | Status                                                                                                                                              | About                                                                                                     |\n| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |\n| [`@hyperapp/dom`](/packages/dom)               | [![npm](https://img.shields.io/npm/v/@hyperapp/dom.svg?style=for-the-badge&color=0366d6&label=)](https://www.npmjs.com/package/@hyperapp/dom)       | Inspect the DOM, focus and blur.                                                                          |\n| [`@hyperapp/svg`](/packages/svg)               | [![npm](https://img.shields.io/npm/v/@hyperapp/svg.svg?style=for-the-badge&color=0366d6&label=)](https://www.npmjs.com/package/@hyperapp/svg)       | Draw SVG with plain functions.                                                                            |\n| [`@hyperapp/html`](/packages/html)             | [![npm](https://img.shields.io/npm/v/@hyperapp/html.svg?style=for-the-badge&color=0366d6&label=)](https://www.npmjs.com/package/@hyperapp/html)     | Write HTML with plain functions.                                                                          |\n| [`@hyperapp/time`](/packages/time)             | [![npm](https://img.shields.io/npm/v/@hyperapp/time.svg?style=for-the-badge&color=0366d6&label=)](https://www.npmjs.com/package/@hyperapp/time)     | Subscribe to intervals, get the time now.                                                                 |\n| [`@hyperapp/events`](/packages/events)         | [![npm](https://img.shields.io/npm/v/@hyperapp/events.svg?style=for-the-badge&color=0366d6&label=)](https://www.npmjs.com/package/@hyperapp/events) | Subscribe to mouse, keyboard, window, and frame events.                                                   |\n| [`@hyperapp/http`](/packages/http)             | [![npm](https://img.shields.io/badge/-planned-6a737d?style=for-the-badge&label=)](https://www.npmjs.com/package/@hyperapp/http)                     | Talk to servers, make HTTP requests ([#1027](https://github.com/jorgebucaran/hyperapp/discussions/1027)). |\n| [`@hyperapp/random`](/packages/random)         | [![npm](https://img.shields.io/badge/-planned-6a737d?style=for-the-badge&label=)](https://www.npmjs.com/package/@hyperapp/random)                   | Declarative random numbers and values.                                                                    |\n| [`@hyperapp/navigation`](/packages/navigation) | [![npm](https://img.shields.io/badge/-planned-6a737d?style=for-the-badge&label=)](https://www.npmjs.com/package/@hyperapp/navigation)               | Subscribe and manage the browser URL history.                                                             |\n\n> Need to create your own effects and subscriptions? [You can do that too](docs/reference.md).\n\n## Help, I'm stuck!\n\nIf you've hit a stumbling block, hop on our [Discord](https://discord.gg/eFvZXzXF9U) server to get help, and if you remain stuck, [please file an issue](https://github.com/jorgebucaran/hyperapp/issues/new), and we'll help you figure it out.\n\n## Contributing\n\nHyperapp is free and open-source software. If you want to support Hyperapp, becoming a contributor or [sponsoring](https://github.com/sponsors/jorgebucaran) is the best way to give back. Thank you to everyone who already contributed to Hyperapp! <3\n\n[![](https://opencollective.com/hyperapp/contributors.svg?width=1024&button=false)](https://github.com/jorgebucaran/hyperapp/graphs/contributors)\n\n## License\n\n[MIT](LICENSE.md)\n","maintainers":[{"name":"jorgebucaran","email":"mail@jorgebucaran.com"}],"time":{"modified":"2022-06-18T23:30:05.657Z","created":"2017-01-05T10:53:18.264Z","0.0.0":"2017-01-05T10:53:18.264Z","0.0.1":"2017-01-20T05:42:10.673Z","0.0.2":"2017-01-22T14:56:14.576Z","0.0.3":"2017-01-22T16:39:19.526Z","0.0.4":"2017-01-30T15:42:50.276Z","0.0.5":"2017-02-01T02:46:34.227Z","0.0.6":"2017-02-02T03:24:39.533Z","0.0.7":"2017-02-03T10:07:58.590Z","0.0.8":"2017-02-04T06:21:11.048Z","0.0.9":"2017-02-04T15:31:51.834Z","0.0.10":"2017-02-06T15:44:40.128Z","0.0.11":"2017-02-06T16:48:36.121Z","0.0.12":"2017-02-07T17:56:03.969Z","0.0.13":"2017-02-09T12:43:26.529Z","0.0.14":"2017-02-11T20:36:34.889Z","0.1.0":"2017-02-12T11:31:28.543Z","0.2.0":"2017-02-12T19:41:06.706Z","0.2.1":"2017-02-12T20:25:54.359Z","0.3.0":"2017-02-14T21:35:03.129Z","0.3.1":"2017-02-14T21:41:27.011Z","0.3.2":"2017-02-14T22:00:14.046Z","0.4.0":"2017-02-14T23:53:44.787Z","0.4.1":"2017-02-17T11:36:21.008Z","0.4.2":"2017-02-18T06:13:16.553Z","0.5.0":"2017-02-21T13:15:57.448Z","0.6.0":"2017-02-27T19:16:55.620Z","0.7.0":"2017-03-06T06:16:14.279Z","0.7.1":"2017-03-06T19:11:58.883Z","0.8.0":"2017-04-13T07:45:37.955Z","0.8.1":"2017-04-13T08:49:44.149Z","0.9.0":"2017-04-30T09:06:34.131Z","0.9.1":"2017-05-09T18:05:00.588Z","0.9.2":"2017-06-04T08:39:13.184Z","0.9.3":"2017-06-19T10:32:16.535Z","0.10.0":"2017-07-09T20:20:01.551Z","0.10.1":"2017-07-17T12:08:29.934Z","0.11.0":"2017-08-12T18:04:31.284Z","0.12.0":"2017-08-18T14:46:57.858Z","0.12.1":"2017-09-05T19:47:24.496Z","0.13.0":"2017-09-28T05:16:44.450Z","0.14.0":"2017-10-05T19:32:06.105Z","0.15.0":"2017-10-10T17:55:30.281Z","0.15.1":"2017-10-11T20:49:36.643Z","0.16.0":"2017-11-05T18:37:33.877Z","0.16.1":"2017-11-30T13:07:47.344Z","0.16.2":"2017-12-01T17:05:51.834Z","0.17.0":"2017-12-10T00:28:49.049Z","0.17.1":"2017-12-14T19:08:35.303Z","0.18.0":"2017-12-17T17:09:51.459Z","0.18.1":"2017-12-27T17:52:18.227Z","0.18.2":"2017-12-28T02:58:25.897Z","0.18.3":"2017-12-28T03:06:50.360Z","0.18.4":"2017-12-28T11:43:22.019Z","0.18.5":"2017-12-28T13:06:33.973Z","1.0.0":"2017-12-28T16:39:30.081Z","1.0.1":"2017-12-31T15:21:56.687Z","1.0.2":"2018-01-15T17:45:13.111Z","1.1.0":"2018-02-07T15:37:12.051Z","1.1.1":"2018-02-07T19:27:49.066Z","1.1.2":"2018-02-10T06:57:46.455Z","1.2.0":"2018-03-18T16:13:18.148Z","1.2.1":"2018-03-22T14:27:04.918Z","1.2.2":"2018-03-23T15:49:31.222Z","1.2.3":"2018-03-24T04:59:35.876Z","1.2.4":"2018-03-24T08:29:00.323Z","1.2.5":"2018-03-24T08:43:34.205Z","1.2.6":"2018-05-31T00:41:52.036Z","1.2.7":"2018-07-18T09:56:32.703Z","1.2.8":"2018-07-18T10:20:50.135Z","1.2.9":"2018-09-07T13:26:56.537Z","2.0.0-alpha.0":"2019-02-15T11:10:47.229Z","2.0.0-alpha.1":"2019-02-20T04:10:59.290Z","2.0.0-alpha.2":"2019-02-21T20:18:47.923Z","2.0.0-alpha.3":"2019-02-27T19:23:24.036Z","2.0.0-alpha.4":"2019-02-28T07:12:10.233Z","2.0.0-alpha.5":"2019-02-28T07:18:56.927Z","2.0.0-alpha.6":"2019-02-28T14:48:26.288Z","2.0.0-alpha.7":"2019-03-03T11:36:58.136Z","2.0.0-alpha.8":"2019-03-03T18:31:02.051Z","2.0.0-alpha.9":"2019-03-12T13:23:26.382Z","2.0.0-alpha.10":"2019-03-13T05:57:47.273Z","2.0.0-beta.1":"2019-05-02T23:37:45.899Z","2.0.0-beta.2":"2019-05-04T16:03:20.006Z","2.0.0-beta.3":"2019-05-04T16:10:05.917Z","2.0.0-beta.4":"2019-05-04T16:11:26.092Z","2.0.0-beta.5":"2019-05-06T19:08:25.698Z","2.0.0-beta.6":"2019-05-06T19:16:03.854Z","2.0.0-beta.7":"2019-05-07T10:17:17.217Z","2.0.0-beta.8":"2019-05-07T10:28:10.106Z","2.0.0-beta.9":"2019-05-07T10:40:55.075Z","2.0.0-beta.10":"2019-05-07T10:49:34.491Z","2.0.0-beta.11":"2019-05-07T14:36:36.312Z","2.0.0-beta.12":"2019-05-14T20:01:28.651Z","2.0.0-beta.13":"2019-05-27T18:30:27.358Z","2.0.0-beta.14":"2019-05-28T06:45:26.630Z","2.0.0-beta.15":"2019-05-28T07:05:56.806Z","2.0.0-beta.16":"2019-05-28T07:09:04.321Z","2.0.0-beta.17":"2019-05-28T07:18:27.765Z","2.0.0-beta.18":"2019-05-28T09:51:03.934Z","2.0.0-beta.19":"2019-06-04T16:57:26.801Z","1.2.10":"2019-06-04T17:21:39.517Z","2.0.0-beta.20":"2019-06-04T17:30:04.407Z","2.0.0-beta.21":"2019-06-05T19:14:17.684Z","2.0.0-beta.22":"2019-06-07T12:09:07.546Z","2.0.0-beta.23":"2019-07-26T19:12:55.814Z","2.0.0-beta.24":"2019-07-26T19:17:09.832Z","2.0.0-beta.25":"2019-07-26T19:37:12.121Z","2.0.0":"2019-07-26T19:54:38.312Z","2.0.1":"2019-08-05T03:47:27.099Z","2.0.2":"2019-10-10T11:59:02.396Z","2.0.3":"2019-10-13T05:56:49.083Z","2.0.4":"2020-01-27T10:25:30.479Z","2.0.5":"2020-07-14T17:46:59.147Z","2.0.6":"2020-07-17T04:17:08.284Z","2.0.7":"2020-07-17T04:18:12.811Z","2.0.8":"2020-07-17T05:33:19.054Z","2.0.9":"2021-01-21T16:47:17.423Z","2.0.10":"2021-01-22T17:39:33.429Z","2.0.11":"2021-01-26T10:56:00.397Z","2.0.12":"2021-01-26T19:39:19.803Z","2.0.13":"2021-04-05T09:35:48.211Z","2.0.14":"2021-04-07T15:24:11.786Z","2.0.15":"2021-04-18T05:39:53.595Z","2.0.16":"2021-04-22T08:04:15.922Z","2.0.17":"2021-04-24T16:59:56.427Z","2.0.18":"2021-05-05T00:38:39.792Z","2.0.19":"2021-09-01T02:58:11.569Z","2.0.20":"2021-12-20T22:44:21.660Z","2.0.21":"2022-03-02T12:26:42.136Z","2.0.22":"2022-03-25T21:08:23.166Z"},"license":"MIT","readmeFilename":"README.md","description":"The tiny framework for building hypertext applications.","homepage":"https://hyperapp.dev","keywords":["framework","hyperapp","frontend","vdom","web","app","ui"],"repository":{"type":"git","url":"git+https://github.com/jorgebucaran/hyperapp.git"},"author":{"name":"Jorge Bucaran"},"bugs":{"url":"https://github.com/jorgebucaran/hyperapp/issues"},"users":{"rexpan":true,"drewigg":true,"matejmazur":true,"me7":true,"lassevolkmann":true,"chilledfrogs":true,"jorgebucaran":true}}