UNPKG

storeon

Version:

Tiny (167 bytes) event-based Redux-like state manager for React and Preact

102 lines (91 loc) 2.77 kB
type DataTypes<Map, Key extends keyof Map> = Map extends never ? [any?] : Map[Key] extends never | undefined ? [never?] : [Map[Key]] /** * Store with application state and event listeners. */ export interface StoreonStore<State = unknown, Events = any> { /** * Add event listener. * * @param event The event name. * @param handler The event listener. * @returns The function to remove listener. */ on<Event extends keyof (Events & StoreonEvents<State, Events>)>( event: Event, handler: createStoreon.EventHandler<State, Events, Event> ): () => void /** * Return current state. You can use this method only to read state. * Any state changes should be in event listeners. * * @returns The current state. */ get(): State /** * Emit event. * * @param event The event name. * @param data Any additional data for the event. * @returns The current state. */ dispatch: StoreonDispatch<Events & createStoreon.DispatchableEvents<State>> } export type StoreonModule<State, Events = any> = ( store: StoreonStore<State, Events> ) => void export interface StoreonEvents<State, Events = any> extends createStoreon.DispatchableEvents<State> { '@dispatch': createStoreon.DispatchEvent< State, Events & createStoreon.DispatchableEvents<State> > } export type StoreonDispatch<Events> = (<Event extends keyof Events>( event: Event, ...data: DataTypes<Partial<Events>, Event> ) => void) & { ___events: Events } export namespace createStoreon { export type DispatchEvent< State, Events, Event extends keyof Events = keyof Events > = [Event, Events[Event], EventHandler<State, Events, Event>[]] export type EventHandler< State, Events, Event extends keyof (Events & StoreonEvents<State, Events>) > = ( state: State extends object ? Readonly<State> : State, data: (Events & StoreonEvents<State, Events>)[Event] ) => Partial<State> | Promise<void> | null | void export interface DispatchableEvents<State> { '@init': never '@changed': State } } /** * Initialize new store and apply all modules to the store. * * ```js * import { createStoreon } from 'storeon' * let increment = store => { * store.on('@init', () => ({ count: 0 })) * store.on('inc', ({ count }) => ({ count: count + 1 })) * } * const store = createStoreon([increment]) * store.get().count //=> 0 * store.dispatch('inc') * store.get().count //=> 1 * ``` * * @param modules Functions which will set initial state define reducer * and subscribe to all system events. * @returns The new store. */ export function createStoreon<State, Events = any> ( modules: (StoreonModule<State, Events> | false)[] ): StoreonStore<State, Events>