lit-tea

0.2.0-rc-2 • Public • Published

lit-tea

An implementation of The Elm Architecture in typescript, using lit-html to render the view.

The idea is to make spinning up a frontend app fast, easy, and reliable. It shouldn't be hard to add new functionality to an app, and whenever possible we should get compile time or linting checks when refactoring or adding new features. Elm gives a superb developer experience in this regard to maintenance, but there is at least some of that we can get with Typescript - and so this package is born!

Quick start

You can quickly get going with a yo generator:

# ensure you have yo available, and the lit-tea generator
npm i -g yo generator-lit-tea

# make a dir and invoke the generator
mkdir my-lit-app
cd my-lit-app
yo lit-tea my-lit-app

Then you'll have a fully workable app.

code . # if you have VSCode
npm start

Edit index.html or src/index.ts and parcel will do its magicks.

How to use

Code from examples/simple-counter.ts.

import { html } from 'lit-html';
import { run, Dispatcher } from 'lit-tea';

type Msg = { incr: number }

const INC: Msg = { incr: 1 };
const DEC: Msg = { incr: -1 };

type Model = {
  counter: number
}

type MsgHandler = (d: Dispatcher<Msg>) => void;

const increment: MsgHandler = dispatch => dispatch(INC);
const decrement: MsgHandler = dispatch => dispatch(DEC);

run<Model, Msg>({
  init: { counter: 0 },
  update: (model, msg) => ({
    ...model,
    counter: model.counter + msg.incr
  }),
  view: (model, dispatch) =>
    html`
      <h2>${model.counter}</h2>
      <div>
        <button @click=${increment(dispatch)}>+1</button>
        <button @click=${decrement(dispatch)}>-1</button>
      </div>
    `
});

ADT Message Type

Typescript has two compiler flags, noFallthroughCasesInSwitch and strictNullChecks, which enable exhaustive switch statements. Together with unions, we can get very close to Elm's way of defining messages and update functions.

Code from examples/adt.ts (TODO - use remote data fetching example).

import { html } from 'lit-html';
import { run, View, Update } from '../src'


// MODEL - application state
type Model = {
  saying: string,
  itrs: number
}

const init: Model = {
  saying: 'hello',
  itrs: 50
};


// MESSAGES - application transitions
type NewSaying = {
  tag: 'NewSaying',
  value: string
}

const mkNewSaying = (newSaying: string): NewSaying => ({
  tag: 'NewSaying',
  value: newSaying
});

type Noop = {
  tag: 'Noop'
}

type Msg =
  NewSaying
  | Noop


// UPDATE - transform the model with the incoming message
const update: Update<Model, Msg> = (model, msg) => {
  switch (msg.tag) {
    case "NewSaying":
      return { ...model, saying: msg.value};
    case "Noop":
      return model;
  }
}


// VIEW - dat sweet html
const view: View<Model, Msg> = (model, dispatcher) => {

  const nextSaying = model.saying === 'hello' ? 'ahoy' : 'hello';

  const onBtnClick = () =>
    dispatcher(mkNewSaying(nextSaying));

  return html`
    <section>
      <p>Well, it is ${model.saying}</p>
      <button @click=${onBtnClick}>Change it</button>
    </section>
  `;
}


// APP - tyingit all together
run({ init, update, view });

Publishing

This project is built with Typescript, and is configured to compile to the /dist folder. We copy the package.json into the dist folder and publish from there.

Dependents (0)

Package Sidebar

Install

npm i lit-tea

Weekly Downloads

0

Version

0.2.0-rc-2

License

ISC

Unpacked Size

12.4 kB

Total Files

12

Last publish

Collaborators

  • snewell