import { PrimitiveOrNested, Primitive } from 'keyweaver'; import { ComponentType, PropsWithChildren } from 'react'; declare const $tate = "$tate"; type Nil = null | undefined; type Falsy = Nil | false | 0 | ''; declare const STATE_MARKER: unique symbol; declare class StateBase { [STATE_MARKER]: T; } /** * Represents a basic reactive state that holds a value. * * @example * ```ts * const state: State = createState(0); * ``` */ interface State extends StateBase { set(value: Value): void; get(): Value; } type ErrorState = StateBase & { set(error: Error | undefined): void; get(): Error | undefined; }; type IsLoadedState = StateBase & { get(): boolean; }; /** * Represents a state that manages an asynchronous value, including {@link AsyncState.isLoaded loading} and {@link AsyncState.error error} states. * Extends {@link State}. */ interface AsyncState extends StateBase { /** A state that holds the latest error, if one occurred during loading. */ readonly error: ErrorState; /** A state that indicates whether the state has successfully loaded */ readonly isLoaded: IsLoadedState; get(): Value | undefined; set(value: Value): void; } /** * Represents a state that supports loading functionality, extending {@link AsyncState} * with a method to initiate and manage the loading process. */ type LoadableState = AsyncState & { /** * Initiates the loading process for the state if it has not already started. * If the loading process is already active, it increases the load listener count. * * The returned function decreases the load listener count, and the loading process * will only be canceled if there are no remaining load listeners. * * @param {boolean} [force=false] - If `true`, forces the loading process to reload, * even if it has previously completed or is in progress. * @returns - A function to decrease the load listener count. The loading * process is only marked as cancelable when all listeners have been removed. * * @example * ```ts * const decreaseLoadListener = state.load(); * * // Call decreaseLoadListener to decrease the load listener count. * // The loading process is only canceled if no other listeners remain. * decreaseLoadListener(); * ``` */ load(force?: boolean): () => void; } & ([Control] extends [never] ? {} : { readonly control: Control; }); declare const SCOPE_MARKER: unique symbol; type ScopeMarker = { [SCOPE_MARKER]: T; }; type ProcessScope, N = Extract> = (0 extends 1 & Value ? { readonly [key in string | number]: ProcessScope; } : M extends Primitive ? {} : M extends any[] ? { readonly [key in ToIndex]-?: ProcessScope; } : { readonly [key in keyof M]-?: ProcessScope; }) & { readonly [$tate]: S extends LoadableState ? LoadableState : S extends AsyncState ? AsyncState : State; } & ScopeMarker; declare class Scope { } type StateScope = Scope & ProcessScope; type AsyncStateScope = Scope & ProcessScope>; type LoadableStateScope = Scope & ProcessScope>; type PollableStateScope = Scope & LoadableStateScope; type StringToNumber = T extends `${infer K extends number}` ? K : never; type ToIndex = [Exclude] extends [never] ? number : StringToNumber; type ExtractValues, Nullable extends boolean = false> = Readonly<{ [index in keyof T]: T[index] extends AsyncState ? K | (Nullable extends false ? never : undefined) : undefined; }>; type ExtractErrors> = Readonly<{ [index in keyof T]: T[index] extends AsyncState ? K | undefined : undefined; }>; type AsyncStateOptions = { /** The initial value of the state or a function to resolve it using keys. */ value?: T | ((...args: [Keys] extends [never] ? [] : [keys: Keys]) => T); /** A function to determine if the state is considered loaded, based on the {@link value current} and {@link prevValue previous} values and the number of loading {@link attempt attempts}. */ isLoaded?(value: T, prevValue: T | undefined, attempt: number): boolean; /** The timeout in milliseconds for considering the loading process slow. */ loadingTimeout?: number; }; interface WithControl { Control: new (options: Omit, state: S) => Control; } type LoadableStateOptions = AsyncStateOptions & { /** * A function to initiate the loading process. This method can optionally return * a cleanup function to be called when the loading is complete or canceled. */ load(this: AsyncState, ...keys: [Keys] extends [never] ? [] : Keys): void | (() => void); /** * The duration in milliseconds. If set, the state will reload * if accessed again after this time has passed since the last load. */ reloadIfStale?: number; /** * The duration in milliseconds. If set, the state will reload * when the tab gains focus after this duration has passed since the last load. */ reloadOnFocus?: number; revalidate?: boolean; } & ([Control] extends [never] ? {} : WithControl>); type RequestableStateOptions = Omit, 'load' | 'isLoaded'> & { /** * A function that starts the loading process for the state and returns a promise * that resolves with the loaded value. */ fetch(...keys: [Keys] extends [never] ? [] : Keys): Promise; /** * A function that determines whether the loading process should be retried after an error occurs. * @param err - The error encountered during the loading attempt. * @param attempt - The number of loading attempts made so far. * @returns The delay in milliseconds before retrying, or `0` to stop retrying. */ shouldRetryOnError?(err: E, attempt: number): number; }; interface PollableMethods { /** Pauses the current polling process. */ pause(): void; /** Resumes a polling process. */ resume(): void; /** Resets the loading process, starting it from the beginning. */ reset(): void; } type PollableState = LoadableState; type PollableStateOptions = RequestableStateOptions & Pick, 'isLoaded'> & { /** The interval in milliseconds at which the state should poll for new data. */ interval: number; /** * The interval in milliseconds for polling when the document is hidden (e.g., when the tab is not in focus). * If set to `0`, polling is disabled while the tab is hidden. */ hiddenInterval?: number; }; type StorageRecord = { [key in string]: StorageItem | StorageMarker; }; type StorageItem = State | ScopeMarker | StorageRecord | Omit, 'usePages'>; declare const STATE_STORAGE_IDENTIFIER: unique symbol; type StorageMarker = { [STATE_STORAGE_IDENTIFIER]: [Keys, Item]; }; type PartialTuple = T extends [...infer Rest, infer _] ? [] extends Rest ? never : Rest | PartialTuple : never; /** * Represents a structured state storage system that allows retrieval and deletion * of state entries using specified keys. */ type Storage = StorageMarker & { /** * Retrieves a state within the storage using the provided keys. * * @example * ```js * const state = storage.get('key', { some: { nested: ['key'] } }); * ``` */ get(...keys: Keys): T; /** * Deletes a state entry from the storage associated with the given key. * * **Warning**: This is an unsafe method. It only removes the state entry from * the storage but does not clear or reset the state itself. */ delete(...keys: Keys | PartialTuple): void; }; type PaginatedStorageOptions = { shouldRevalidate?: boolean | ((...args: T extends LoadableState ? [state: T] : [scope: T]) => boolean); }; /** * Represents a paginated state storage system for managing state entries across multiple pages. */ type PaginatedStorage = { readonly page: State; /** Retrieves a state entry for the specified page number within the paginated storage. */ get(page: number): T; /** * Deletes a state entry for the specified page number from the paginated storage. * * **Warning**: This is an unsafe method. It only removes the state entry from * the storage but does not clear or reset the state itself. */ delete(page: number): void; } & (T extends ScopeMarker ? { /** * A hook that retrieves an array of items and errors for the current {@link PaginatedStorage.page page state value} in the paginated storage. * * @example * ```js * const [items, errors] = paginatedStorage.usePages(); * ``` */ usePages(getState: (scope: T) => S): S extends LoadableState ? readonly [ items: ReadonlyArray, errors: ReadonlyArray ] : never; } : { /** * A hook that retrieves an array of items and errors for the current {@link PaginatedStorage.page page state value} in the paginated storage. * * @example * ```js * const [items, errors] = paginatedStorage.usePages(); * ``` */ usePages(): T extends LoadableState ? readonly [ items: ReadonlyArray, errors: ReadonlyArray ] : never; }); type WithInitModule = [ ...Args, stateInitializer?: StateInitializer ]; type StateInitializer = (keys: PrimitiveOrNested[] | undefined) => { set(value: T): void; get(): T | undefined; observe?(setState: (value: T) => void): () => void; }; type ContainerType = ComponentType | keyof JSX.IntrinsicElements; export { type AsyncState as A, type ContainerType as C, type ExtractValues as E, type Falsy as F, type LoadableState as L, type PollableState as P, type RequestableStateOptions as R, type State as S, type WithInitModule as W, type StateScope as a, type AsyncStateScope as b, type LoadableStateScope as c, type LoadableStateOptions as d, type AsyncStateOptions as e, type PollableStateScope as f, type PollableStateOptions as g, type Storage as h, type PaginatedStorage as i, StateBase as j, type ExtractErrors as k, type StorageRecord as l, type PollableMethods as m, type StateInitializer as n, type PaginatedStorageOptions as o };