import { hsmls2idomPatch } from "../src/hsml-idom"; import { HElements, HElement } from "../src/hsml"; type View = (state: State, dispatch: Dispatch) => HElements; type Dispatch = (action: Actions, data?: any) => void; type Dispatcher = (action: Actions, data: any, state: State, dispatch: Dispatch) => State; function render(element: HTMLElement, view: View, state: State, dispatch: Dispatch): void { (render as any).scheduled || ((render as any).scheduled = null); if (!state) { return; } if (!(render as any).scheduled) { (render as any).scheduled = setTimeout(() => { const hsml = view(state, dispatch); // console.log("render", hsml); hsmls2idomPatch(element, hsml); (render as any).scheduled = null; }, 0); } } const dispatch: Dispatch = (action, data): void => { // console.log("dispatch", action, data); const state = dispatcher(action, data, appState, dispatch); // console.log("state", state); render(appElement!, view, state, dispatch); }; const appState = { title: "Counter", count: 0 }; type State = typeof appState; type Actions = | "inc" | "dec" | "dec_async" | "action" | "xxx"; const view: View = (state, dispatch): HElements => { return [ ["h2", [state.title]], ["p", [ ["em", ["Count"]], ": ", state.count.toString(), " ", button("-", () => dispatch("dec", 1)), button("+", () => dispatch("inc", 2)), " ", button("xxx", () => dispatch("xxx")) ]], ]; } function button(label: string, cb: (e: Event) => void): HElement { return ["button", { click: cb }, [label]]; } const dispatcher: Dispatcher = (action, data, state, dispatch) => { console.log("action:", action, data); switch (action) { case "inc": state.count += data; break; case "dec": state.count -= data; setTimeout(dispatch, 1e3, "dec_async", 1); break; case "dec_async": state.count -= data; break; default: console.warn("unhandled action:", action, data); } return state; } const appElement = document.getElementById("app"); render(appElement!, view, appState, dispatch); dispatch("action", {});