cycle-custom-elementify
v1.0.2
Published
##### Experimental
Downloads
2
Readme
Cycle.js customElementify
Experimental
Helper function that takes a Cycle.js component ((sources: Sources) => Sinks
) and returns a JavaScript class that can be registered as a Web Component custom element with document.registerElement
:
import customElementify from 'cycle-custom-elementify';
function main(sources) {
// ...
}
const customElementClass = customElementify(main);
document.registerElement('my-web-component', { prototype: customElementClass });
<my-web-component></my-web-component>
Installation
npm install cycle-custom-elementify
Required!
Your target browser must support Custom Elements v0. To install the polyfill:
npm install webcomponents.js
- Include
<script src="./node_modules/webcomponents.js/webcomponents.js"></script>
in your page
This library is experimental and so far only supports Cycle.js apps written with xstream. You can only customElementify
a function that expects xstream sources and sinks.
Usage
Your Cycle.js component function can expect sources to have DOM
and props
:
// TypeScript signature:
type Sources = {
DOM: DOMSource,
props: Stream<Object>
}
Your component's sinks should have DOM
and any other sink will be converted to DOM events on the custom element:
// TypeScript signature:
type Sinks = {
DOM: Stream<VNode>,
bark: Stream<string>,
// `bark` sink stream will be converted to DOM Events emitted on the resulting custom element
}
Write your function MyButton: (sources: Sources) => Sinks
like you would do with any typical Cycle.js app. sources.props
is a Stream of objects that contain attributes given to the custom element.
Then convert it to a custom element class:
import customElementify from 'cycle-custom-elementify';
const customElementClass = customElementify(MyButton);
Then, register your custom element on the DOM with a tagName of your choice:
document.registerElement('my-button', customElementClass);
If you want to use this my-button
inside another Cycle.js app, be careful to wait for the WebComponentsReady
event first:
window.addEventListener('WebComponentsReady', () => {
document.registerElement('my-button', { prototype: customElementify(MyButton) });
Cycle.run(main, {
DOM: makeDOMDriver('#app-container')
});
});
If your parent Cycle.js app passes attributes to the custom element, then they will be available as sources.props
in the child Cycle.js app (inside the custom element):
function main(sources) {
// ...
const vnode$ = xs.of(
div([
h('my-button', {attrs: {color: 'red'}})
])
);
// ...
}
function MyButton(sources) {
const color$ = sources.props.map(p => p.color);
// ...
}
Known issues
- This is an experimental library :)
- We're following the Custom Elements V0 spec, not yet V1
- The custom elements generated by this helper do not support children yet, only attributes
- Using this library might confuse the Cycle.js DevTool