chore: update site, readme, & examples for v2.0 features
This commit is contained in:
parent
4d4fdb3d89
commit
4c885ccf9d
7 changed files with 209 additions and 4338 deletions
110
README.md
110
README.md
|
@ -5,46 +5,53 @@
|
|||
[](https://www.npmjs.com/package/web-component-base)
|
||||
[](https://bundlephobia.com/package/web-component-base)
|
||||
|
||||
> A zero-dependency, ~600 Bytes (minified & gzipped), JS base class for creating reactive custom elements easily
|
||||
🤷♂️ zero-dependency, 🤏 tiny JS base class for creating reactive custom elements easily ✨
|
||||
|
||||
When you extend the `WebComponent` class for your component, you only have to define the `template` and `properties`. Any change in any property value will automatically cause just the component UI to render.
|
||||
|
||||
The result is a reactive UI on property changes. [View on CodePen ↗](https://codepen.io/ayoayco-the-styleful/pen/ZEwoNOz?editors=1010)
|
||||
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
<ol>
|
||||
<li><a href="#import-via-unpkg">Import via unpkg</a></li>
|
||||
<li><a href="#installation-via-npm">Installation via npm</a></li>
|
||||
<li><a href="#usage">Usage</a></li>
|
||||
<li><a href="#template-vs-render">`template` vs `render()`</a></li>
|
||||
<li><a href="#prop-access">Prop access</a>
|
||||
<ol>
|
||||
<li><a href="#alternatives">Alternatives</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#quick-start-example">Quick Start Example</a></li>
|
||||
<li><a href="#life-cycle-hooks">Life-Cycle Hooks</a>
|
||||
<ol>
|
||||
<li><a href="#oninit">`onInit`</a> - the component is connected to the DOM, before view is initialized</li>
|
||||
<li><a href="#afterviewinit">`afterViewInit`</a> - after the view is first initialized</li>
|
||||
<li><a href="#ondestroy">`onDestroy`</a> - the component is disconnected from the DOM</li>
|
||||
<li><a href="#onchanges">`onChanges`</a> - every time an attribute value changes</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#library-size">Library Size</a></li>
|
||||
</ol>
|
||||
</details>
|
||||
## Features
|
||||
|
||||
## Import via unpkg
|
||||
- A props API that synchronizes your components' property values and HTML attributes
|
||||
- Sensible life-cycle hooks that you understand and remember
|
||||
- An html tagged templates powered by preact's html/mini
|
||||
- Attach functions as "side effects" that gets triggered on property value changes with attachEffect (example)
|
||||
- Provided out-of-the-box with McFly, a powerful no-framework framework
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Installation](#installation)
|
||||
1. [Import via unpkg](#import-via-unpkg)
|
||||
2. [Installation via npm](#installation-via-npm)
|
||||
3. [Usage](#usage)
|
||||
4. [`template` vs `render()`](#template-vs-render)
|
||||
5. [Prop access](#prop-access)
|
||||
1. [Alternatives](#alternatives)
|
||||
6. [Quick Start Example](#quick-start-example)
|
||||
7. [Life-Cycle Hooks](#life-cycle-hooks)
|
||||
1. [`onInit`](#oninit) - the component is connected to the DOM, before view is initialized
|
||||
2. [`afterViewInit`](#afterviewinit) - after the view is first initialized
|
||||
3. [`onDestroy`](#ondestroy) - the component is disconnected from the DOM
|
||||
4. [`onChanges`](#onchanges) - every time an attribute value changes
|
||||
8. [Library Size](#library-size)
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
The library is distributed as complete ESM modules, published on [NPM](https://ayco.io/n/web-component-base). Please file an issue in our [issue tracker](https://ayco.io/gh/web-component-base/issues) for problems or requests regarding our distribution.
|
||||
|
||||
### Import via unpkg (no bundlers needed!)
|
||||
Import using [unpkg](https://unpkg.com/web-component-base) in your vanilla JS component. We will use this in the rest of our [usage examples](#usage).
|
||||
|
||||
Please check
|
||||
|
||||
```js
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/WebComponent.min.js";
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
```
|
||||
|
||||
## Installation via npm
|
||||
Usable for projects with bundlers or using import maps.
|
||||
### Installation via npm
|
||||
Usable for projects with bundlers or using import maps pointing to to the specific files in downloaded in your `node_modules/web-component-base`.
|
||||
|
||||
```bash
|
||||
npm i web-component-base
|
||||
|
@ -56,13 +63,17 @@ In your component class:
|
|||
|
||||
```js
|
||||
// HelloWorld.mjs
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/WebComponent.min.js";
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
|
||||
class HelloWorld extends WebComponent {
|
||||
static properties = ["my-name", "emotion"];
|
||||
static props ={
|
||||
myName: 'World',
|
||||
emotion: 'sad'
|
||||
}
|
||||
get template() {
|
||||
return `
|
||||
<h1>Hello ${this.props.myName}${this.props.emotion === "sad" ? ". 😭" : "! 🙌"}</h1>`;
|
||||
<h1>Hello ${this.props.myName}${this.props.emotion === "sad" ? ". 😭" : "! 🙌"}</h1>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,13 +119,11 @@ This mental model attempts to reduce the cognitive complexity of authoring compo
|
|||
|
||||
```js
|
||||
class HelloWorld extends WebComponent {
|
||||
static properties = ["my-prop"];
|
||||
onInit() {
|
||||
let count = 0;
|
||||
this.onclick = () => this.props.myProp = `${++count}`
|
||||
static props = {
|
||||
myProp: 'World'
|
||||
}
|
||||
get template() {
|
||||
return `
|
||||
return html`
|
||||
<h1>Hello ${this.props.myProp}</h1>
|
||||
`;
|
||||
}
|
||||
|
@ -133,7 +142,7 @@ this.props.myName = 'hello'
|
|||
this.setAttribute('my-name','hello');
|
||||
```
|
||||
|
||||
Therefore, this will tell the browser that the UI needs a render if the attribute is one of the component's observed attributes we explicitly provided with `static properties = ['my-name']`;
|
||||
Therefore, this will tell the browser that the UI needs a render if the attribute is one of the component's observed attributes we explicitly provided with `static props`;
|
||||
|
||||
> [!NOTE]
|
||||
> The `props` property of `WebComponent` works like `HTMLElement.dataset`, except `dataset` is only for attributes prefixed with `data-`. A camelCase counterpart using `props` will give read/write access to any attribute, with or without the `data-` prefix.
|
||||
|
@ -155,10 +164,12 @@ Here is an example of using a custom element in a single .html file.
|
|||
<head>
|
||||
<title>WC Base Test</title>
|
||||
<script type="module">
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/WebComponent.min.js";
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
|
||||
class HelloWorld extends WebComponent {
|
||||
static properties = ["my-name"];
|
||||
static props = {
|
||||
myName: 'World'
|
||||
}
|
||||
get template() {
|
||||
return `<h1>Hello ${this.props.myName}!</h1>`;
|
||||
}
|
||||
|
@ -188,7 +199,7 @@ Define behavior when certain events in the component's life cycle is triggered b
|
|||
- Best for setting up the component
|
||||
|
||||
```js
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/WebComponent.min.js";
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
|
||||
class ClickableText extends WebComponent {
|
||||
// gets called when the component is used in an HTML document
|
||||
|
@ -225,7 +236,7 @@ class ClickableText extends WebComponent {
|
|||
- best for undoing any setup done in `onInit()`
|
||||
|
||||
```js
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/WebComponent.min.js";
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
|
||||
class ClickableText extends WebComponent {
|
||||
|
||||
|
@ -252,7 +263,7 @@ class ClickableText extends WebComponent {
|
|||
- Triggered when an attribute value changed
|
||||
|
||||
```js
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/WebComponent.min.js";
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
|
||||
class ClickableText extends WebComponent {
|
||||
// gets called when an attribute value changes
|
||||
|
@ -269,4 +280,15 @@ class ClickableText extends WebComponent {
|
|||
|
||||
## Library Size
|
||||
|
||||
The bundle size was reported to be 587 Bytes (minified & gzipped) by [bundlephobia](https://bundlephobia.com/package/web-component-base). Running [size-limit](https://npmjs.com/package/@size-limit/preset-small-lib) reports the base class size as around 760 Bytes (minified & brotlied), and using the `WebComponent.min.js` version gets it down to around 400 Bytes.
|
||||
All the functions and the base class in the library are minimalist by design and only contains what is needed for their purpose.
|
||||
|
||||
As of the major release v2.0.0, the base class is around 1.7 kB (min + gzip) according to [bundlephobia.com](https://bundlephobia.com/package/web-component-base@2.0.0) and 1.1 kB (min + brotli) according to [size-limit](http://github.com/ai/size-limit). There is an increase in size before this release -- primarily for advanced features in building complex applications.
|
||||
|
||||
> [!NOTE]
|
||||
> As a builder of both simple sites and complex web apps, I recognize that not all custom elements need advanced features for reactivity.
|
||||
>
|
||||
>I also don't want to get things in my code that I don't need (YAGNI -- You Aren't Gonna Need It)... and I want a base class for simpler use cases that don't have Proxy props or attaching effects...
|
||||
>
|
||||
>To address this, I am working on a "lite" version my base class... please stay tuned.
|
||||
>
|
||||
> -Ayo
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
@ -10,23 +10,19 @@
|
|||
}
|
||||
</style>
|
||||
<script type="module">
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@1.13.3/WebComponent.min.js";
|
||||
import {
|
||||
WebComponent,
|
||||
html,
|
||||
} from "https://unpkg.com/web-component-base@latest/index.js";
|
||||
|
||||
/**
|
||||
* @see https://ayco.io/n/web-component-base
|
||||
*/
|
||||
class Counter extends WebComponent {
|
||||
static properties = ["count"];
|
||||
onInit() {
|
||||
this.props.count = 0;
|
||||
this.onclick = () => ++this.props.count;
|
||||
}
|
||||
onChanges(changes) {
|
||||
console.log(changes);
|
||||
// now click the button & check your devtools console
|
||||
}
|
||||
export class Counter extends WebComponent {
|
||||
static props = {
|
||||
count: 0,
|
||||
};
|
||||
get template() {
|
||||
return `<button>${this.props.count}</button>`;
|
||||
return html`<button onClick=${() => ++this.props.count}>
|
||||
${this.props.count}
|
||||
</button>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
27
sample.html
27
sample.html
|
@ -1,27 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>WC Base Test</title>
|
||||
<script type="module">
|
||||
import { WebComponent } from "./src/WebComponent.js";
|
||||
|
||||
class HelloWorld extends WebComponent {
|
||||
static properties = ["my-name"];
|
||||
get template() {
|
||||
return `<h1>Hello ${this.props.myName}!</h1>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hello-world", HelloWorld);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<hello-world my-name="Ayo"></hello-world>
|
||||
<script>
|
||||
const helloWorld = document.querySelector("hello-world");
|
||||
setTimeout(() => {
|
||||
helloWorld.props.myName = "Ayo zzzZzzz";
|
||||
}, 2500);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
4188
site/package-lock.json
generated
4188
site/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,7 @@
|
|||
<style>
|
||||
.my-header {
|
||||
border-radius: 5px;
|
||||
background: linear-gradient(45deg, #3054bf, #416fff);
|
||||
background: linear-gradient(45deg, var(--color-primary), var(--color-fade));
|
||||
color: white;
|
||||
margin: 1em 0;
|
||||
padding: 1.5em;
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
<div class="call-to-action">
|
||||
<a id="primary"
|
||||
href="https://ayco.io/gh/web-component-base#readme">
|
||||
<a id="primary" href="https://ayco.io/gh/web-component-base#readme">
|
||||
Learn More
|
||||
</a>
|
||||
<a href="https://codepen.io/ayoayco-the-styleful/pen/PoVegBK?editors=1010">Playground →</a>
|
||||
<a
|
||||
href="https://codepen.io/ayoayco-the-styleful/pen/PoVegBK?editors=1010"
|
||||
target="_blank"
|
||||
>Playground →</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.call-to-action {
|
||||
.call-to-action {
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
justify-content: center;
|
||||
|
@ -31,14 +34,14 @@
|
|||
min-width: 35%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-device-width: 430px) {
|
||||
@media only screen and (max-device-width: 430px) {
|
||||
.call-to-action {
|
||||
flex-direction: column;
|
||||
& a {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
Hello! This page is an example McFly page.
|
||||
|
@ -18,6 +18,32 @@
|
|||
url: "https://ayco.io",
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
@counter-style publish-icons {
|
||||
system: cyclic;
|
||||
symbols: "️✅";
|
||||
suffix: " ";
|
||||
}
|
||||
main {
|
||||
font-size: large;
|
||||
|
||||
& section ul {
|
||||
list-style: publish-icons;
|
||||
}
|
||||
& hr {
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
& section p:not(blockquote *):first-of-type::first-letter {
|
||||
font-weight: 900;
|
||||
font-size: 2rem;
|
||||
line-height: 2rem;
|
||||
float: left;
|
||||
color: var(--color-primary);
|
||||
margin-top: -8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</my-head>
|
||||
<body>
|
||||
<awesome-header>
|
||||
|
@ -25,61 +51,100 @@
|
|||
<span slot="description">{{ project.description }}</span>
|
||||
</awesome-header>
|
||||
<main>
|
||||
<section style="font-size: large;">
|
||||
<section>
|
||||
<p>
|
||||
By extending our base class, you get an easy authoring experience as you would expect in writing your components:</p>
|
||||
By extending our base class, you get the easy authoring experience you
|
||||
have come to expect when coming from more mature JS frameworks-- all
|
||||
with zero-dependency, minimal tooling and very thin abstraction over
|
||||
the vanilla web platform.
|
||||
</p>
|
||||
<ul>
|
||||
<li>A <code-block inline>props</code-block> API that synchronizes your components' property values and HTML attributes</li>
|
||||
<li>
|
||||
A robust <code-block inline>props</code-block> API that synchronizes
|
||||
your components' property values and HTML attributes
|
||||
</li>
|
||||
<li>Sensible life-cycle hooks that you understand and remember</li>
|
||||
<li>Extensible templates & renderer (examples in-progress)</li>
|
||||
<li>Provided out-of-the-box with <a href="https://ayco.io/gh/McFly">McFly</a>, a powerful no-framework framework</li>
|
||||
<li>
|
||||
A minimal <code-block inline>html</code-block> function for tagged
|
||||
templates powered by Preact's tiny (450 Bytes)
|
||||
<a href="http://github.com/developit/htm" target="_blank"
|
||||
>html/mini</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Attach "side effects" that gets triggered on property value changes
|
||||
with <code-block inline>attachEffect</code-block> (<a
|
||||
href="https://codepen.io/ayoayco-the-styleful/pen/ExrdWPv?editors=1011"
|
||||
target="_blank"
|
||||
>example</a
|
||||
>)
|
||||
</li>
|
||||
<li>
|
||||
Provided out-of-the-box with
|
||||
<a href="https://ayco.io/gh/McFly">McFly</a>, a powerful
|
||||
no-framework framework
|
||||
</li>
|
||||
</ul>
|
||||
<call-to-action></call-to-action>
|
||||
<warning-block>See this issue for FAQs or comment your own: <a href="https://github.com/ayoayco/web-component-base/issues/3">Issue #3</a></warning-block>
|
||||
<my-quote type="info">
|
||||
<p>
|
||||
Version 2.0.0-beta is out! 🎉
|
||||
</p>
|
||||
<p>
|
||||
We are now able to attach "side effects" to property value changes, from inside the component and outside.
|
||||
</p>
|
||||
<p>
|
||||
Play on <a href="https://codepen.io/ayoayco-the-styleful/pen/ExrdWPv?editors=1011">CodePen</a>.
|
||||
</p>
|
||||
</my-quote>
|
||||
</section>
|
||||
<hr style="margin: 2em 0;" />
|
||||
<section style="font-size: large;">
|
||||
<hr />
|
||||
<section>
|
||||
<p>Why use this base class?</p>
|
||||
<p>
|
||||
When you extend the WebComponent class for your component, you only have to define the template and properties. Any change in any property value will automatically cause just the component UI to render.
|
||||
Writing Web Components from the vanilla
|
||||
<code-block inline>HTMLElement</code-block> can easily get confusing
|
||||
and hard to maintain, especially when coming from JS frameworks with
|
||||
advanced tooling.
|
||||
</p>
|
||||
<p>
|
||||
This project aims to ease this with the thinnest possible abstraction
|
||||
from vanilla and virtually zero need for advanced tooling. It works
|
||||
without bundlers, transpilers, or polyfills.
|
||||
</p>
|
||||
<p>
|
||||
When you extend the <code-block inline>WebComponent</code-block> class
|
||||
for your component, you only have to define the template and
|
||||
properties. Any change in any property value will automatically cause
|
||||
just the component UI to render.
|
||||
</p>
|
||||
|
||||
<p>The result is a reactive UI on property changes: <my-counter></my-counter></p>
|
||||
<p>
|
||||
The result is a reactive UI on property changes:
|
||||
<my-counter></my-counter>
|
||||
</p>
|
||||
<code-block language="js">
|
||||
<pre>
|
||||
import { WebComponent } from "https://unpkg.com/web-component-base@1.13.3/WebComponent.min.js";
|
||||
import { WebComponent, html } from "https://unpkg.com/web-component-base@2.0.0/index.js";
|
||||
|
||||
export class Counter extends WebComponent {
|
||||
static properties = ["count"];
|
||||
onInit() {
|
||||
this.props.count = 0;
|
||||
this.onclick = () => ++this.props.count;
|
||||
static props = {
|
||||
count: 0
|
||||
}
|
||||
get template() {
|
||||
return `<button>${this.props.count}</button>`;
|
||||
return html`
|
||||
<button onClick=${() => ++this.props.count}>
|
||||
${this.props.count}
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("my-counter", Counter);
|
||||
</pre>
|
||||
customElements.define("my-counter", Counter);</pre
|
||||
>
|
||||
</code-block>
|
||||
</section>
|
||||
</main>
|
||||
<my-footer>
|
||||
<span>This site is built with <a href="https://github.com/ayoayco/McFly">McFly</a>, the no-framework framework;
|
||||
</span><br />
|
||||
<span>✨ Star on <a href="https://github.com/ayoayco/web-component-base">GitHub</a> to support;
|
||||
</span><br />
|
||||
<span
|
||||
>This site is built with
|
||||
<a href="https://github.com/ayoayco/McFly">McFly</a>, the no-framework
|
||||
framework; </span
|
||||
><br />
|
||||
<span
|
||||
>✨ Star on
|
||||
<a href="https://github.com/ayoayco/web-component-base">GitHub</a> to
|
||||
support; </span
|
||||
><br />
|
||||
<span>
|
||||
A project by <a href="{{ author.url }}">{{ author.name }}</a>
|
||||
</span>
|
||||
|
|
Loading…
Reference in a new issue