import { VNode } from 'dom-renderer'; import { observable, reaction } from 'mobx'; import { AFC, FC, FunctionComponent, observer, WebCellComponent } from './decorator'; import { ClassComponent, component, WebCell, WebCellProps } from './WebCell'; export type ComponentTag = string | WebCellComponent; export interface FunctionCellProps extends WebCellProps { component: FC | AFC; } export interface FunctionCell extends WebCell {} @component({ tagName: 'function-cell' }) @observer export class FunctionCell extends HTMLElement implements WebCell { @observable accessor component: FunctionCellProps['component']; @observable accessor vNode: VNode | undefined; disconnectedCallback = reaction( () => this.component, () => (this.vNode = undefined) ); render() { const result = this.vNode || this.component({}); if (!(result instanceof Promise)) return result; result.then(vNode => (this.vNode = vNode)); } } type GetAsyncProps = T extends () => Promise<{ default: FunctionComponent | ClassComponent; }> ? P : {}; export const lazy = Promise<{ default: FunctionComponent | ClassComponent }>>(loader: T) => (props: GetAsyncProps) => ( { const { default: Tag } = await loader(); return ; }} /> );