Skip to content

Repository files navigation

Pretty simple Web-application framework

License: MIT npm version npm downloads Build Status

Currently this is an experimental Web-framework built on top of snabbdom-ng.

The snabbdom-ng is the modified snabbdom Virtual DOM library.

Overview

Literium is a client-side framework for modern Web-application. Its core principles are explicit state, controllable behavior, declarative code, effeciency, simplicity and flexibility.

Features

  • Browser interaction (Client-side)
  • Dynamic HTML generation (Server-side)
  • Static HTML pre-rendering
  • Preferred to live at top-level (i.e. root <html>-node or document.documentElement)

Architecture

The component is a part of application which lives and can be used independently from it. So the application itself is a root component which lives at top-level.

The state and event is a main objects which application operates with using some set of operations. The state object uniquely determines current state of the component or application. The event objects is used to modify the state of the component or application.

Functions

Emit<Signal>

The emit function allows to send events to component in order to modify its state.

export interface Emit<Signal> {
    (signal: Signal): void;
}

To deal with sub-components you can change the type of Signal using map_emit() function, like so:

import { Emit } from 'literium';

interface SubSignal { }

interface Signal {
  _: SubSignal;
}

const emit: Emit<Signal>;

const sub_emit: Emit<SubSignal> =
  map_emit((sub_signal: SubSignal) => ({ _: sub_signal }))
  (emit);

When the Keyed container is used to wrap signals you can do it much simpler:

import { Keyed, Emit } from 'literium';

interface SubSignal { }

type Signal = Keyed<'sub-signal', SubSignal>;

const emit: Emit<Signal>;

const sub_emit: Emit<SubSignal> = Emit.wrap(emit, 'sub-signal');

Done

The done function allows to notify the host when some asynchronous operation is complete.

export interface Done {
    (): void;
}

Fork<Signal>

The fork function can be used to start some asynchronous operation which may send signals to the component.

export interface Fork<Signal> {
    (): [Emit<Signal>, Done];
}

You may use it like so:

/* start task */
const [emit, done] = fork();

/* emit events */
emit({ $: 'some-signal' });
...
emit({ $: 'other-signal' });

/* end task */
done();

This way simplifies asynchronous code handling both on client and server.

To deal with sub-components you can change the type of Signal using map_fork function, like so:

import { Fork } from 'literium';

interface SubSignal { }

interface Signal { _: SubSignal; }

function wrapSubSignal(sub_signal: SubSignal): Signal {
    return { _: sub_signal };
}

const fork: Fork<Signal>;

const sub_fork: Fork<SubSignal> = map_fork(wrapSubSignal)(fork);

When the Keyed container is used to wrap events you can do it much simpler:

import { Keyed, Fork } from 'literium';

interface SubSignal { }

type Signal = Keyed<'sub-signal', SubSignal>;

const fork: Fork<Signal>;

const sub_fork: Fork<SubSignal> = wrap_fork(fork, 'sub-signal');

Create<State, Signal>

The function create is purposed to get initial state of the component.

export interface Create<State, Signal> {
    (fork: Fork<Signal>): State;
}

The component can start asynchronous operations on initializing using fork.

Update<State, Signal>

The function update is purposed to change current state of the component.

export interface Update<State, Signal> {
    (state: Readonly<State>, signal: Signal, fork: Fork<Signal>): State;
}

Also the component can start asynchronous operations on updating.

Render<State, Signal>

The function render is used to render the component in current state.

export interface Render<State, Signal> {
    (state: Readonly<State>, emit: Emit<Signal>): VNode;
}

Component<State, Signal>

By default the components have a state so it must implements all three methods.

export interface Component<State, Signal> {
    create: Create<State, Signal>;
    update: Update<State, Signal>;
    render: Render<State, Signal>;
}

Combining

The components may be combined with other components in any reasonable way. Also you have full control on the state and event handling of the nested components in the parent. But you must provide right event routing and state changing for the nested components to have expected behavior.

About

Pretty simple Web-application framework

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages