https://github.com/lastmjs/functional-element
Functional custom elements
https://github.com/lastmjs/functional-element
Last synced: 3 months ago
JSON representation
Functional custom elements
- Host: GitHub
- URL: https://github.com/lastmjs/functional-element
- Owner: lastmjs
- License: mit
- Created: 2018-11-02T16:38:54.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2022-01-21T15:57:22.000Z (over 3 years ago)
- Last Synced: 2024-10-13T13:11:30.560Z (8 months ago)
- Language: JavaScript
- Homepage:
- Size: 233 KB
- Stars: 28
- Watchers: 5
- Forks: 1
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://www.npmjs.com/package/functional-element) [](https://david-dm.org/lastmjs/functional-element) [](https://david-dm.org/lastmjs/functional-element?type=dev)
# functional-element
`functional-element` exposes the custom element API in a functional manner. It allows you to express your custom element's behavior as a function. The custom element lifecycle is exposed through parameters to your function. You simply return a template or props as needed. Templating is currently handled by `lit-html`. Hook up event listeners with simple functions. No more classes, methods, or inheritance.
## Live demo
* Tic tac toe demo: https://functional-tic-tac-toe.netlify.com
* Tic tac toe code: https://github.com/lastmjs/tic-tac-toe* Calculator demo: https://mwad-functional-element.netlify.com
* Calculator code: https://github.com/lastmjs/mwad-functional-element## Installation
```bash
npm install functional-element
```## Use
`functional-element` produces bonafide custom elements. Use them as follows:
```html
```
Create them as follows:
```javascript
import { html, customElement } from 'functional-element';customElement('example-element', ({ constructing, hello }) => {
if (constructing) {
return {
hello: 'world!'
};
}return html`
${hello}
`;
});
```### Lifecycle
```javascript
import { html, customElement } from 'functional-element';customElement('example-element', ({ constructing, connecting, disconnecting, adopting }) => {
if (constructing) {
console.log(`We're in the constructor!`);
}if (connecting) {
console.log(`We're in the connectedCallback!`);
}if (disconnecting) {
console.log(`We're in the disconnectedCallback!`);
}if (adopting) {
console.log(`We're in the adopted callback!`);
}return html`
It's the cycle of life!
`;
});
```## Properties
```javascript
import { html, customElement } from 'functional-element';customElement('example-element', ({ constructing, regularProp, computedProp }) => {
if (constructing) {
return {
regularProp: `Just your average property`,
computedProp: () => {
return `This property was made by a function`;
}
};
}return html`
regularProp:${regularProp}
computedProp:${computedProp()}
`;
});
```## Listening to events
```javascript
import { html, customElement } from 'functional-element';customElement('example-element', ({ constructing, update, count }) => {
if (constructing) {
return {
count: 0
};
}return html`
update({ count: count + 1 })}>${count}
`;
});
```## Dispatching events
```javascript
import { html, customElement } from 'functional-element';customElement('example-element', ({ constructing, element, count }) => {
if (constructing) {
return {
count: 0
};
}return html`
increment(element, count)}>${count}
`;
});function increment(element, count) {
element.dispatch(new CustomEvent('increment', {
detail: {
count: count + 1
}
}));
}
```
## Async```javascript
import { html, customElement } from 'functional-element';customElement('example-element', async ({ constructing, update, count }) => {
if (constructing) {
return {
count: 0
};
}const newCount = await increment(count);
return html`
count: ${count}
`;
});async function increment(count) {
await wait(5000);
return count + 1;
}async function wait(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
```