UNPKG

atomic-state

Version:

Atomic State is a state management library for React

307 lines (306 loc) 11.1 kB
/** @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 {};