atomic-state
Version:
Atomic State is a state management library for React
307 lines (306 loc) • 11.1 kB
TypeScript
/** @license Atomic State
* Copyright (c) Dany Beltran
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the roo&t directory of this source tree.
*/
import { Dispatch, SetStateAction } from 'react';
type Observable = {
addListener(event: string, listener?: any): void;
removeListener(event: string, listener?: any): void;
emit(event: string, payload?: any): void;
};
export type ActionType<Args, T = any, Return = any> = T extends undefined ? (args: {
args?: Args;
state: T;
dispatch: Dispatch<SetStateAction<T>>;
} & ActionGet) => Return : (args: {
args: Args;
state: T;
dispatch: Dispatch<SetStateAction<T>>;
} & ActionGet) => Return;
/**
* Atom type
*/
export type Atom<T = any, ActionArgs = any> = {
/**
* @deprecated Use `key` instead
*/
name?: string;
key: string;
default?: T | Promise<T> | (() => Promise<T>) | (() => T);
/**
* Short for `localStoragePersistence`
*/
persist?: boolean;
/**
* The persistence provider (optional). It should have the `getItem`, `setItem` and `removeItem` methods.
*
* @default localStorage
*/
persistenceProvider?: PersistenceStoreType;
/**
* If true, `persist` will keep the value in sync between tabs.
* By default it's `true`
*/
sync?: boolean;
/**
* If `persist` is true, this will run whenever the state is updated from another tab. This will not run in the tab that updated the state.
*/
onSync?(message: T): void;
actions?: {
[E in keyof Partial<ActionArgs>]: ActionType<ActionArgs[E], T>;
};
effects?: ((s: {
previous: T;
state: T;
dispatch: Dispatch<SetStateAction<T>>;
/**
* Cancel the new state update
*/
cancel: () => void;
}) => void)[];
};
export type ActionsObjectType<ArgsTypes = any> = {
[E in keyof ArgsTypes]: <Returns = any>(args?: ArgsTypes[E]) => Returns;
};
export type useAtomType<R, ActionsArgs = any> = () => (R | Dispatch<SetStateAction<R>> | ActionsObjectType<ActionsArgs>)[];
/**
* Type for the `get` function of filters
*/
export type SelectorGet = {
get<R>(atom: useAtomType<R> | Atom<R, any>): R;
};
/**
* Type for the `get` function of filters
*/
export type ActionGet = {
get<R>(atom: useAtomType<R> | Atom<R, any>, storeName?: string | boolean): R;
};
/**
* Filter type
*/
export type Selector<T = any> = {
/**
* @deprecated Use `key` instead
*/
name?: string;
key: string;
default?: T;
get(c: SelectorGet): T | Promise<T>;
};
export declare function createObserver(): {
observer: Observable;
notify: (storeName: string, hookCall: string, payload: any) => void;
};
type PersistenceGet = (key: string) => any;
type PersistenceSet = (key: string, value: any) => void;
type PersistenceRemove = (key: string) => void;
export type PersistenceStoreType = {
get?: PersistenceGet;
getItem?: PersistenceGet;
getItemAsync?: PersistenceGet;
set?: PersistenceSet;
setItem?: PersistenceSet;
setItemAsync?: PersistenceSet;
remove?: PersistenceRemove;
removeItem?: PersistenceRemove;
removeItemAsync?: PersistenceRemove;
delete?: PersistenceRemove;
deleteItem?: PersistenceRemove;
deleteItemAsync?: PersistenceRemove;
};
export declare function createPersistence(_persistenceProvider?: PersistenceStoreType): {
setItem: any;
getItem: any;
removeItem: any;
};
export declare const AtomicState: React.FC<{
clientOnly?: boolean;
children: any;
/**
* Set default values using an atom's key
*/
default?: {
[key: string]: any;
};
value?: {
[key: string]: any;
};
/**
* The store name where atoms under the tree will be saved
*/
storeName?: string | boolean;
/**
* The persistence provider (optional). It should have the `getItem`, `setItem` and `removeItem` methods.
*
* @default localStorage
*/
persistenceProvider?: PersistenceStoreType;
}>;
/**
* Take a snapshot of all atoms' and filters' values.
* You can pass a string with the `prefix` you used in the `AtomicState` root component
* if you want only atoms and filters using that prefix.
*/
export declare function takeSnapshot(storeName?: string): any;
export declare function setAtom<R = any>($atom: Atom<R>, v: SetStateAction<R>, prefix?: string): void;
export declare function getActions<R = any, A = any>($atom: Atom<R, A>): Required<ActionsObjectType<A>>;
/**
* Creates an atom containing state
*/
export declare function atom<R, ActionsArgs = any>($init: Omit<Atom<R, ActionsArgs>, 'name'> | Omit<Selector<R>, 'name'>): Atom<R, ActionsArgs> | Selector<R>;
export declare const createAtom: typeof atom;
export declare function filter<R>(init: Selector<R | Promise<R>>): Selector<R>;
export declare const selector: typeof filter;
export declare function useFilter<T>(f: (() => T | Promise<T>) | Selector<T | Promise<T>>): T;
/**
* Get an atom's value and state setter
*/
export declare function useAtom<R, ActionsArgs = any>(atom: Atom<R, ActionsArgs>): [R, React.Dispatch<SetStateAction<R>>, ActionsObjectType<ActionsArgs>];
/**
* Creates a store with the `setPartialvalue`, `setValue` and `reset` methods.
* It returns a hook that returns an array with the value and the actions
*/
export declare function createAtomicHook<R, Actions = {
[k: string]: any;
}>(config?: Partial<Atom<R, Actions>>): {
(): readonly [R, ActionsObjectType<{
setPartialvalue: Partial<R> | ((v: Required<R>) => Partial<R>);
setPartial: Partial<R> | ((v: Required<R>) => Partial<R>);
setValue: R | ((v: Required<R>) => R);
reset: any;
} & Actions>];
atom: Atom<R, {
setPartialvalue: Partial<R> | ((v: Required<R>) => Partial<R>);
setPartial: Partial<R> | ((v: Required<R>) => Partial<R>);
setValue: R | ((v: Required<R>) => R);
reset: any;
} & Actions> | Selector<R>;
};
/**
* Creates a store with the `setPartialvalue`, `setValue` and `reset` methods.
* It uses `createAtomicHook` under the hood but instead of returing an array, it returns an object with the store value and actions merged
*/
export declare function createStore<R, Actions = {
[k: string]: any;
}>(config?: Partial<Atom<R, Actions>>): {
(): R & ActionsObjectType<{
setPartialvalue: Partial<R> | ((v: Required<R>) => Partial<R>);
setPartial: Partial<R> | ((v: Required<R>) => Partial<R>);
setValue: R | ((v: Required<R>) => R);
reset: any;
} & Actions>;
atom: Atom<R, {
setPartialvalue: Partial<R> | ((v: Required<R>) => Partial<R>);
setPartial: Partial<R> | ((v: Required<R>) => Partial<R>);
setValue: R | ((v: Required<R>) => R);
reset: any;
} & Actions> | Selector<R>;
};
export declare function create<R, Actions = {
[k: string]: any;
}>(config: Omit<Atom<R, Actions>, 'name'> | Omit<Selector<R>, 'name'>): {
(): [R, Dispatch<SetStateAction<R>>, ActionsObjectType<any>] & {
value: R;
setValue: Dispatch<SetStateAction<R>>;
actions: ActionsObjectType<any>;
};
value(): R;
set(value: R | ((v: R) => R), storeName?: string): void;
actions: Required<ActionsObjectType<Actions>>;
atom: Atom<R | Promise<R> | (() => Promise<R>) | (() => R), Actions> | Selector<R | Promise<R> | (() => Promise<R>) | (() => R)>;
useValue(): R;
setValue: (value: R | ((v: R) => R), storeName?: string) => void;
useAtom(): [R, Dispatch<SetStateAction<R>>, ActionsObjectType<any>];
};
export declare const store: typeof createStore;
export declare const atomicHook: typeof createAtomicHook;
/**
* Get an atom's value
*/
export declare function useValue<R>(atom: useAtomType<R> | Atom<R, any> | Selector<R>): R;
export declare const useAtomValue: typeof useValue;
/**
* Get the function that updates the atom's value
*/
export declare function useDispatch<R>(atom: useAtomType<R> | Atom<R, any>): (cb: ((c: R) => R) | R) => void;
export declare const useAtomDispatch: typeof useDispatch;
/**
* Get the actions of the atom as reducers
*/
export declare function useActions<R, ActionsArgs = any>(atom: useAtomType<R, ActionsArgs> | Atom<R, ActionsArgs>): Required<ActionsObjectType<ActionsArgs>>;
/**
* Get an atom's value and actions
*/
export declare function useValueAndActions<R, ActionsArgs = any>(atom: useAtomType<R, ActionsArgs> | Atom<R, ActionsArgs>): readonly [R, ActionsObjectType<ActionsArgs>];
export declare const useAtomActions: typeof useActions;
/**
* Create a single provider hook with atoms
*/
export declare function atomProvider<R>(states: {
[e in keyof R]: Atom<R[e]>;
}): {
<E extends keyof R>(name: E): [R[E], Dispatch<SetStateAction<R[E]>>, ActionsObjectType<{
[x: string]: /*elided*/ any;
}>] & {
value: R[E];
dispatch: Dispatch<SetStateAction<R[E]>>;
actions: ActionsObjectType<{
[x: string]: /*elided*/ any;
}>;
};
stores: { [e in keyof R]: Atom<R[e], any>; };
value<E extends keyof R>(name: E): R[E] | Promise<R[E]> | (() => Promise<R[E]>) | (() => R[E]);
dispatch<E extends keyof R>(name: E): (cb: R[E] | ((c: R[E]) => R[E])) => void;
actions<E extends keyof R>(name: E): Required<ActionsObjectType<{
[x: string]: /*elided*/ any;
}>>;
};
export declare const stateProvider: typeof atomProvider;
/**
* Get all localStorage items as an object (they will be JSON parsed). You can pass default values (which work with SSR) and a type argument
*/
export declare function useStorage<K = any>(defaults?: K): K;
/**
* A sync wrapper around the `localStorage` API
*/
export declare const storage: {
/**
* Set an item in `localStorage`. Its value will be serialized as JSON
*/
set<T = any>(k: string, v: T): void;
/**
* Remove a `localStorage` item
*/
remove(k: string): Promise<void>;
/**
* Get an item in `localStorage`. Its value will be JSON parsed. If it does not exist or
* is an invalid JSON format, the default value passed in the second argument will be returned
*/
get<T = any>(k: string, def?: T): T;
};
/**
* A sync wrapper around the `sessionStorage` API
*/
export declare const session: {
/**
* Set an item in `sessionStorage`. Its value will be serialized as JSON
*/
set<T = any>(k: string, v: T): void;
/**
* Remove a `sessionStorage` item
*/
remove(k: string): Promise<void>;
/**
* Get an item in `sessionStorage`. Its value will be JSON parsed. If it does not exist or
* is an invalid JSON format, the default value passed in the second argument will be returned
*/
get<T = any>(k: string, def?: T): T;
};
/**
* Get a localStorage item. Whenever `storage.set` or `storage.remove` are called,
* this hook will update its state
*/
export declare function useStorageItem<T = any>(k: string, def?: T): T;
export {};