import type { AllKeys, ReadableAtom, ReadonlyIfObject, WritableAtom } from '../atom/index.js' type KeyofBase = keyof any type Get = Extract[K] export type HasIndexSignature = string extends keyof T ? true : false export type ValueWithUndefinedForIndexSignatures< Value, Key extends keyof Value > = HasIndexSignature extends true ? undefined | Value[Key] : Value[Key] export type WritableStore = | (Value extends object ? MapStore : never) | WritableAtom export type Store = ReadableAtom | WritableStore export type AnyStore = { get(): Value readonly value: undefined | Value } export type StoreValue = SomeStore extends { get(): infer Value } ? Value : any export type BaseMapStore = { setKey: (key: any, value: any) => any } & WritableAtom export type MapStoreKeys = SomeStore extends { setKey: (key: infer K, ...args: any[]) => any } ? K : AllKeys> export interface MapStore< Value extends object = any > extends WritableAtom { /** * Subscribe to store changes. * * In contrast with {@link Store#subscribe} it do not call listener * immediately. * * @param listener Callback with store value and old value. * @param changedKey Key that was changed. Will present only if `setKey` * has been used to change a store. * @returns Function to remove listener. */ listen( listener: ( value: ReadonlyIfObject, oldValue: ReadonlyIfObject, changedKey: AllKeys ) => void ): () => void /** * Low-level method to notify listeners about changes in the store. * * Can cause unexpected behaviour when combined with frontend frameworks * that perform equality checks for values, such as React. */ notify(oldValue?: ReadonlyIfObject, changedKey?: AllKeys): void /** * Change store value. * * ```js * $settings.set({ theme: 'dark' }) * ``` * * Operation is atomic, subscribers will be notified once with the new value. * `changedKey` will be undefined * * @param newValue New store value. */ set(newValue: Value): void /** * Change key in store value. * * ```js * $settings.setKey('theme', 'dark') * ``` * * To delete key set `undefined`. * * ```js * $settings.setKey('theme', undefined) * ``` * * @param key The key name. * @param value New value. */ setKey>( key: Key, value: Get | ValueWithUndefinedForIndexSignatures ): void /** * Subscribe to store changes and call listener immediately. * * ``` * import { $router } from '../store' * * $router.subscribe(page => { * console.log(page) * }) * ``` * * @param listener Callback with store value and old value. * @param changedKey Key that was changed. Will present only * if `setKey` has been used to change a store. * @returns Function to remove listener. */ subscribe( listener: ( value: ReadonlyIfObject, oldValue: ReadonlyIfObject | undefined, changedKey: AllKeys | undefined ) => void ): () => void } export interface PreinitializedMapStore< Value extends object = any > extends MapStore { readonly value: Value } /** * Create map store. Map store is a store with key-value object * as a store value. * * @param init Initialize store and return store destructor. * @returns The store object with methods to subscribe. */ export function map( value?: Value ): PreinitializedMapStore & StoreExt