import { BasicFun } from "../fun/state"; import { BasicUpdater } from "../fun/domains/updater/state"; import { Unit, unit } from "../../main"; export type View = ( props: HeadlessTemplateProps & embeddedChildren, ) => JSX.Element; export type HeadlessTemplateProps = { context: context; setState: BasicFun, void>; foreignMutations: foreignMutations; }; export type TemplateChildren = JSX.Element | JSX.Element[]; export type Wrapper = BasicFun<{ children?: TemplateChildren }, JSX.Element>; export type TemplateProps = { context: context; setState: BasicFun, void>; foreignMutations: foreignMutations; view: view; children?: TemplateChildren; }; type TemplateRunner = ( props: TemplateProps, ) => JSX.Element; export type Template = { any: BasicFun< Array>, Template >; wrap: (Wrapper: Wrapper) => Template; withView: (view: view) => Template; withViewFromProps: ( f: BasicFun, view>, ) => Template; mapState: ( f: BasicFun, BasicUpdater>, ) => Template; mapStateFromProps: ( f: BasicFun< [ TemplateProps, BasicUpdater, ], BasicUpdater >, ) => Template; mapContext: ( f: BasicFun, ) => Template; mapForeignMutations: ( f: BasicFun, ) => Template; mapContextFromProps: ( f: BasicFun< TemplateProps, context | undefined >, ) => Template; mapForeignMutationsFromProps: ( f: BasicFun< TemplateProps, foreignMutations >, ) => Template; mapView: ( f: BasicFun, ) => Template; mapViewFromProps: ( f: BasicFun, view>, ) => Template; } & TemplateRunner; export const createTemplate = ( actual: TemplateRunner, ): Template => { const result = actual as Template; result.wrap = function ( this: Template, Wrapper: Wrapper, ) { return Template.Operations.Wrap(this, Wrapper); }; result.withView = function ( this: Template, view: view, ): Template { return Template.Operations.WithView(this, view); }; result.withViewFromProps = function ( this: Template, f: BasicFun, view>, ): Template { return Template.Operations.WithViewFromProps(this, f); }; result.mapState = function ( this: Template, f: BasicFun, BasicUpdater>, ): Template { return Template.Operations.MapState(this, f); }; result.mapStateFromProps = function ( this: Template, f: BasicFun< [ TemplateProps, BasicUpdater, ], BasicUpdater >, ): Template { return Template.Operations.MapStateFromProps(this, f); }; result.mapContext = function ( this: Template, f: BasicFun, ) { return Template.Operations.MapContext(this, f); }; result.mapForeignMutations = function ( this: Template, f: BasicFun, ): Template { return Template.Operations.MapForeignMutations(this, f); }; result.mapContextFromProps = function ( this: Template, f: BasicFun< TemplateProps, context | undefined >, ) { return Template.Operations.MapContextFromProps(this, f); }; result.mapForeignMutationsFromProps = function ( this: Template, f: BasicFun< TemplateProps, foreignMutations >, ): Template { return Template.Operations.MapForeignMutationsFromProps(this, f); }; result.mapView = function ( this: Template, f: BasicFun, ): Template { return Template.Operations.MapView(this, f); }; result.mapViewFromProps = function ( this: Template, f: BasicFun, view>, ): Template { return Template.Operations.MapViewFromProps(this, f); }; result.any = function ( this: Template, others: Array>, ): Template { return Template.Operations.Any(this, others); }; return result; }; export const Template = { Default: ( actual: TemplateRunner, ): Template => createTemplate(actual), Operations: { Wrap: ( p: Template, Wrapper: BasicFun<{ children?: TemplateChildren }, JSX.Element>, ): Template => createTemplate((props) => {p(props)}), WithView: ( p: Template, view: view, ): Template => createTemplate((props) => ( <> {p({ ...props, view: view, })} )), WithViewFromProps: ( p: Template, f: BasicFun, view>, ): Template => createTemplate((props) => ( <> {p({ ...props, view: f(props), })} )), MapState: ( p: Template, f: BasicFun, BasicUpdater>, ): Template => createTemplate((props) => ( <> {p({ context: props.context, setState: (_) => props.setState(f(_)), foreignMutations: props.foreignMutations, view: props.view, })} )), MapStateFromProps: ( p: Template, f: BasicFun< [ TemplateProps, BasicUpdater, ], BasicUpdater >, ): Template => createTemplate((props) => ( <> {p({ context: props.context, setState: (_) => props.setState(f([props, _])), foreignMutations: props.foreignMutations, view: props.view, })} )), MapContext: ( p: Template, f: BasicFun, ): Template => createTemplate((props) => { const context = f(props.context); if (!context) return <>; return ( <> {p({ context: context, setState: props.setState, foreignMutations: props.foreignMutations, view: props.view, })} ); }), MapForeignMutations: < context, state, foreignMutations, newForeignMutations, view, >( p: Template, f: BasicFun, ): Template => createTemplate((props) => ( <> {p({ context: props.context, setState: props.setState, foreignMutations: f(props.foreignMutations), view: props.view, })} )), MapContextFromProps: ( p: Template, f: BasicFun< TemplateProps, context | undefined >, ): Template => createTemplate((props) => { const context = f(props); if (!context) return <>; return ( <> {p({ context: context, setState: props.setState, foreignMutations: props.foreignMutations, view: props.view, })} ); }), MapForeignMutationsFromProps: < context, state, foreignMutations, newForeignMutations, view, >( p: Template, f: BasicFun< TemplateProps, foreignMutations >, ): Template => createTemplate((props) => ( <> {p({ context: props.context, setState: props.setState, foreignMutations: f(props), view: props.view, })} )), Any: ( p: Template, others: Array>, ): Template => createTemplate((props) => { return ( <> {[ p(props), ...others.map((_) => _({ context: props.context, setState: props.setState, foreignMutations: props.foreignMutations, view: unit, }), ), ]} ); }), MapView: ( p: Template, f: BasicFun, ): Template => createTemplate((props) => { const view = f(props.view); return ( <> {p({ context: props.context, setState: props.setState, foreignMutations: props.foreignMutations, view: view, })} ); }), MapViewFromProps: ( p: Template, f: BasicFun< TemplateProps, view >, ): Template => createTemplate((props) => { const view = f(props); return ( <> {p({ context: props.context, setState: props.setState, foreignMutations: props.foreignMutations, view: view, })} ); }), }, };