Last active
May 19, 2020 19:02
-
-
Save tornqvist/78af058bd9e0c8a455f053703510bf74 to your computer and use it in GitHub Desktop.
A series of examples illustrating a new component API I've been working on in conjunction with changes to nanohtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var { html, render } = require('nanohtml') | |
var { Component, memo, onupdate } = require('nanohtml/component') | |
// This example illustrates how memo can be used to maintain form state. | |
// On first render, getInitialValues is called and read values either | |
// from the fields argument or from local storage. | |
// Whenever a field changes its value is persisted to local storage. | |
var Form = Component(function (fields, values = memo(getInitialValues)) { | |
var update = onupdate(function (fields, values) { | |
if (values) { | |
for (const [key, value] of Object.entries(values)) { | |
window.localStorage.set(key, value) | |
} | |
} | |
}) | |
return html` | |
<form> | |
${fields.map((attrs) => html` | |
<input ${attrs} value="${values[attrs.name]}" oninput=${(event) => update(fields, { ...values, [attrs.name]: event.target.value })}> | |
`)} | |
</form> | |
` | |
}) | |
function getInitialValues (fields) { | |
return fields.reduce(function (acc, attrs) { | |
acc[attrs.name] = attrs.value || window.localStorage.get(attrs.name) || '' | |
return acc | |
}, {}) | |
} | |
render(html` | |
<body> | |
${Form([ | |
{ type: 'text', name: 'firstname' }, | |
{ type: 'text', name: 'lastname' } | |
])} | |
</body> | |
`, document.body) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var mapboxgl = require('mapbox-gl') | |
var { html, render } = require('nanohtml') | |
var { Component, memo, onupdate, onload } = require('nanohtml/component') | |
// This example uses onload to render an interactive map. | |
// The map instance is memoized as the second argument. The | |
// instance can accessed with the memo utility. | |
// It compares the coordinates on update, and if changed, | |
// pans the map to the new coordinates. | |
var Map = Component(function ([lng, lat]) { | |
var update = onupdate(function (prev) { | |
return function beforeupdate (next, map = memo()) { | |
// Compare the arguments used to issue an update with the arguments | |
// used for the previous update to determine if the coordinates have | |
// changed. If so, pan the map to the new coordinates. | |
if (map && prev.join() !== next.join()) map.panTo(next) | |
} | |
}) | |
onload(function (el) { | |
var map = new mapboxgl.Map({ | |
container: el, | |
center: [lng, lat], | |
style: 'mapbox://styles/mapbox/streets-v11' | |
}) | |
var onresize = map.resize.bind(map) | |
// Issue an update to memoize the map instance | |
update([lng, lat], map) | |
window.addEventListener('resize', onresize) | |
return function unload () { | |
map.remove() | |
window.removeEventListener('resize', onresize) | |
} | |
}) | |
return html`<div></div>` | |
}) | |
render(html` | |
<body> | |
${Map([17.841, 59.326])} | |
</body> | |
`, document.body) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var { html, render } = require('nanohtml') | |
var { Component, memo, onupdate } = require('nanohtml/component') | |
// This example illustrates how to use the onupdate hook. | |
// Whenever the component is rendered/updated it starts a timer | |
// which when expiring renders a "Too slow!" message. | |
// Clicking the button will reset the timer. | |
// The time can be overriden by the caller at any time. | |
var Awake = Component(function (time = memo(5000)) { | |
var update = onupdate(function (time = memo()) { | |
if (time > 0) { | |
var timeout = setTimeout(function () { | |
update(time - 1000) | |
}, 1000) | |
} | |
// This is called before the next update is executed | |
return function cleanup () { | |
clearTimeout(timeout) | |
} | |
}) | |
return html` | |
<h1>Stay awake!</h1> | |
<p>Click button within ${Math.floor(time / 1000)} seconds</p> | |
${time > 0 ? html` | |
<button onclick=${() => update(5000)}>Click me!</button> | |
` : html` | |
<p>Too slow!</p> | |
`} | |
` | |
}) | |
render(html` | |
<body> | |
${Awake()} | |
</body> | |
`, document.body) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var { html, render } = require('nanohtml') | |
var { Component, Ref } = require('nanohtml/component') | |
// This example uses a Ref to start playing a video when clicking a button | |
// The Ref is a proxied _live_ HTMLCollection which serializes to a string. | |
// By assinging the serialized string as class to child elements, they | |
// can be accessed by index or id. | |
var Player = Component(function (uri) { | |
var ref = new Ref() | |
return html` | |
<video src="${uri}" id="player" class="${ref}" type="video/mp4"></video> | |
<button onclick=${() => ref.player.play()}>Play</button> | |
` | |
}) | |
render(html` | |
<body> | |
${Player('http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4')} | |
</body> | |
`, document.body) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment