import React from 'react'; /** * 'JSON path' from root of a state object to a nested property. * Return type of [StateMethod.path](#readonly-path). * * For example, an object `{ a: [{ b: 1 }, { 1000: 'value' }, '3rd'] }`, * has got the following paths pointing to existing properties: * * - `[]` * - `['a']` * - `['a', 0]` * - `['a', 0, 'b']` * - `['a', 1]` * - `['a', 1, 1000]` * - `['a', 2]` */ export declare type Path = ReadonlyArray; /** * Type of an argument of [State.set](#set). * * @typeparam S Type of a value of a state */ export declare type SetStateAction = (S | Immutable | Promise>) | ((prevState: S) => (S | Immutable | Promise>)); /** * Type of an argument of [State.merge](#merge). * * @typeparam S Type of a value of a state */ export declare type SetPartialStateAction = S extends ReadonlyArray<(infer U)> ? ReadonlyArray> | Record> | ((prevValue: S) => (ReadonlyArray> | Record>)) : S extends object | string ? Partial> | ((prevValue: S) => Partial>) : S | Immutable | ((prevState: S) => (S | Immutable)); /** * Type of an argument of [hookstate](#hookstate) and [useHookstate](#useHookstate). * * @typeparam S Type of a value of a state */ export declare type SetInitialStateAction = S | Promise | (() => S | Promise); /** * Special symbol which might be used to delete properties * from an object calling [State.set](#set) or [State.merge](#merge). * * [Learn more...](https://hookstate.js.org/docs/nested-state#deleting-existing-element) */ export declare const none: any; /** * Return type of [State.keys](#readonly-keys). * * @typeparam S Type of a value of a state */ export declare type InferStateKeysType = S extends ReadonlyArray ? ReadonlyArray : S extends null ? undefined : S extends object ? ReadonlyArray : undefined; /** * Return type of [State.ornull](#ornull). * * @typeparam S Type of a value of a state */ export declare type InferStateOrnullType = S extends undefined ? undefined : S extends null ? null : State; /** * Makes a value deep readonly */ export declare type Immutable = T extends ImmutablePrimitive ? T : T extends Array ? ImmutableArray : T extends Map ? ImmutableMap : T extends Set ? ImmutableSet : ImmutableObject; export declare type ImmutablePrimitive = undefined | null | boolean | string | number | Function; export declare type ImmutableArray = ReadonlyArray>; export declare type ImmutableMap = ReadonlyMap, Immutable>; export declare type ImmutableSet = ReadonlySet>; export declare type ImmutableObject = { readonly [K in keyof T]: Immutable; }; /** * An interface to manage a state in Hookstate. * * @typeparam S Type of a value of a state */ export interface StateMethods { /** * 'Javascript' object 'path' to an element relative to the root object * in the state. For example: * * ```tsx * const state = useHookstate([{ name: 'First Task' }]) * state.path IS [] * state[0].path IS [0] * state.[0].name.path IS [0, 'name'] * ``` */ readonly path: Path; /** * Return the keys of nested states. * For a given state of [State](#state) type, * `state.keys` will be structurally equal to Object.keys(state), * with two minor difference: * 1. if `state.value` is an array, the returned result will be * an array of numbers, not strings like with `Object.keys`. * 2. if `state.value` is not an object, the returned result will be undefined. */ readonly keys: InferStateKeysType; /** * Unwraps and returns the underlying state value referred by * [path](#readonly-path) of this state instance. * * It returns the same result as [State.get](#get) method. * * This property is more useful than [get](#get) method for the cases, * when a value may hold null or undefined values. * Typescript compiler does not handle elimination of undefined with get(), * like in the following examples, but value does: * * ```tsx * const state = useHookstate(0) * const myvalue: number = state.value * ? state.value + 1 * : 0; // <-- compiles * const myvalue: number = state.get() * ? state.get() + 1 * : 0; // <-- does not compile * ``` */ readonly value: Immutable; /** * True if state value is not yet available (eg. equal to a promise) */ readonly promised: boolean; /** * If the State is promised, this will be a defined promise * which an application can use to subscribe to with 'then' callback. */ readonly promise: Promise> | undefined; /** * If a state was set to a promise and the promise was rejected, * this property will return the error captured from the promise rejection */ readonly error: StateErrorAtRoot | undefined; /** * Unwraps and returns the underlying state value referred by * [path](#readonly-path) of this state instance. * * It returns the same result as [State.value](#readonly-value) method. * * If the additional option `noproxy` is set, the method will return * the original data object without wrapping it by proxy. * All properties of the object will be marked as used and on change will trigger the rerender. * * If the additional option `stealth` is set, the method will not mark * the object as used and it will not trigger the rerender if it is changed. * It might be helpful to use it during debugging, for example: * `console.log(state.get({ stealth: true }))`. * If you use it, make sure you know what you are doing. */ get(options?: { noproxy?: boolean; stealth?: boolean; }): Immutable; /** * Sets new value for a state. * If `this.path === []`, * it is similar to the `setState` variable returned by `React.useState` hook. * If `this.path !== []`, it sets only the segment of the state value, pointed out by the path. * Unlike [merge](#merge) method, this method will not accept partial updates. * Partial updates can be also done by walking the nested states and setting those. * * @param newValue new value to set to a state. * It can be a value, a promise resolving to a value * (only if [this.path](#readonly-path) is `[]`), * or a function returning one of these. * The function receives the current state value as an argument. */ set(newValue: SetStateAction): void; /** * Similarly to [set](#set) method updates state value. * * - If current state value is an object, it does partial update for the object. * - If state value is an array and the argument is an array too, * it concatenates the current value with the value of the argument and sets it to the state. * - If state value is an array and the `merge` argument is an object, * it does partial update for the current array value. * - If current state value is a string, it concatenates the current state * value with the argument converted to string and sets the result to the state. */ merge(newValue: SetPartialStateAction): void; /** * Returns nested state by key. * `state.nested('myprop')` returns the same as `state.myprop` or `state['myprop']`, * but also works for properties, which names collide with names of state methods. * * [Learn more about nested states...](https://hookstate.js.org/docs/nested-state) * * @param key child property name or index */ nested(key: K): State; /** * If state value is null or undefined, returns state value. * Otherwise, it returns this state instance but * with null and undefined removed from the type parameter. * * [Learn more...](https://hookstate.js.org/docs/nullable-state) */ ornull: InferStateOrnullType; } /** * Returns an interface stripped of all keys that don't resolve to U, defaulting * to a non-strict comparison of T[key] extends U. Setting B to true performs * a strict type comparison of T[key] extends U & U extends T[key] */ export declare type InferKeysOfType = { [P in keyof T]: B extends true ? T[P] extends U ? (U extends T[P] ? P : never) : never : T[P] extends U ? P : never; }[keyof T]; /** * A symbol which is used for type inference marking. * * @hidden * @ignore */ export declare const __state: unique symbol; /** * An interface which is used for type inference marking. * * @hidden * @ignore */ export interface __State { [__state]: [S, E]; } /** * A routine which allows to extract value type of a state. Useful for extension developers. */ export declare type InferStateValueType = InferReturnType extends __State<(infer S), (infer _)> ? S : V; /** * A routine which allows to extract extension methods / properties type of a state. * Useful for extension developers. */ export declare type InferStateExtensionType = InferReturnType extends __State<(infer _), (infer E)> ? E : InferReturnType extends Extension<(infer _), (infer _), (infer E)> ? E : V; export declare type InferReturnType = V extends (...args: any) => (infer R) ? InferReturnType : V; /** * Type of a result of [hookstate](#hookstate) and [useHookstate](#useHookstate) functions * * @typeparam S Type of a value of a state * * [Learn more about global states...](https://hookstate.js.org/docs/global-state) * [Learn more about local states...](https://hookstate.js.org/docs/local-state) * [Learn more about nested states...](https://hookstate.js.org/docs/nested-state) */ export declare type State = __State & StateMethods & E & (S extends ReadonlyArray ? ReadonlyArray> : S extends object ? Omit<{ readonly [K in keyof Required]: State; }, keyof StateMethods | InferKeysOfType | keyof E> : {}); /** * For extension developers only. * Type alias to highlight the places where we are dealing with root state value. * * @hidden * @ignore */ export declare type StateValueAtRoot = any; /** * For extension developers only. * Type alias to highlight the places where we are dealing with nested state value. * * @hidden * @ignore */ export declare type StateValueAtPath = any; /** * For extension developers only. * Type alias to highlight the places where we are dealing with state error. * * @hidden * @ignore */ export declare type StateErrorAtRoot = any; /** * For extension developers only. * Type alias to highlight the places where we are dealing with unknown state extension type. * * @hidden * @ignore */ export declare type StateExtensionUnknown = any; /** * For extension developers only. * An additional descriptor of an action mutation action applied * * @hidden * @ignore */ export interface SetActionDescriptor { path: Path; actions?: Record; } /** * For extension developers only. * Set of callbacks, an extension may subscribe to. * * [Learn more...](https://hookstate.js.org/docs/writing-extension) */ export interface Extension { readonly onCreate?: (state: State, extensionsCallbacks: { [K in keyof I]: (i: State) => I[K]; }) => { readonly [K in keyof Required]: (state: State) => E[K]; }; readonly onInit?: (state: State, extensionsCallbacks: { [K in keyof E & I]: (i: State) => (E & I)[K]; }) => void; readonly onPreset?: (state: State, value: StateValueAtPath, rootState: State) => void; readonly onPremerge?: (state: State, value: StateValueAtPath, rootState: State) => void; readonly onSet?: (state: State, descriptor: SetActionDescriptor, rootState: State) => void; readonly onDestroy?: (state: State) => void; } export declare type ExtensionFactory = (typemarker?: __State) => Extension; export declare function hookstate(source: __State, extension?: ExtensionFactory): never; /** * Creates new state and returns it. * * You can create as many global states as you need. * * When you the state is not needed anymore, * it should be destroyed by calling * `destroy()` function. * This is necessary for some extensions, * which allocate native resources, * like subscription to databases, broadcast channels, etc. * In most cases, a global state is used during * whole life time of an application and would not require * destruction. However, if you have got, for example, * a catalog of dynamically created and destroyed global states, * the states should be destroyed as advised above. * * @param initial Initial value of the state. * It can be a value OR a promise, * which asynchronously resolves to a value, * OR a function returning a value or a promise. * * @typeparam S Type of a value of the state * * @returns [State](#state) instance, * which can be used directly to get and set state value * outside of React components. * When you need to use the state in a functional `React` component, * pass the created state to [useHookstate](#useHookstate) function and * use the returned result in the component's logic. */ export declare function hookstate(initial: SetInitialStateAction, extension?: ExtensionFactory): State; /** * A method to destroy a global state and resources allocated by the extensions */ export declare function destroy(state: __State): void; /** * A method to check if a variable is an instance of Hookstate State */ export declare function isHookstate(v: any): boolean; /** * A method to check if a variable is an instance of traced (wrapped in a proxy) Hookstate Value */ export declare function isHookstateValue(v: any): boolean; /** * A function combines multiple extensions into one extension and returns it * Browse an example [here](https://hookstate.js.org/docs/extensions-snapshotable) */ export declare function extend(e1?: ExtensionFactory, e2?: ExtensionFactory, e3?: ExtensionFactory, e4?: ExtensionFactory, e5?: ExtensionFactory): ExtensionFactory; /** * @warning Initializing a local state to a promise without using * an initializer callback function, which returns a Promise, * is almost always a mistake. So, it is blocked. * Use `useHookstate(() => your_promise)` instead of `useHookstate(your_promise)`. */ export declare function useHookstate(source: Promise, extension?: ExtensionFactory): never; export declare function useHookstate(source: __State, extension: ExtensionFactory): never; /** * Enables a functional React component to use a state, * either created by [hookstate](#hookstate) (*global* state) or * derived from another call to [useHookstate](#useHookstate) (*scoped* state). * * The `useHookstate` forces a component to rerender every time, when: * - a segment/part of the state data is updated *AND only if* * - this segment was **used** by the component during or after the latest rendering. * * For example, if the state value is `{ a: 1, b: 2 }` and * a component uses only `a` property of the state, it will rerender * only when the whole state object is updated or when `a` property is updated. * Setting the state value/property to the same value is also considered as an update. * * A component can use one or many states, * i.e. you may call `useHookstate` multiple times for multiple states. * * The same state can be used by multiple different components. * * @param source a reference to the state to hook into * * The `useHookstate` is a hook and should follow React's rules of hooks. * * @returns an instance of [State](#state), * which **must be** used within the component (during rendering * or in effects) or it's children. */ export declare function useHookstate(source: __State): State; /** * This function enables a functional React component to use a state, * created per component by [useHookstate](#useHookstate) (*local* state). * In this case `useHookstate` behaves similarly to `React.useState`, * but the returned instance of [State](#state) * has got more features. * * When a state is used by only one component, and maybe it's children, * it is recommended to use *local* state instead of *global*, * which is created by [hookstate](#hookstate). * * *Local* (per component) state is created when a component is mounted * and automatically destroyed when a component is unmounted. * * The same as with the usage of a *global* state, * `useHookstate` forces a component to rerender when: * - a segment/part of the state data is updated *AND only if* * - this segment was **used** by the component during or after the latest rendering. * * You can use as many local states within the same component as you need. * * @param source An initial value state. * * @returns an instance of [State](#state), * which **must be** used within the component (during rendering * or in effects) or it's children. */ export declare function useHookstate(source: SetInitialStateAction, extension?: ExtensionFactory): State; export declare function StateFragment(props: { state: __State; extension: ExtensionFactory; children: (state: State) => React.ReactElement; suspend?: boolean; }): never; /** * Allows to use a state without defining a functional react component. * It can be also used in class-based React components. It is also * particularly useful for creating *scoped* states. * * [Learn more...](https://hookstate.js.org/docs/using-without-statehook) * * @typeparam S Type of a value of a state */ export declare function StateFragment(props: { state: __State; children: (state: State) => React.ReactElement; suspend?: boolean; }): React.ReactElement; /** * Allows to use a state without defining a functional react component. * See more at [StateFragment](#statefragment) * * [Learn more...](https://hookstate.js.org/docs/using-without-statehook) * * @typeparam S Type of a value of a state */ export declare function StateFragment(props: { state: SetInitialStateAction; extension?: ExtensionFactory; children: (state: State) => React.ReactElement; suspend?: boolean; }): React.ReactElement; /** * If state is promised, then it returns a component which integrates with React 18 Suspend feature automatically. * Note, that React 18 Suspend support for data loading is still experimental, * but it worked as per our experiments and testing. */ export declare function suspend(state: State): React.FunctionComponentElement | undefined; /** * A type of an argument of the configure function */ export interface Configuration { /** * By default Hookstate intercepts calls to useEffect, useMemo and * other functions where a dependency lists are used as arguments. * This allows these hook functions to have Hookstate State objects * in dependency lists and everything to work as 'expected'. * * It is possible to opt-out from this mode, configuring the option to never. * * Alternatively, it is possible to set it to intercept only during development, * which will raise HOOKSTATE-100 error whenever Hookstate State is used in a dependency list of standard React hook function. * This error can be fixed by replacing standard React hooks by Hookstate provided hooks, * for example useEffect by useHookstateEffect */ interceptDependencyListsMode: 'always' | 'development' | 'never'; /** * Defines is Hookstate is running in a development mode. * Development mode enables additional checking and HMR support. * By default, it detects if process.env.NODE_ENV is set to 'development'. * It might not work in all environments and so expected to be provided by an application explicitly. */ isDevelopmentMode: boolean; /** * A callback which allows Hookstate to detect if a provided variable is a promise or not. * This allows to enable Hookstate working in Angular environment when Promises are wrapped by zone.js, * which breaks standard promise resolution / detection convention. */ promiseDetector: (p: any) => boolean; } /** * Configures Hookstate behavior globally. This is for special cases only, when default * heuristics fail to work in a specific environment. * * @param config */ export declare function configure(config: Partial): void; export declare function useHookstateEffect(effect: React.EffectCallback, deps?: React.DependencyList): void; export declare function useHookstateLayoutEffect(effect: React.EffectCallback, deps?: React.DependencyList): void; export declare function useHookstateInsertionEffect(effect: React.EffectCallback, deps?: React.DependencyList): void; export declare function useHookstateImperativeHandle(ref: React.Ref | undefined, init: () => R, deps?: React.DependencyList): void; export declare function useHookstateMemo(factory: () => T, deps: React.DependencyList | undefined): T; export declare function useHookstateCallback(callback: T, deps: React.DependencyList): T; export declare function hookstateMemo>(Component: T, propsAreEqual?: (prevProps: Readonly>, nextProps: Readonly>) => boolean): React.MemoExoticComponent; //# sourceMappingURL=index.d.ts.map