tsui
TypeScript icon, indicating that this package has built-in type declarations

0.0.1 • Public • Published

TSui

TypeScript user interface.

Installation

You should install it both globally (for command line usage) and locally.

npm i --save tsui && npm i -g tsui

Notice: The global installation will just act as an interface to listen to your command line inputs, while the local installation is the one responsible for compiling and providing dependencies. This way you can depend on a specific version of this framework regardless of the globally installed version.

Usage

This is not just a front end framework, I actually created as a solution for all the mess that I have to deal with while writing my application's front end. So a module bundler (rollup) and a transpiler (babel) is included.

Starting by writing your components, typically each component should be a class in a file with a render method that returns a JSX object.

// file: component.tsx
 
import {Component} from 'tsui';
 
// the class should extend
// the Component class in the framework
export default class extends Component {
    render(state) {
        return (<p>My name is {state.name}</p>);
    }
}

Then you application file import this class, create a new instance of it with an initial state and mount it to an element:

// file app.ts
import Component from "./component.tsx";
 
// instantiate
const component = Component({
    // initial state
    name:"Bond, James Bond"
});
// mount it
component.mount("element-id");
 
// then you can update the state like this:
 
component.update({
    // new state
    name:"Alex"
});
 
// HTML view will update automatically

Then you can compile your typescript code and component into a transpiled single file JavaScript using the tsui command

tsui app.ts

And you'll get a file (app.js) will be generated that is consumable by the browser.

Component API

When instantiating a component the following methods and properties will be available to you:

Get the component state

The component state is the state property of the initialized component:

import Component from "./component.tsx";
const component = Component({name:"Alex"});
component.mount("element-id");
console.log(component.state.name);
// > "Alex"
 
// Important:
// setting the name to "Dan" like the following:
component.state.name = "Dan";
// will not be reflected to the DOM unless you call the update method
component.update({});
// thus it's always better to just call the update
// method with any state change you'd like
// (below)
 

Update the component state

component.mount("element-id");
component.update({name:"Dan"});

Note an update must be carried out only after mounting the component to a parent element.

Mount and Destroy

The mount method must be given an element ID.

component.mount("element-id");

otherwise it will complain that it didn't find the element specified with the given ID.

Destroy component

Basically it will remove the component root element

component.destroy();

Observe state change

You can set a callback for a specific state changes in the component

component.observe("name",(oldVal,newVal) => {
    console.log(oldVal,newVal);
});

Cancel observance

When observing a state change a unique identifier will be given to that observer, you can pass this unique identifier to the cancel method and your callback method will not by called anymore.

const observer1 = component.observe("name",(oldVal,newVal) => {
    console.log(oldVal,newVal);
});
 
component.update({name:"Alex"});
// callback will be called
 
component.cancel(observer1);
 
component.update({name:"James Bond"});
// callback will NOT be called
 

Life Cycle Events in the Components

There are 4 life cycle events for your component:

  • onInit: Your component has been constructed
  • onMount: Your component has been mounted to the DOM
  • onUpdate: Your component state has been updated
  • onDestroy: Your component has been destroyed/demounted from the DOM.

You can use those life cycle event in your component:

// file: component.tsx
 
import {Component} from 'tsui';
 
// the class should extend
// the Component class in the framework
export default class extends Component {
    render(state) {
        return (/*what ever*/);
    }
    onInit(state){
        console.log(state);
    }
    onMount($parent,state){
        console.log($parent,state)
    }
    onDestroy($parent,state){
        console.log($parent,state)
    }
    onUpdate(newState,oldState){
        console.log(newState,oldState)
    }
}

DOM events

All vanilla javascript DOM events are supported like onclick, onchange, onDblClick ... etc But you have to capitalize the first letter.

// file: component.tsx
 
import {Component} from 'tsui';
export default class extends Component {
    render(state) {
        return (<button OnClick={handlers.click}>Click me, {state.name}</button>);
    }
}
 
const handlers = {
    click:function(){
        // the context of event function is the DOM element
        // so inside this function `this` refers to the DOM element
        // just like vanilla javascript
        console.log(this); // logs the DOM element in question
        // However, all dom elements that has been created
        // in this component has a `component` attribute that refers to
        // this instance of the component
        // so you can do the following:
        this.component.update({name:"Alex"});
    }
}

Custom events

A custom event can by anything, called anything, passed anything, triggered anywhere, and being listened to anywhere.

 
// In your application
 
import Component from "./component.tsx";
const component = Component({name:"Alex"});
component.mount("element-id");
 
// Once you started listening to a custom event
// you've practically created one:
 
// listen to: "myEvent":
component.on("myEvent",function(a,b,c){
    console.log(a,b,c);
});
 
// trigger my event
component.trigger("myEvent",1,2,3);
// first argument: event name
// all other argument are callback arguments
 
// Multiple listeners can be set to a single custom event:
 
component.on("myEvent",function(a,b,c){
    console.log(a*b*c) // 6
});
 
// file: component.tsx
 
import {Component} from 'tsui';
 
export default class extends Component {
    render(state) {
        return (<button OnClick={this.trigger("myEvent","hello","world")}>Click me, {state.name}</button>);
    }
    // register a listener from inside the component
    onMyEvent:function(a,b){
        console.log(a+" "+b) // hello world
    }
}

Surely, a custom event can get listened to in your app.ts and triggered inside your component.

Child components

A child component can be used in the render method and it's props will be considered as it's state:

// file: child.tsx
 
import {Component} from 'tsui';
 
export default class extends Component {
    render(state) {
        return (<span>name: {state.name}, age: {state.age}</span>);
    }
}
// file: component.tsx
 
import {Component} from 'tsui';
import Child from "./child";
 
export default class extends Component {
    render(state) {
        return (
            <div>
                <Child name="alex" age={state.age}/>
            </div>
        );
    }
}

Type definitions for your state

To get the full out of typescript definitions you can define your components constructor function and update method with a parameter and an interface, but remember to call the super methods.

import {Component} from 'tsui';
 
interface State {
    name:string,
    age:number
}
 
export default class extends Component {
 
 
    constructor(state:State){
        super(state);
    }
 
    update(state:State){
        super.update(state)
    }
 
 
    render(state) {
        return (/*anything*/);
    }
}

Examples

Package Sidebar

Install

npm i tsui

Weekly Downloads

3

Version

0.0.1

License

MIT

Last publish

Collaborators

  • alexcorvi