@expressive/react
Version:
Use classes to define state in React!
122 lines (121 loc) • 5.62 kB
TypeScript
import { Context, State } from "@expressive/state";
import { ReactNode } from "react";
//#region src/state.d.ts
declare const Pragma: {
useState<S>(initial: () => S): [S, (next: (previous: S) => S) => void];
useEffect(effect: () => () => void, deps?: any[]): void;
createElement(type: any, props?: any, ...children: any[]): any;
};
/** 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>;
};
type GetFactory<T extends State, R> = (this: T, current: T, refresh: ForceRefresh) => R;
type GetEffect<T extends State> = (this: T, current: T, refresh: ForceRefresh) => null;
type UseArgs<T extends State> = T extends {
use(...props: infer P): any;
} ? P : State.Args<T>;
type Props<T extends State> = { [K in Exclude<keyof T, keyof Component>]?: T[K] };
type Render<T extends State, P extends object> = ((props: P & Props<T>, self: T) => ReactNode) & PropsValid<P, T>;
type Overlap<P extends object, V extends object> = Extract<keyof P, keyof V>;
type PropsConflicting<P extends object, V extends object> = { [K in Overlap<P, V>]: [P[K]] extends [V[K]] ? never : K }[Overlap<P, V>];
type PropsValid<P extends object, T extends State> = [PropsConflicting<P, Props<T>>] extends [never] ? unknown : never;
type ComponentProps<T extends State> = Readonly<Props<T> & {
/**
* Callback for newly created instance. Only called once.
* @returns Callback to run when instance is destroyed.
*/
is?: (instance: T) => void;
/**
* A fallback react tree to show when suspended.
* If not provided, `fallback` property of the State will be used.
*/
fallback?: React.ReactNode;
/**
* Children to render within component. Will be passed as `children` prop.
*/
children?: React.ReactNode;
}>;
interface Component<P = {}> extends ReactState {
readonly props: ComponentProps<this> & P;
context: Context;
state: State.Values<this>;
fallback?: ReactNode;
render(): ReactNode;
/** @deprecated Only for React JSX compatibility in typescript and nonfunctional. */
setState: (state: any, callback?: () => void) => void;
/** @deprecated Only for React JSX compatibility in typescript and nonfunctional. */
forceUpdate: (callback?: () => void) => void;
}
type ComponentType<T, P = {}> = State.Type<T & Component<P>>;
declare namespace ReactState {
export import Extends = State.Extends;
export import Type = State.Type;
export import Args = State.Args;
export import Init = State.Init;
export import Assign = State.Assign;
export import Field = State.Field;
export import Event = State.Event;
export import Export = State.Export;
export import Value = State.Value;
export import Setter = State.Setter;
export import OnEvent = State.OnEvent;
export import OnUpdate = State.OnUpdate;
export import Values = State.Values;
export import Partial = State.Partial;
export import Ref = State.Ref;
export import Effect = State.Effect;
export import EffectCallback = State.EffectCallback;
export { GetFactory, GetEffect, UseArgs, Props, Component };
}
declare abstract class ReactState extends State {
/**
* Optional hook is called when State.use() is invoked within a React component.
*
* This is called *every render* of the component, and will intercept
* arguments which would otherwise be merged into the State.
*
* @param props Arguments passed to State.use().
*/
protected use?(...props: any[]): Promise<void> | void;
/**
* Create and manage instance of this State within React component.
*
* @param args Arguments to pass to constructor or `use` method (if defined).
* @returns Managed instance of this State.
*/
static use<T extends ReactState>(this: State.Type<T>, ...args: UseArgs<T>): T;
/** Fetch instance of this class from context. */
static get<T extends State>(this: State.Extends<T>): T;
/** Fetch instance of this class optionally. */
static get<T extends State>(this: State.Extends<T>, required: false): T | undefined;
/** Fetch instance of this class from context. */
static get<T extends State>(this: State.Extends<T>, requireValues: true): Required<T>;
static get<T extends State, R>(this: State.Extends<T>, factory: GetFactory<T, Promise<R> | R>): NoVoid<R>;
static get<T extends State>(this: State.Extends<T>, factory: GetEffect<T>): null;
static as<T extends State, P extends object = {}>(this: State.Type<T>, render: Render<T, P>): ComponentType<T, P>;
static as<T extends State, P extends object = {}>(this: ComponentType<T, P>, withProps: Props<T>): ComponentType<T, P>;
static as<T extends State>(this: State.Type<T>, withProps: Props<T>): ComponentType<T, {}>;
}
declare function Render<T extends Component, P extends State.Assign<T>>(this: T, render: (props: P, self: T) => ReactNode): ReactNode;
//#endregion
export { Pragma, ReactState };
//# sourceMappingURL=state.d.ts.map