https://github.com/iconstorm/lol-element
A JavaScript base class for creating Web Components like you know what you're doing
https://github.com/iconstorm/lol-element
javascript javascript-library web-components
Last synced: over 1 year ago
JSON representation
A JavaScript base class for creating Web Components like you know what you're doing
- Host: GitHub
- URL: https://github.com/iconstorm/lol-element
- Owner: iconstorm
- Created: 2021-03-23T19:58:10.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2022-08-12T17:24:39.000Z (almost 4 years ago)
- Last Synced: 2025-02-18T23:17:33.126Z (over 1 year ago)
- Topics: javascript, javascript-library, web-components
- Language: JavaScript
- Homepage:
- Size: 194 KB
- Stars: 1
- Watchers: 1
- Forks: 1
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# lol element
 
A JavaScript base class for creating Web Components like you know what you're doing.
## Goals
๐งฌ **tiny API**: if you need to invest time in learning something, let it be how custom elements work and not ephemeral library APIs.
๐ตโ๐ซ **just enough abstractions**: custom elements can be cool, but they're definitely not fancy, it is what it is.
๐ซ **small and lightweight**: if you need to debug, start confidently with your own code, it's probably not lol.
๐ณ **no build step necessary**: if you enjoy spending hours debugging a cryptic compile error in the terminal and hunting for that buggy dependency, we don't.
๐ญ **a list with random emoji in the README**: checked.
## Install
With npm (or similar):
```
npm install @iconstorm/lol-element
```
Via CDN, you can use a script tag:
```html
const { LOL, css, html } = lol // global window.lol is made available
```
or hotlink in your ES modules:
```js
import { LOL, css, html } from 'https://unpkg.com/@iconstorm/lol-element?module'
```
## Usage
Starting with Web Components and custom HTML elements?
Please go read the chapter dedicated to them on [the great javascript.info site](https://javascript.info/custom-elements). Once you're familiar with custom elements in general, you'll be enjoying LOL within minutes.
Also the [Classes chapter](https://javascript.info/classes) is a recommended read.
No build step or transpiling is necessary. All of this just works in the browser.
Define a component:
```js
import { LOL, html, css } from 'https://unpkg.com/@iconstorm/lol-element'
class HelloWorld extends LOL {
static get attributes () {
return { name: 'with-exclamation-mark', boolean: true }
}
static get styles () {
return css`
span { font-size: 300%; }
`
}
template () {
return html`
Hello World${this.withExclamationMark ? '!' : ''}
`
}
}
customElements.define('lol-hello-world', HelloWorld)
```
Use it in your markup:
```html
```
๐ฉ [Try this on CodePen.](https://codepen.io/acstll/pen/oNWNrgb)
## API
- [`LOL` class](#the-lol-class)
- [static `shadowOptions`](#static-shadowoptions-static-getter-or-property)
- [static `attributes`](#static-attributes-static-getter-or-property)
- [static `styles`](#static-styles-static-getter-or-property)
- [`template()`](#template-method)
- [`changed()`](#changed-method)
- [`{propertyName}Changed()`](#propertynamechanged-method)
- [`emit()`](#emit-method)
- [`render()`](#render-method)
- [`renderRoot`](#renderroot-property)
- [Lifecycle callbacks](#lifecycle-callbacks)
- [Template syntax](#template-syntax)
- [Named exports](#named-exports)
### The `LOL` class
#### static `shadowOptions` _static (getter or property)_
Define the [Shadow DOM options](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#syntax) being passed to the `attachShadow()` call.
Defaults to `{ mode: 'open' }`. Use `null` to not use Shadow DOM.
---
#### static `attributes` _static (getter or property)_
Define the element's attributes to be observed with an array of names or [config objects](https://github.com/iconstorm/lol-element/blob/main/src/lol-element.js#L157), with following keys:
- `name` string: The name of the attribute
- `reflect` boolean (default: `true`): Whether the attribute should be reflected in a property
- `boolean` boolean (default: `false`): Whether the attribute is a [boolean type of attribute](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started#boolean_attributes)
- `read` function (default: `x => x`): A function to process the property value being accessed
- `write` function (default: `x => x`): A function to process the value being set in the attribute
- `fallbackValue`: The value returned by the property getter when the attribute is missing
Except for `name`, all options are optional.
An attribute being reflected means that for a given `foo-bar` attribute, a `fooBar` getter/setter property will be created. So assigning a value to `fooBar` will set the same value to the `foo-bar` attribute. `LOL` has no observable/reactivity system, for simplicity's sake, it leverages the browser's via `attributeChangedCallback`.
Attributes and props?
Attributes live in HTML, properties belong in JavaScript objects. If the different is not clear, [stack overflow is your friend](https://stackoverflow.com/a/6004028). This can create some confusion. This [post by Rich Harris](https://dev.to/richharris/why-i-don-t-use-web-components-2cia) can be interesting (scroll down to part 6).
---
#### static `styles` _static (getter or property)_
Define the styles for the component with CSS. The ` css`` ` template literal tag must be used.
Example
```js
import { css } from '@iconstorm/lol-element'
// ..
static get styles() {
return css`
:host {
font-size: 100%;
}
`
}
```
---
#### `template()` _method_
Define the markup of the component, the ` html`` ` template literal tag must be used.
Parameters:
- `host` object: The element instance
๐ฅ This method is usually called `render()` in many libraries and frameworks.
Example
```js
import { html } from '@iconstorm/lol-element'
// ..
template() {
return html`
Loren ipsum
`
}
```
---
#### `changed()` _method_
Fires every time an attribute is added, removed, or changed. This is only an alias for `attributeChangedCallback` for the convenience of avoiding `super.attributeChangedCallback()`.
Parameters:
- `name` string: The name of the attribute the changed
- `oldValue` string
- `newValue` string
---
#### `{propertyName}Changed()` _method_
An individual callback for every observed attribute, when implemented. For example, every time the `foo-bar` attribute changes, if there's a `fooBarChanged()` method defined, it will be called.
Parameters:
- `oldValue` string
- `newValue` string
---
#### `emit()` _method_
A helper to dispatch custom events from within the element.
Parameters:
- `eventName` string: The name of the event
- `detail` any: The thing being emitted, available in `event.detail`
- `options` object: any other options for the event, defaults to `{ bubbles: true, cancelable: true }`
---
#### `render()` _method_
Call this method to trigger a DOM update. You shouldn't need to implement this method.
---
#### `renderRoot` _property_
The DOM node where rendering happens. This is either the element's [`shadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) (when using Shadow DOM) or the host element itself (when not).
### Lifecycle callbacks
Apart from `changed()` and `{propertyName}Changed()`, no other lifecycle callbacks are provided other than the ones offered by default in HTMLElement:
- `constructor()`
- `connectedCallback()`
- `attributeChangedCallback()`
- `disconnectedCallback()`
> See [Using the lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks) in MDN.
โ ๏ธ Don't forget the `super` keyword when using these.
If you don't call `super` on `constructor`, `connectedCallback` and `attributeChangedCallback`, things will break.
```js
class MyComponent extends LOL {
constructor() {
super()
// ..
}
connectedCallback() {
super.connectedCallback()
// ..
}
attributeChangedCallback() {
super.attributeChangedCallback()
// ..
}
}
```
More info: https://javascript.info/class-inheritance#overriding-a-method
### Template syntax
See [ยตhtml](https://www.npmjs.com/package/uhtml) for now.
### Named exports
- `LOL` - extends `LOLElement`,
- `LOLElement` - extends `HTMLELement`, `render()` is not implemented
- `css`
- `html`*
- `svg`*
```js
import { LOL, LOLElement, css, html, svg } from '@iconstorm/lol-element'
```
*implementation may vary depending on _flavor_ (more on this soon).
## Thank-yous (prior art)
- [FAST](https://github.com/microsoft/fast/)
- [swiss](https://github.com/luwes/swiss)
- [Lit](https://github.com/lit/lit/)
- [Stencil](https://github.com/ionic-team/stencil)
- [hybrids](https://github.com/hybridsjs/hybrids)
## License
MIT