// Copyright (c) 2020 Gonzalo Müller Bravo. import React from 'react' import type { Node, AbstractComponent } from 'react' // Provider Component ///////////////////// export type Id = string | number | symbol | null export interface ProviderProps { id?: Id; children: Node; } export interface StateProviderProps extends ProviderProps { initialState?: (() => STATE) | STATE; } // Reducer Component Definition /////////////////////////////// export interface ReducerProps extends StateProviderProps { /** * Must always be assigned, although can be 'null' or 'undefined'. */ reducer: REDUCER | null | typeof(undefined) } export interface SyncReducer { (prevState: STATE, action: ACTION, ...args: $ReadOnlyArray): STATE } export interface SyncReducerProps extends ReducerProps> {} declare export class SyncReducerProvider extends React.Component> {} export interface AsyncReducer { (prevState: STATE, action: ACTION, ...args: $ReadOnlyArray): Promise } export interface AsyncReducerProps extends ReducerProps> {} declare export class AsyncReducerProvider extends React.Component> {} // Mapper Component Definition ////////////////////////////// export interface MapperProps extends StateProviderProps { /** * Must always be assigned, although can be 'null' or 'undefined'. */ mapper: MAPPER | null | typeof(undefined) } export interface SyncMapper { (action: ACTION, ...args: $ReadOnlyArray): STATE } export interface SyncMapperProps extends MapperProps> {} declare export class SyncMapperProvider extends React.Component> {} export interface AsyncMapper { (action: ACTION, ...args: $ReadOnlyArray): Promise } export interface AsyncMapperProps extends MapperProps> {} declare export class AsyncMapperProvider extends React.Component> {} // Actuator Component Definition //////////////////////////////// export interface ActuatorProps extends ProviderProps { /** * Must always be assigned, although can be 'null' or 'undefined'. */ actuator: ACTUATOR | null | typeof(undefined) } declare class ActuatorProvider extends React.Component> {} // Providers Consumption //////////////////////// export type Sync = RESULT export type Async = Promise export type DispatcherResult = Async | Sync export interface Dispatcher | Sync<> = Sync> { (value: ACTION, ...args: $ReadOnlyArray): DISPATCH } export interface ProviderValueObject { /** * provider id */ +provider: Id } export interface StateProviderValueObject< STATE, ACTION, DISPATCH: Async | Sync = Sync > extends ProviderValueObject { +state: STATE; +dispatch: Dispatcher; } export type ProviderValueTuple< STATE, ACTION, DISPATCH: Async | Sync = Sync > = [STATE, Dispatcher, Id] export type ProviderValue< STATE, ACTION, DISPATCH: Async | Sync = Sync > = StateProviderValueObject & ProviderValueTuple declare export function useReducer | Sync = Sync>( id?: Id ): ProviderValue declare export function useReducerState(id?: Id): STATE declare export function useReducerDispatcher | Sync<> = Sync>( id?: Id ): Dispatcher declare export function useMapper | Sync = Sync>( id?: Id ): ProviderValue declare export function useMapperState(id?: Id): STATE declare export function useMapperDispatcher | Sync<> = Sync>( id?: Id ): Dispatcher declare export function injectReducer( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> declare export function injectReducerState( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> declare export function injectReducerDispatcher( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> declare export function injectMapper( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> declare export function injectMapperState( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> declare export function injectMapperDispatcher( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> // Actuator Consumption /////////////////////// export type ActuatorProviderValue = ACTUATOR & ProviderValueObject declare export function useActuator ( id?: Id ): ActuatorProviderValue // Tagged Provider Component //////////////////////////// export interface TaggedProviderProps { id?: Id; children: Node; } export type TaggedProcessor = [ Id, PROCESSOR, any ] | [ Id, PROCESSOR ] // Tagged Reducer Component Definition ////////////////////////////////////// export interface TaggedReducerProps extends TaggedProviderProps { /** * Must always be assigned, although can be 'null' or 'undefined'. */ reducers: REDUCER[] | null | typeof(undefined) } export type SyncTaggedReducer = TaggedProcessor> export interface SyncTaggedReducerProps extends TaggedReducerProps {} declare export class SyncTaggedReducerProvider extends React.Component {} export type AsyncTaggedReducer = TaggedProcessor> export interface AsyncTaggedReducerProps extends TaggedReducerProps {} declare export class AsyncTaggedReducerProvider extends React.Component {} // Tagged Mapper Component Definition ////////////////////////////////////// export interface TaggedMapperProps extends TaggedProviderProps { /** * Must always be assigned, although can be 'null' or 'undefined'. */ mappers: MAPPER[] | null | typeof(undefined) } export type SyncTaggedMapper = TaggedProcessor> export interface SyncTaggedMapperProps extends TaggedMapperProps {} declare export class SyncTaggedMapperProvider extends React.Component {} export type AsyncTaggedMapper = TaggedProcessor> export interface AsyncTaggedMapperProps extends TaggedMapperProps {} declare export class AsyncTaggedMapperProvider extends React.Component {} // Tagged Actuator Component Definition /////////////////////////////////////// export interface TaggedActuatorProps[] = TaggedProcessor[]> extends ProviderProps { /** * Must always be assigned, although can be 'null' or 'undefined'. */ actuators: ACTUATORS | null | typeof(undefined) } declare export class TaggedActuatorProvider[] = TaggedProcessor[]> extends React.Component> {} // Tagged Consumption ///////////////////// export interface TaggedProviderValueObject< STATE, ACTION, DISPATCH: Async | Sync = Sync > extends StateProviderValueObject { +tag: Id; } export type TaggedProviderValueTuple< STATE, ACTION, DISPATCH: Async | Sync = Sync > = [STATE, Dispatcher, Id, Id] export type TaggedProviderValue< STATE, ACTION, DISPATCH: Async | Sync = Sync > = TaggedProviderValueObject & TaggedProviderValueTuple export interface TaggedProviderGetter< ANY_ID: Id = Id, ANY_STATE = any, ANY_ACTION = any, ANY_DISPATCH: DispatcherResult = Sync > { +get: (tag: ANY_ID) => TaggedProviderValue } declare export function useTaggedAny< ANY_ID: Id = Id, ANY_STATE = any, ANY_ACTION = any, ANY_DISPATCH: DispatcherResult = Sync>( id?: Id ): TaggedProviderGetter declare export function useTaggedReducer | Sync = Sync>( tag: Id, id?: Id ): TaggedProviderValue declare export function useTaggedReducerState(tag: Id, id?: Id): STATE declare export function useTaggedReducerDispatcher | Sync<> = Sync>( tag: Id, id?: Id ): Dispatcher declare export function useTaggedMapper | Sync = Sync>( tag: Id, id?: Id ): TaggedProviderValue declare export function useTaggedMapperState(tag: Id, id?: Id): STATE declare export function useTaggedMapperDispatcher | Sync<> = Sync>( tag: Id, id?: Id ): Dispatcher declare export function injectTaggedAny( ComponentClass: AbstractComponent, injectedPropName: $Keys, id?: Id ): AbstractComponent<$Diff> declare export function injectTaggedReducer( ComponentClass: AbstractComponent, injectedPropName: $Keys, tag: Id, id?: Id ): AbstractComponent<$Diff> declare export function injectTaggedReducerState( ComponentClass: AbstractComponent, injectedPropName: $Keys, tag: Id, id?: Id ): AbstractComponent<$Diff> declare export function injectTaggedReducerDispatcher( ComponentClass: AbstractComponent, injectedPropName: $Keys, tag: Id, id?: Id ): AbstractComponent<$Diff> declare export function injectTaggedMapper( ComponentClass: AbstractComponent, injectedPropName: $Keys, tag: Id, id?: Id ): AbstractComponent<$Diff> declare export function injectTaggedMapperState( ComponentClass: AbstractComponent, injectedPropName: $Keys, tag: Id, id?: Id ): AbstractComponent<$Diff> declare export function injectTaggedMapperDispatcher( ComponentClass: AbstractComponent, injectedPropName: $Keys, tag: Id, id?: Id ): AbstractComponent<$Diff> // Tagged Actuator Consumption /////////////////////// declare export function useTaggedActuator ( tag: Id, id?: Id ): ActuatorProviderValue // Helpers ////////// export interface AnyAsyncDispatcher = Async> { (value: ACTION, ...args: $ReadOnlyArray): DISPATCH } export interface Action { type: TYPE; data?: DATA; }