UNPKG

@expressive/react

Version:
106 lines (100 loc) 4.35 kB
import { Context } from '@expressive/mvc'; import React__default, { FunctionComponent } from 'react'; declare module '@expressive/mvc' { namespace Model { interface Component<T extends Model, P extends Model.Assign<T>> extends FunctionComponent<P & Model.Props<T>> { displayName?: string; Model: Model.Type<T>; } function as<T extends Model, P extends Model.Assign<T>>(this: Model.Init<T>, render: (props: P, self: T) => React__default.ReactNode): Component<T, P>; } } declare module '@expressive/mvc' { namespace Model { function use<T extends Model>(this: Model.Init<T>, apply?: Model.Assign<T>, repeat?: boolean): T; function use<T extends Model>(this: Model.Init<T>, callback?: Model.Callback<T>, repeat?: boolean): T; } } /** Type may not be undefined - instead will be null. */ type NoVoid<T> = T extends undefined | void ? null : T; type ForceRefresh = { /** Request a refresh for current component. */ (): void; /** * Request a refresh and again after promise either resolves or rejects. * * @param waitFor Promise to wait for. * @returns Promise which resolves, after refresh, to same value as `waitFor`. */ <T = void>(waitFor: Promise<T>): Promise<T>; /** * Request refresh before and after async function. * A refresh will occur both before and after the given function. * * **Note:** Any actions performed before first `await` will occur prior to refresh. * * @param invoke Async function to invoke. * @returns Promise which resolves returned value after refresh. */ <T = void>(invoke: () => Promise<T>): Promise<T>; }; declare module '@expressive/mvc' { namespace Model { type GetFactory<T extends Model, R> = (this: T, current: T, refresh: ForceRefresh) => R; type GetEffect<T extends Model> = (this: T, current: T, refresh: ForceRefresh) => null; /** Fetch instance of this class from context. */ function get<T extends Model>(this: Model.Type<T>): T; /** Fetch instance of this class optionally. */ function get<T extends Model>(this: Model.Type<T>, required: false): T | undefined; /** Fetch instance of this class from context. */ function get<T extends Model>(this: Model.Type<T>, requireValues: true): Required<T>; function get<T extends Model, R>(this: Model.Type<T>, factory: GetFactory<T, Promise<R> | R>): NoVoid<R>; function get<T extends Model>(this: Model.Type<T>, factory: GetEffect<T>): null; } } declare module '@expressive/mvc' { namespace Model { type HasProps<T extends Model> = { [K in Exclude<keyof T, keyof Model>]?: T[K]; }; /** * Props which will not conflict with a Model's use as a Component. * * Built-in properties must be optional, as they will always be omitted. */ type RenderProps<T extends Model> = HasProps<T> & { is?: undefined; get?: undefined; set?: undefined; }; /** Model which is not incompatable as Component in React. */ interface Compat extends Model { render?(props: RenderProps<this>, self: this): React.ReactNode; fallback?: React.ReactNode; } interface BaseProps<T extends Model> { /** * Callback for newly created instance. Only called once. * @returns Callback to run when instance is destroyed. */ is?: (instance: T) => void; render?(props: HasProps<T>, self: T): React.ReactNode; /** * A fallback react tree to show when suspended. * If not provided, `fallback` property of the Model will be used. */ fallback?: React.ReactNode; } type Props<T extends Model> = T extends { render(props: infer P, self: any): any; } ? BaseProps<T> & HasProps<T> & Omit<P, keyof Model> : BaseProps<T> & HasProps<T> & { children?: React.ReactNode; }; } } declare const Pragma: { useContext(): Context; useFactory<T extends Function>(factory: (refresh: () => void) => T): T; useLifecycle(callback: () => () => void): void; }; export { Pragma };