UNPKG

react-sweet-state

Version:

Global + local state combining the best of Redux and Context API

332 lines (289 loc) 9.95 kB
// @flow /* eslint-disable no-redeclare */ import type { Node } from 'react'; /** * ST: Full store state * AC: Store actions * SE: Selector output * PR: Component props * CPR: Container props * SAA: Store action API */ type SetState<ST> = (partialState: $Shape<ST>) => void; type GetState<ST> = () => $ReadOnly<ST>; type StoreUnsubscribe = () => void; export type RenderPropComponent<ST, AC> = ( state: ST, actions: $Exact<BoundActions<AC>> ) => Node; export type HookReturnValue<ST, AC> = [ST, $Exact<BoundActions<AC>>]; export type Store<ST, AC> = {| key: string, initialState: ST, actions: AC, containedBy?: ContainerComponent<any>, handlers?: { onInit?: () => (api: StoreActionApi<ST>, containerProps: any) => any, onUpdate?: () => (api: StoreActionApi<ST>, containerProps: any) => any, onDestroy?: () => (api: StoreActionApi<ST>, containerProps: any) => any, onContainerUpdate?: () => ( api: StoreActionApi<ST>, containerProps: any ) => any, }, |}; export type StoreState<ST> = {| getState: GetState<ST>, setState: SetState<ST>, resetState: () => void, notify: () => void, key: string, subscribe: (listener: () => void) => StoreUnsubscribe, mutator: SetState<ST>, |}; type ExtractReturnType = <R>( (api: StoreActionApi<any>, containerProps: any) => R ) => R; export type StoreActionApi<ST> = {| setState: SetState<ST>, getState: GetState<ST>, dispatch: <F>(actionThunk: F) => $Call<ExtractReturnType, F>, |}; export type Action<ST, CPR = void, R = *> = ( api: StoreActionApi<ST>, containerProps: CPR ) => R; // prettier-ignore type BoundAction<F, SAA = *, CPR = *> = & (<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E) => $Call<$Call<F, A, B, C, D, E>, SAA, CPR>) & (<A, B, C, D>(a: A, b: B, c: C, d: D) => $Call<$Call<F, A, B, C, D>, SAA, CPR>) & (<A, B, C>(a: A, b: B, c: C) => $Call<$Call<F, A, B, C>, SAA, CPR>) & (<A, B>(a: A, b: B) => $Call<$Call<F, A, B>, SAA, CPR>) & (<A>(a: A) => $Call<$Call<F, A>, SAA, CPR>) & (() => $Call<$Call<F>, SAA, CPR>); type MapBoundAction = <F>(F) => BoundAction<F>; export type BoundActions<AC> = $ObjMap<AC, MapBoundAction>; export type StoreInstance<ST, AC> = { store: StoreState<ST>, actions: BoundActions<AC>, }; declare export class Registry { stores: Map<string, StoreInstance<any, any>>; initStore: <ST, AC>( store: Store<ST, AC>, key: string ) => StoreInstance<ST, AC>; getStore: <ST, AC>( store: Store<ST, AC>, scopeId?: string ) => StoreInstance<ST, AC>; hasStore: <ST, AC>(store: Store<ST, AC>, scopeId?: string) => boolean; deleteStore: <ST, AC>(store: Store<ST, AC>, scopeId?: string) => void; } declare export var defaultRegistry: Registry; type MiddlewareResult = any; export type Middleware = ( storeState: StoreState<any> ) => (next: (arg: any) => MiddlewareResult) => (arg: any) => MiddlewareResult; declare export var defaults: { batchUpdates: boolean, devtools: boolean | ((storeState: StoreState<any>) => Object), middlewares: Set<Middleware>, mutator: <ST>(currentState: ST, setStateArg: any) => ST, }; declare export function batch(callback: () => any): void; export type ContainerComponent<PR = void> = React$ComponentType<{| scope?: string, isGlobal?: boolean, children: Node, ...PR, |}>; export type SubscriberComponent<ST, AC, PR = void> = React$ComponentType<{| children: RenderPropComponent<ST, AC>, ...PR, |}>; export type HookFunction<ST, AC, PR = void> = ( props?: PR ) => HookReturnValue<ST, AC>; export type HookActionsFunction<AC> = () => $Exact<BoundActions<AC>>; export type HookStateFunction<ST, PR = void> = (props?: PR) => ST; /** * createStore */ declare export function createStore<ST: { ... }, AC, CPR = void>({| initialState: ST, actions: AC, name?: string, containedBy?: ContainerComponent<CPR>, handlers?: { onInit?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any, onUpdate?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any, onDestroy?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any, onContainerUpdate?: () => ( api: StoreActionApi<ST>, containerProps: CPR ) => any, }, |}): Store<ST, AC>; /** * createContainer */ declare export function createContainer<CPR>(config?: {| displayName?: string, |}): ContainerComponent<CPR>; declare export function createContainer<ST, AC, CPR>( store: Store<ST, AC>, options?: {| onInit?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any, onUpdate?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any, onCleanup?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any, displayName?: string, |} ): ContainerComponent<CPR>; /** * createSubscriber */ declare export function createSubscriber<ST, AC>( store: Store<ST, AC>, options?: {| displayName?: string, |} ): SubscriberComponent<ST, AC, {||}>; // Flow does not support null properly to refine override :( // declare export function createSubscriber<ST, AC>( // store: Store<ST, AC>, // options: {| // selector: null, // displayName?: string, // |} // ): SubscriberComponent<undefined, AC, {||}>; declare export function createSubscriber<ST, AC, SE, PR>( store: Store<ST, AC>, options: {| selector: null | ((state: ST, props: PR) => SE), displayName?: string, |} ): SubscriberComponent<SE, AC, PR>; /** * createHook */ declare export function createHook<ST, AC>( store: Store<ST, AC> ): HookFunction<ST, AC, void>; // Flow does not support null properly to refine override :( // declare export function createHook<ST, AC>( // store: Store<ST, AC>, // options: {| // selector: null, // |}, // ): () => HookReturnValue<void, AC>; declare export function createHook<ST, AC, SE, PR>( store: Store<ST, AC>, options: {| selector: null | ((state: ST, props: PR) => SE), |} ): HookFunction<SE, AC, PR>; declare export function createActionsHook<ST, AC>( store: Store<ST, AC> ): HookActionsFunction<AC>; declare export function createStateHook<ST, AC>(store: Store<ST, AC>): () => ST; declare export function createStateHook<ST, AC, SE, PR>( store: Store<ST, AC>, options: {| selector: (state: ST, props: PR) => SE, |} ): HookStateFunction<SE, PR>; /** * createSelector */ declare type InputSelector<-ST, PR, SE> = (state: ST, props: PR) => SE; declare type OutputSelector<-ST, PR, SE> = { (state: ST, props: PR): SE, resultFunc(...args: any[]): SE, dependencies: any[], }; declare export function createSelector<ST, PR, SE, T1>( selector1: InputSelector<ST, PR, T1>, resultFn: (arg1: T1) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1>( selectors: [InputSelector<ST, PR, T1>], resultFn: (arg1: T1) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2>( selector1: InputSelector<ST, PR, T1>, selector2: InputSelector<ST, PR, T2>, resultFn: (arg1: T1, arg2: T2) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2>( selectors: [InputSelector<ST, PR, T1>, InputSelector<ST, PR, T2>], resultFn: (arg1: T1, arg2: T2) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3>( selector1: InputSelector<ST, PR, T1>, selector2: InputSelector<ST, PR, T2>, selector3: InputSelector<ST, PR, T3>, resultFn: (arg1: T1, arg2: T2, arg3: T3) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3>( selectors: [ InputSelector<ST, PR, T1>, InputSelector<ST, PR, T2>, InputSelector<ST, PR, T3> ], resultFn: (arg1: T1, arg2: T2, arg3: T3) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3, T4>( selector1: InputSelector<ST, PR, T1>, selector2: InputSelector<ST, PR, T2>, selector3: InputSelector<ST, PR, T3>, selector4: InputSelector<ST, PR, T4>, resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3, T4>( selectors: [ InputSelector<ST, PR, T1>, InputSelector<ST, PR, T2>, InputSelector<ST, PR, T3>, InputSelector<ST, PR, T4> ], resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5>( selector1: InputSelector<ST, PR, T1>, selector2: InputSelector<ST, PR, T2>, selector3: InputSelector<ST, PR, T3>, selector4: InputSelector<ST, PR, T4>, selector5: InputSelector<ST, PR, T5>, resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5>( selectors: [ InputSelector<ST, PR, T1>, InputSelector<ST, PR, T2>, InputSelector<ST, PR, T3>, InputSelector<ST, PR, T4>, InputSelector<ST, PR, T5> ], resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5, T6>( selector1: InputSelector<ST, PR, T1>, selector2: InputSelector<ST, PR, T2>, selector3: InputSelector<ST, PR, T3>, selector4: InputSelector<ST, PR, T4>, selector5: InputSelector<ST, PR, T5>, selector6: InputSelector<ST, PR, T6>, resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => SE ): OutputSelector<ST, PR, SE>; declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5, T6>( selectors: [ InputSelector<ST, PR, T1>, InputSelector<ST, PR, T2>, InputSelector<ST, PR, T3>, InputSelector<ST, PR, T4>, InputSelector<ST, PR, T5>, InputSelector<ST, PR, T6> ], resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => SE ): OutputSelector<ST, PR, SE>;