TypeScript Decorators for Web Components

Introducing @readymade/core

Readymade is a JavaScript library for composing user interfaces with Web Components. @readymade/core provides an interface for bootstrapping new custom elements.

What is Readymade?

Readymade simplifies handling template and styling for Web Components via an interface similar to Angular and makes heavy use of TypeScript and Decorators.

Example

In this example, a class named MyButtonComponent includes a template and styling for a button. A call to action is bound to the template through the state property. MyButtonComponent includes decorators and methods for handling when the user clicks. The button component broadcasts a 'bang' event when the user clicks on it. Readymade components are stateful, enabling one-way data binding with a template. Emitters broadcast events with the BroadcastChannel API, meaning Readymade components can emit events where they otherwise can't bubble and even to other browsing contexts like a ServiceWorker.

Getting Started

Install

Install readymade/core via npm or yarn.

If typescript is not already part of your project, install it too.

Readymade requires experimentalDecorators to be set to true in your tsconfig.json. A sample minimal recommended configuration is below.

Readymade is compiled with Typescript.

First Component

Code your component. First, import all the necessary Decorators and classes for a component that implements ShadowDOM.

Declare a html template and styling using the Component decorator.

Declare a new custom element.

Use the CustomElements API to define a new HTML element called my-component.

Use the new component in your template.

Using Readymade

Decorators

Readymade implements UI components using a decorator pattern. Decorators are currently in stage 2 proposal for the ECMAScript Internationalization API Specification. Readymade implements decorators with TypeScript. A class decorator called Component allows you to declare styling and template for custom elements. The Emitter decorator provides a way to declare CustomEvents that can be emitted or broadcasted to other elements. The Listen decorator binds a method to the callback of an event listener.

Types of Readymade Decorators

@Component

The Component decorator modifies the class it decorates by providing metadata needed for Readymade to compile the template and styling defined within it.

@Listen

The Listen sets up addEventListener for Events. This example listens for keyup events and emits a CustomEvent when the user presses Enter. This method decorator takes the event name in it's first argument. When listening for broadcasted events over the BroadcastChannel API, a channel name can be specified in the second argument.

@Emitter

The Emitter decorator defines CustomEvent the component can emit. This decorator takes the CustomEvent type as a first arugment and options for the CustomEvent in the second argument. If you want to broadcast Event with this Emitter, a channel name can be specified in the third argument.

Emitters are stored on the component instance with the property emitter. There are two methods for Emitters: emit and broadcast.

Data Binding

Readymade includes state used for one-way data binding with templates.

In the example below state is declared with a property called buttonCopy.

template

buttonCopy is bound to the template. Set the value of buttonCopy in the class constructor so the button can display with a call to action: Click.

Proxy

Readymade listens for changes to state with ES2015 Proxy and then uses the DOM TreeWalker API to crawl nodes and update template.

Components

Readymade comes packaged with several component classes that are used to bootstrap web component development. Readymade takes the hassle out of remembering which DOM elements support ShadowDOM. Readymade takes the guess work out of implementing autonomous custom elements and customized built-in elements.

Basic Usage

Typically you would extend HTMLElement when coding a custom element that uses ShadowDOM.

With Readymade extend CustomElement instead. CustomElement extends HTMLElement, but also bootstraps event listeners and state.

Sometimes you need to extend other elements to retain Web Accessibility features or other user experience paradigms.

This is called a customized built-in element. Readymade handles styling differently for customized built-in elements by passing styles into the <head> due to the lack of ShadowDOM.

Readymade provides a single interface for handling 'autonomous custom' and 'customized built-in' elements.

Why Do We Need Another Web Component Library?

Readymade started as an exercise to see how component based frameworks like Angular, Polymer, and Stencil could be built with just available browser API. The microlibrary that came to fruition simplifes web component development and includes some powerful features. The Component metadata decorator provides an easy interface for declaring styling and template. One way data binding allows you to forget about setting innerHTML and attributes of elements. Method decorators bind CustomEvent listeners and use the BroadcastChannel API to overcome limitations of event bubbling. Readymade is treeshakable, meaning you only import the code your project needs and leave the rest behind.

A simple 'Hello World' readymade project compiled with TypeScript and Terser minifies down to ~1Kb (gzipped). This site is built with Readymade and weighs in ~7Kb (gzipped). The bundle deployed to Github Pages includes minimal application logic, a small library of components, polyfills, and third party library for syntax highlighting (PrismJS)and it weighs in at ~38Kb (gzipped).

The name of the project 'readymade' is an homage to Marcel Duchamp, an artist in the 20th century who made art with ordinary objects. Like Duchamp's readymades, this library picks up ordinary objects found in ECMAScript, repositions and joins them together to form something completely new.

Resources