An opinionated library for building web applications with typescript.
npm install -s Geordi7/ts-waf#main
See example.ts
for a detailed example
- As strictly typed as is reasonable
- Functional Style with no
class
es - A component is defined w.r.t. a State type and a view that renders it
- Only State Transitions can change the state
- Whenever the state changes the view is updated
Two function types represent state transitions: StateEventTransition<State>
if it will attached to a DOM event, and StateTransition<State>
otherwise.
StateTransition<State>
and StateEventTransition<State>
have the same return type:
type StateTransition<State> = (s: State) =>
| null
| State
| Promise<StateTransition<State>>
| {now: State, later: Promise<StateTransition<State>>}
These four return types have specific meanings and are treated in different ways:
null
means no state changeState
means update the state of the application now (and rerender it)Promise<StateTransition<State>>
means that at some future point a state transition will be ready. When this promise resolves send the state transition function the state at that time so that it can make its changes.{now: State, later: Promise<StateTransition<State>>}
is a combination of the previous two: update the application state withnow
and uselater
to update the application state when it resolves.
Create model.ts
, define your State
type and the relevant parameterized types:
import * as waf from 'ts-waf';
export type State = {...};
export const init: () => State = () => ({...})
export type View = waf.View<State>;
export type Content = waf.Content<State>;
export type StateTransition = waf.StateTransition<State>;
export type StateEventTransition = waf.StateEventTransition<State>;
export const tag = waf.getTagFactory<State>();
export const tools = waf.getTools<State>();
Create main.ts
, define your main view and mount it:
import {init, tag, State, View} from './model';
import {mount} from 'ts-waf';
const {div} = tag;
const view: View<State> = (s) => div({}, 'Hello World');
const stateManager = mount(document.getElementById('root'), view, init());
When you create subviews, use the Content type
export const loginWidget = (s: State): Content => ...