UNPKG

@benev/slate

Version:
75 lines (63 loc) 1.89 kB
import {ob} from "../../tools/ob.js" import {StateTree} from "../state_tree.js" export namespace ZipAction { export type Blueprint<S> = {[key: string]: Blueprint<S> | Fn<S, any>} export type SetState<S> = (state: S) => void export type Fn<S, P extends any[]> = ( (state: S, setState: (newState: S) => void) => (...params: P) => void ) export type Callable<B extends Blueprint<any>> = { [P in keyof B]: B[P] extends Blueprint<any> ? Callable<B[P]> : B[P] extends Fn<any, any> ? ReturnType<B[P]> : never } export function actualize<S, B extends Blueprint<S>>(tree: StateTree<S>, blueprint: B) { return ob(blueprint).map(value => { if (typeof value === "function") { return (...params: any[]) => { tree.transmute(state => { const setState = (newState: S) => { state = newState } value(state, setState)(...params) return state }) } } else { return (actualize as any)(tree, value) } }) as Callable<B> } export function fn<S>() { return <F extends Fn<S, any[]>>(fn: F) => fn } export function blueprint<S>() { return <B extends Blueprint<S>>(blueprint: B) => blueprint } export type Helpers<S, H> = (state: S, setState: ZipAction.SetState<S>) => H export const prepFn = <S, H>( helpers: Helpers<S, H> ) => <P extends any[]>( fun: (helpers: H) => (...params: P) => void ): ZipAction.Fn<S, P> => ( (state, setState) => (...params) => { fun(helpers(state, setState))(...params) return state } ) export const prepBlueprint = <S, H>( helpers: Helpers<S, H> ) => <B extends Blueprint<S>>( makeBp: (action: <P extends any[]>(f: (helpers: H) => (...params: P) => void) => Fn<S, P>) => B ) => ( makeBp(prepFn<S, H>(helpers)) ) export function prep<S, H>(helpers: Helpers<S, H>) { return { action: prepFn(helpers), blueprint: prepBlueprint(helpers), } } }