0.1.0 • Published 6 years ago

@framejs/component v0.1.0

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

Frame Component

An ultra light typescript library for writing custom elements.

Ultra light

Less than 1.5kb (gzipped) when using all decorators in a custom element.

Simple, yet powerful

This framework utilizes only typescript, and has no dependency on any CLI or specific build tooling.

A library, not a framework

This library aims to ease the developer experience when writing custom elements, and to fit in to any build system.

Installing

Install from NPM:

npm install @framejs/component

Decorators

@Component({tag: string, style?: string})

The main decorator that holds state provides a renderer (this is needed in order to use the rest of the decorators).

To manually run the renderer use: this._invalidate();

To auto-render on @Attr and @Prop changes set this._renderOnPropertyChange = true. This should only be done with a smart renderer function. it's enabled by default when extending LitElement.

import { Component } from '@framejs/component';

@Component({
    tag: 'my-element',
    style: ':host { color: blue; }'
})
class MyElement extends HTMLElement {
    render() {
        return `Hello World!`;
    }
}

@Attr() property: string | boolean | number

Decorates the element with an attribute setter and getter and updates state/render on change. Updating the property from within the element or externally will update the attribute in the rendered HTML and the other way around.

Providing a default value will set the attribute when the element is ready. If the attribute is already set by the user, the default will be overwritten.

import { Component, Attr } from '@framejs/component';

@Component({
    tag: 'my-element'
})
class MyElement extends HTMLElement {
    @Attr() target: string = 'World!'

    render() {
        return `Hello ${this.target}`;
    }
}

@Prop() property: any

Decorates the element with a property setter and getter and updates state/render on change. This value will not be reflected in the rendered HTML as an attribute.

import { Component, Prop } from '@framejs/component';

@Component({
    tag: 'my-element'
})
class MyElement extends HTMLElement {
    @Prop() data: string[] = ['Hello', 'world!'];

    render() {
        return `
            ${data.map(word => {
                return word;
            }).join(' ')}
        `;
    }
}

@Watch(property: string) Function(oldValue: any, newValue: any)

The function provided will get triggered when the property changes with the old and new value.

import { Component, Prop } from '@framejs/component';

@Component({
    tag: 'my-element'
})
class MyElement extends HTMLElement {
    @Prop() data: string[] = ['Hello', 'world!'];

    @Watch('data')
    dataChangedHandler(oldValue, newValue) {
        // Do something with the new data entry
    }

    render() {
        return `
            ${data.map(word => {
                return word;
            }).join(' ')}
        `;
    }
}

@Event() property: EventEmitter

Creates a simple event emitter.

import { Component, Emit, EventEmitter } from '@framejs/component';

@Component({
    tag: 'my-element'
})
class MyElement extends HTMLElement {
    @Emit() isReady: EventEmitter;

    connectedCallback() {
        this.isReady.emit('my-element is ready!')
    }
}

@Listen(event: string, target?: window | document) Function

Listens for events and executes the nested logic.

import { Component, Listen } from '@framejs/component';

@Component({
    tag: 'my-element'
})
class MyElement extends HTMLElement {
    @Listen('click')
    clickedOnInstanceHandler(event) {
        console.log(event)
    }

    @Listen('resize', window)
    windowResizeHandler(event) {
        console.log(event)
    }
}

It's also possible to listen for events from child elements

import { Component, Listen } from '@framejs/component';
import './my-other-element';

@Component({
    tag: 'my-element'
})
class MyElement extends HTMLElement {
    @Listen('onOtherElementClicked')
    onOtherElementClickedHandler(event) {
        console.log(event)
    }

    render() {
        return `
            // my-other-element emits an customEvent called 'onOtherElementClicked'.
            <my-other-element></my-other-element>
        `;
    }
}

Using lit-html element

lit-html is a great templating extension when working with complex components. Read more about lit-html.

Extend LitElement instead of HTMLElement to get all it offers.

It's important to use html string literal function as it converts the literal to lit-html.

import { Component, LitElement, html } from '@framejs/component';

@Component({
    tag: 'my-element'
})
class MyElement extends LitElement {
    render() {
        return html`I\m so lit!`;
    }
}

Extendable renderer

The built in renderer is very simple: it receives the returned value, and replaces innerHTML with the new template when updated.

This example shows how LitElement is written.

import { render } from 'lit-html/lib/lit-extended';

export class LitElement extends HTMLElement {
    // Set _renderOnPropertyChange if the renderer
    // should render on every property change.
    public _renderOnPropertyChange = true;

    renderer(template) {
        render(template(), this.shadowRoot);
    }
}

Inside your element you can use it like this:

import { Component, Prop } from '@framejs/component';
import { html } from 'lit-html/lib/lit-exteded';

@Component({
    tag: 'my-element'
})
class MyElement extends LitElement {
    @Prop() message: string = 'it\'s lit!';

    render() {
        return html`${this.message}`;
    }
}
0.1.0

6 years ago

0.0.5

6 years ago

0.0.4

6 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago