0.0.2 • Published 7 years ago

spark-js v0.0.2

Weekly downloads
6
License
ISC
Repository
github
Last release
7 years ago

spark.js

A small library that takes the pain out of pure javascript (or typescript) web components.

What spark.js does

Spark.js is primarily used to handle template updates and attribute changes, using only javascript/typescript. There are other libraries (Polymer), that help you maintain your templates and attributes, but does that only in HTML files.

Spark.js uses jsx and decorators to create web components in a very React-like way.

Code Sample

import { CustomElement, h } from 'spark.js';

class MyComponent extends CustomElement('my-component') {
   get template() {
       return <div>Hello!</div>
   }
}

window.customElements.define(MyComponent.is, MyComponent);

Advanced:

import { CustomElement, h, ObserveAttribute } from 'spark.js';

interface PersonProps {
    age: number;
}
class Person extends CustomElement<PersonProps>('person-comp') {
    
    @ObserveAttribute()
    age: number;

    get template() {
        return <div>I am {this.age}</div>
    }
}
window.customElements.define(Person.is, Person);

class Place extends CustomElement('place-comp') {
    get template() {
        return <Person age={2}>
    }

    get styles() {
        return `
            :host {
                background-color: royalblue;
            }
        `
    }
}
window.customElements.define(Place.is, Place);

Getting Started

Installation

npm install -S spark.js

Configuration

The bare minimum tsconfig.json.

{
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "jsx": "react",
    "jsxFactory": "h",
    "moduleResolution": "node",
    "lib": [
      "es2015",
      "dom"
    ],
    "experimentalDecorators": true
  }
}

Here's a default webpack.config.js that you can use to get started.

module.exports = {
    entry: './spark-component.tsx',
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"]
    },
    output: {
        filename: 'spark-component.js',
        path: __dirname
    }
};

Events

Spark.js does not have any kind of special event system. You can use whatever kind of event system you want that works with Web Components.

There are few things to note when using spark.js components with events within each other:

  • Events must start with on and are optional in the component props. eg. onCelebrate
  • When dispatching an event, the event name must be what comes after on.
import { CustomElement, h, ObserveAttribute } from 'spark.js';

interface PersonProps {
    onCelebrate?: (data: CustomEvent) => void;
}
class Person extends CustomElement<PersonProps>('person-comp') {

    get template() {
        return <div onClick={this.onClick}>Celebrate!</div>
    }

    onClick(event) {
        this.dispatchEvent(new CustomEvent('celebrate', {
            bubbles: true,
            detail: 'Celebrate!'
        }););
    }
}
window.customElements.define(Person.is, Person);

class Place extends CustomElement('place-comp') {
    get template() {
        return <Person onCelebrate={(event) => this.celebrate(event)}>
    }

    celebrate(event: CustomEvent) {
        console.log(event.detail);
    }

}
window.customElements.define(Place.is, Place);

Top level APIs

CustomElement

The base class that all spark.js component inherit from. Takes 1 argument for the name of the component.

This sets static properties for better component management:

  • is returns the name of the web component.
  • observedAttributes returns all properties with @ObserveAttribute on them. This is the same static property as standard Web Components.

Components can override the template and style property.

  • template must return VNode.
  • styles must return a string.
class MyComponent extends CustomElement<props>('my-component') {

    get template() {
        return <div>Hi</div>
    }

    get styles() {
        `
        :host {
            background-color: royalblue;
        }
        `
    }
}

customElements.define(MyComponent.is, MyComponent)

ObserveAttribute

When ObserveAttribute is added to a property in a spark.js component, any changes made on the attribute (through DOM or setAttribute) are reflected back to the class property

When set to true, then any changes done on the property programmatically (eg. querySelector('my-comp').property = 'test') are reflected on the attribute

Whenever an property or attribute changes with ObserveAttribute, spark.js will update the DOM automatically.

h

Function used to create a VNode

...
get template() {
    return h('div', { disabled: false }, ['hello'])
}
...

Typescript

If using Typescript you can specify to use h in the jsxFactory value in tsconfig.json.

{
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "jsx": "react",
    "jsxFactory": "h",
    "moduleResolution": "node",
    "lib": [
      "es2015",
      "dom"
    ],
    "experimentalDecorators": true
  }
}

Babel

For Babel configuration, follow this guide to set up h with Babel.

Basically, if using .babelrc use the following:

{
  "plugins": [
    ["transform-react-jsx", {
      "pragma": "h" // default pragma is React.createElement
    }]
  ]
}

For individual files, use /** @jsx dom */

After configuring your transpiler of choice, you can then just use jsx to create h functions.

Life cycle

Since spark.js is just a helper library for Web Components, all the standard Web Component events happen automatically.

For each of the below life cycles, you must call super() when providing your own functionality. This ensures that spark.js functionality get called whenever you provide your own functions.

CallbackDescription
connectedCallback()Called every time the element is inserted into the DOM. Useful for running setup code, such as fetching resources or rendering. Generally, you should try to delay work until this time.
disconnectedCallback()Called every time the element is removed from the DOM. Useful for running clean up code (removing event listeners, etc.).
attributeChangedCallback(attrName, oldVal, newVal)An attribute was added, removed, updated, or replaced. Also called for initial values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes property will receive this callback.
adoptedCallback()The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).