react-hooks-global-states 16.0.0 → 16.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/jest.config.js +50 -0
  2. package/package.json +52 -2
  3. package/GlobalStore.cjs +0 -525
  4. package/GlobalStore.d.ts +0 -160
  5. package/GlobalStore.debugProps.cjs +0 -28
  6. package/GlobalStore.debugProps.d.ts +0 -5
  7. package/GlobalStore.debugProps.js +0 -28
  8. package/GlobalStore.debugProps.mjs +0 -7
  9. package/GlobalStore.js +0 -525
  10. package/GlobalStore.mjs +0 -497
  11. package/actions.cjs +0 -61
  12. package/actions.d.ts +0 -32
  13. package/actions.js +0 -61
  14. package/actions.mjs +0 -30
  15. package/bundle.cjs +0 -40
  16. package/bundle.js +0 -40
  17. package/bundle.mjs +0 -19
  18. package/createContext.cjs +0 -253
  19. package/createContext.d.ts +0 -15
  20. package/createContext.js +0 -253
  21. package/createContext.mjs +0 -235
  22. package/createGlobalState.cjs +0 -29
  23. package/createGlobalState.d.ts +0 -7
  24. package/createGlobalState.js +0 -29
  25. package/createGlobalState.mjs +0 -8
  26. package/index.d.ts +0 -9
  27. package/isRecord.cjs +0 -46
  28. package/isRecord.d.ts +0 -2
  29. package/isRecord.js +0 -46
  30. package/isRecord.mjs +0 -15
  31. package/shallowCompare.cjs +0 -115
  32. package/shallowCompare.d.ts +0 -52
  33. package/shallowCompare.js +0 -115
  34. package/shallowCompare.mjs +0 -84
  35. package/throwWrongKeyOnActionCollectionConfig.cjs +0 -41
  36. package/throwWrongKeyOnActionCollectionConfig.d.ts +0 -2
  37. package/throwWrongKeyOnActionCollectionConfig.js +0 -41
  38. package/throwWrongKeyOnActionCollectionConfig.mjs +0 -20
  39. package/types.cjs +0 -18
  40. package/types.d.ts +0 -1250
  41. package/types.js +0 -18
  42. package/types.mjs +0 -0
  43. package/uniqueId.cjs +0 -72
  44. package/uniqueId.d.ts +0 -7
  45. package/uniqueId.js +0 -72
  46. package/uniqueId.mjs +0 -51
package/types.d.ts DELETED
@@ -1,1250 +0,0 @@
1
- import type GlobalStore from './GlobalStore';
2
- import type { Context as ReactContext, PropsWithChildren } from 'react';
3
- export type Any = any;
4
- export type AnyFunction = (...args: Any[]) => Any;
5
- /**
6
- * @description Represents a hook that returns a readonly state.
7
- */
8
- export interface ReadonlyHook<State, StateMutator, Metadata extends BaseMetadata> extends ReadonlyStateApi<State, StateMutator, Metadata> {
9
- /**
10
- * @description Returns the current state value.
11
- */
12
- (): State;
13
- /**
14
- * @description Returns a derived state based on the provided selector function.
15
- */
16
- <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Derivate;
17
- /**
18
- * @description Returns a derived state based on the provided selector function and configuration.
19
- */
20
- <Derivate>(selector: (state: State) => Derivate, config?: UseHookOptions<Derivate, State>): Derivate;
21
- }
22
- /**
23
- * @description Hook to select a fragment of the state
24
- */
25
- export interface SelectHook<State> {
26
- /**
27
- * @description Selects a fragment of the state using the provided selector function.
28
- * @param selector - The function to select a fragment of the state.
29
- * @param dependencies - Optional dependencies array to control re-evaluation.
30
- * @returns The selected fragment of the state.
31
- */
32
- <Selection>(selector: (state: State) => Selection, dependencies?: unknown[]): Selection;
33
- /**
34
- * @description Selects a fragment of the state using the provided selector function and configuration.
35
- * @param selector - The function to select a fragment of the state.
36
- * @param args - Configuration options for the selection.
37
- * @returns The selected fragment of the state.
38
- */
39
- <Selection>(selector: (state: State) => Selection, args?: UseHookOptions<Selection, State>): Selection;
40
- }
41
- /**
42
- * @description Represents the complete non-reactive API of a global state instance.
43
- * This API provides full control over the state, including reading, writing, subscribing,
44
- * and creating derived hooks or observable fragments.
45
- */
46
- export type StateApi<State, StateMutator, Metadata extends BaseMetadata> = {
47
- /**
48
- * Returns the metadata
49
- * Metadata is additional non reactive information associated with the global state
50
- */
51
- getMetadata: MetadataGetter<Metadata>;
52
- /**
53
- * Sets the metadata value
54
- * The metadata value is not reactive and wont trigger re-renders
55
- */
56
- setMetadata: MetadataSetter<Metadata>;
57
- /**
58
- * @description Contains the generated action functions if custom actions are defined.
59
- * If no actions are provided, this property is `null`.
60
- */
61
- actions: StateMutator extends AnyFunction ? null : StateMutator;
62
- /**
63
- * @description Provides direct access to the state updater.
64
- * Always available for testing purposes, even when actions are defined.
65
- * In production, prefer using actions when they are defined.
66
- */
67
- setState: React.Dispatch<React.SetStateAction<State>>;
68
- /**
69
- * @description Get the current state value
70
- */
71
- getState: () => State;
72
- /**
73
- * @description Subscribe to the state changes
74
- * You can subscribe to the whole state or to a fragment of the state by passing a selector as first parameter,
75
- * this can be used in non react environments to listen to the state changes
76
- */
77
- subscribe: SubscribeToState<State>;
78
- /***
79
- * @description Creates a new hooks that returns the result of the selector passed as a parameter
80
- * Your can create selector hooks of other selectors hooks and extract as many derived states as or fragments of the state as you want
81
- * The selector hook will be evaluated only if the result of the selector changes and the equality function returns false
82
- * you can customize the equality function by passing the isEqualRoot and isEqual parameters
83
- */
84
- createSelectorHook: <Selection>(selector: (state: State) => Selection, args?: Omit<UseHookOptions<Selection, State>, 'dependencies'> & {
85
- name?: string;
86
- }) => ReadonlyHook<Selection, StateMutator, Metadata>;
87
- /**
88
- * @description Creates a function that allows you to subscribe to a fragment of the state
89
- * The observable selection will notify the subscribers only if the fragment changes and the equality function returns false
90
- * you can customize the equality function by passing the isEqualRoot and isEqual parameters
91
- */
92
- createObservable: <Selection>(this: ReadonlyStateApi<State, StateMutator, Metadata>, selector: (state: State) => Selection, args?: {
93
- isEqual?: (current: Selection, next: Selection) => boolean;
94
- isEqualRoot?: (current: State, next: State) => boolean;
95
- /**
96
- * @description Name of the observable fragment for debugging purposes
97
- */
98
- name?: string;
99
- }) => ObservableFragment<Selection, StateMutator, Metadata>;
100
- /**
101
- * @description Selects a fragment of the state using the provided selector function.
102
- */
103
- select: SelectHook<State>;
104
- /**
105
- * @description Sugared hook to use the global state in React components
106
- * Allows you to tread the global hook as an store, with better semantics
107
- *
108
- * @example
109
- * ```tsx
110
- * const contacts = createContext<ContactType[]>([]);
111
- *
112
- * function ContactsList() {
113
- * const [contacts, setContacts] = contacts.use();
114
- * ```
115
- *
116
- * This is more practical since the StateApi is slightly more complex than a simple hook
117
- *
118
- * @example
119
- * Using a global state:
120
- *
121
- * ```tsx
122
- * const [state, setState, metadata] = state.use();
123
- *
124
- * const selection = state.select((state) => state.someFragment);
125
- *
126
- * const unsubscribe = state.subscribe((state) => { ... });
127
- *
128
- * const useFragment = state.createSelectorHook((state) => state.someFragment);
129
- *
130
- * const observable = state.createObservable((state) => state.someFragment);
131
- * ```
132
- */
133
- use: StateHook<State, StateMutator, Metadata>;
134
- /**
135
- * @description Disposes the global state instance, cleaning up all resources and subscriptions.
136
- */
137
- dispose: () => void;
138
- /**
139
- * PLEASE USE CALLBACK-BASED INITIALIZERS FOR STATE AND METADATA IF YOU PLAN TO USE RESET OFTEN.
140
- *
141
- * @description Resets the store to its initial state and metadata as provided during creation.
142
- * This method is reserved for advanced use cases and testing scenarios, use with caution.
143
- * If the initial state and metadata are static values this may not work as you expect.
144
- */
145
- reset(): void;
146
- /**
147
- * @description Resets the store to a new initial state and re-runs initialization (including onInit callbacks).
148
- * Existing subscribers are maintained and notified of the new state.
149
- * Useful for testing scenarios where you need to reinitialize the store.
150
- * @param newState - The new initial state to reset to
151
- * @param newMetadata - The new metadata to set after reset
152
- */
153
- reset(newState: State, newMetadata: Metadata): void;
154
- /**
155
- * @deprecated
156
- * @description Useful for debugging purposes, exposes the current subscribers of the store
157
- * You'll probably not need to use this in your application
158
- */
159
- subscribers: Set<SubscriberParameters>;
160
- };
161
- /**
162
- * @description Readonly version of the StateApi, excluding mutative methods.
163
- */
164
- export type ReadonlyStateApi<State, StateMutator, Metadata extends BaseMetadata> = Pick<StateApi<State, StateMutator, Metadata>, 'dispose' | 'getState' | 'subscribe' | 'createSelectorHook' | 'createObservable' | 'subscribers'>;
165
- /**
166
- * @description Function that allows you to subscribe to a fragment of the state
167
- */
168
- export type ObservableFragment<State, StateMutator, Metadata extends BaseMetadata> = SubscribeToState<State> & Pick<StateApi<State, StateMutator, Metadata>, 'getState' | 'subscribe' | 'createSelectorHook' | 'createObservable' | 'dispose' | 'subscribers'>;
169
- export interface StateHook<State, StateMutator, Metadata extends BaseMetadata> extends StateApi<State, StateMutator, Metadata> {
170
- /**
171
- * @description React hook that provides access to the state, state mutator, and metadata.
172
- */
173
- (): Readonly<[state: State, stateMutator: StateMutator, metadata: Metadata]>;
174
- /**
175
- * @description React hook that provides a derived state based on the provided selector function.
176
- */
177
- <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
178
- /**
179
- * @description React hook that provides a derived state based on the provided selector function and configuration.
180
- */
181
- <Derivate>(selector: (state: State) => Derivate, config?: UseHookOptions<Derivate, State>): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
182
- }
183
- /**
184
- * @description Function to set the metadata value
185
- * The metadata value is not reactive and wont trigger re-renders
186
- */
187
- export type MetadataSetter<Metadata extends BaseMetadata> = (setter: Metadata | ((metadata: Metadata) => Metadata)) => void;
188
- /**
189
- * @description Represents the changes in the state
190
- */
191
- export type StateChanges<State> = {
192
- state: State;
193
- previousState: State | undefined;
194
- identifier: string | undefined;
195
- };
196
- /**
197
- * API for the actions of the global states
198
- **/
199
- export type StoreTools<State, StateMutator = React.Dispatch<React.SetStateAction<State>>, Metadata extends BaseMetadata = BaseMetadata> = {
200
- /**
201
- * The actions available for the global state if provided
202
- */
203
- actions: StateMutator extends AnyFunction ? null : StateMutator;
204
- /**
205
- * @description Metadata associated with the global state
206
- */
207
- getMetadata: () => Metadata;
208
- /**
209
- * @description Current state value
210
- */
211
- getState: () => State;
212
- /**
213
- * @description Sets the metadata value
214
- */
215
- setMetadata: MetadataSetter<Metadata>;
216
- /**
217
- * @description Function to set the state value
218
- */
219
- setState: (setter: React.SetStateAction<State>, args?: {
220
- /**
221
- * @description Force update even if the state value did not change, this is for advanced use cases only
222
- */
223
- forceUpdate?: boolean;
224
- /**
225
- * @description Optional identifier visible on the devtools
226
- */
227
- identifier?: string;
228
- }) => void;
229
- /**
230
- * @description Subscribe to the state changes
231
- * You can subscribe to the whole state or to a fragment of the state by passing a selector as first parameter,
232
- * this can be used in non react environments to listen to the state changes
233
- *
234
- * @example
235
- * ```ts
236
- * const unsubscribe = storeTools.subscribe((state) => {
237
- * console.log('State changed:', state);
238
- * });
239
- *
240
- * // To unsubscribe later
241
- * unsubscribe();
242
- * ```
243
- */
244
- subscribe: SubscribeToState<State>;
245
- };
246
- /**
247
- * contract for the storeActionsConfig configuration
248
- */
249
- export interface ActionCollectionConfig<State, Metadata extends BaseMetadata, ThisAPI = Record<string, (...parameters: Any[]) => unknown>> {
250
- readonly [key: string]: {
251
- (this: ThisAPI, ...parameters: Any[]): (this: ThisAPI, storeTools: StoreTools<State, Record<string, (...parameters: Any[]) => unknown | void>, Metadata>) => unknown | void;
252
- };
253
- }
254
- /**
255
- * @description Resulting type of the action collection configuration
256
- */
257
- export type ActionCollectionResult<State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>> = {
258
- [key in keyof ActionsConfig]: {
259
- (...params: Parameters<ActionsConfig[key]>): ReturnType<ReturnType<ActionsConfig[key]>>;
260
- };
261
- };
262
- export type CleanupFunction = () => void;
263
- /**
264
- * Callbacks for the global store lifecycle events
265
- */
266
- export type GlobalStoreCallbacks<State, StateMutator, Metadata extends BaseMetadata> = {
267
- /**
268
- * @description Called when the store is initialized
269
- */
270
- onInit?: (args: StoreTools<State, StateMutator, Metadata>) => void | Promise<void> | CleanupFunction;
271
- /**
272
- * @description Called when the state has changed
273
- */
274
- onStateChanged?: (args: StoreTools<State, StateMutator, Metadata> & StateChanges<State>) => void;
275
- /**
276
- * @description Called when a new subscription is created
277
- */
278
- onSubscribed?: (args: StoreTools<State, StateMutator, Metadata>, subscription: SubscriberParameters) => void;
279
- /**
280
- * @description Called to determine whether to prevent a state change
281
- */
282
- computePreventStateChange?: (args: StoreTools<State, StateMutator, Metadata> & StateChanges<State>) => boolean;
283
- /**
284
- * @description Called when the store is unmounted, only applicable in context stores
285
- */
286
- onUnMount?: (store: StoreTools<State, StateMutator, Metadata>) => void;
287
- };
288
- /**
289
- * @description Configuration options for the use hook
290
- */
291
- export type UseHookOptions<State, TRoot = Any> = {
292
- isEqual?: (current: State, next: State) => boolean;
293
- isEqualRoot?: (current: TRoot, next: TRoot) => boolean;
294
- dependencies?: unknown[];
295
- };
296
- /**
297
- * @description Callback function to unsubscribe from the store changes
298
- */
299
- export type UnsubscribeCallback = () => void;
300
- /**
301
- * @description Configuration for the subscribe callback
302
- */
303
- export type SubscribeCallbackConfig<State> = UseHookOptions<State> & {
304
- /**
305
- * By default the callback is executed immediately after the subscription
306
- */
307
- skipFirst?: boolean;
308
- };
309
- /**
310
- * Callback function to subscribe to the store changes
311
- */
312
- export type SubscribeCallback<State> = (state: State) => void;
313
- /**
314
- * @description Subscribe to the state changes
315
- * You can subscribe to the whole state or to a fragment of the state by passing a selector as first parameter
316
- * This can be used in non react environments to listen to the state changes
317
- */
318
- export type SubscribeToState<State> = {
319
- /**
320
- * @description Subscribe to the whole state changes
321
- *
322
- * @example
323
- * ```ts
324
- * const unsubscribe = store.subscribe((state) => {
325
- * console.log('State changed:', state);
326
- * });
327
- *
328
- * // To unsubscribe later
329
- * unsubscribe();
330
- * ```
331
- */
332
- (subscription: SubscribeCallback<State>, config?: SubscribeCallbackConfig<State>): UnsubscribeCallback;
333
- /**
334
- * @description Subscribe to a fragment of the state changes
335
- *
336
- * @example
337
- * ```ts
338
- * const unsubscribe = store.subscribe(
339
- * (fragment) => {
340
- * console.log('Fragment changed:', fragment);
341
- * },
342
- * (state) => {
343
- * console.log('Selected fragment changed:', state.someFragment);
344
- * }
345
- * );
346
- *
347
- * // To unsubscribe later
348
- * unsubscribe();
349
- * ```
350
- */
351
- <TDerivate>(selector: SelectorCallback<State, TDerivate>, subscription: SubscribeCallback<TDerivate>, config?: SubscribeCallbackConfig<TDerivate>): UnsubscribeCallback;
352
- };
353
- /**
354
- * @description Metadata, non reactive additional information associated with the global state
355
- */
356
- export type BaseMetadata = Record<string, unknown>;
357
- /**
358
- * @description Function to get the metadata
359
- */
360
- export type MetadataGetter<Metadata extends BaseMetadata> = () => Metadata;
361
- /**
362
- * @description Selector function to derive a fragment of the state
363
- */
364
- export type SelectorCallback<State, TDerivate> = (state: State) => TDerivate;
365
- /**
366
- * @description Parameters for the store subscription
367
- */
368
- export type SubscriberParameters = {
369
- selector: SelectorCallback<Any, Any> | undefined;
370
- currentState: unknown;
371
- /**
372
- * @description notification callback
373
- */
374
- onStoreChange: SubscriptionCallback | (() => void);
375
- } & UseHookOptions<Any> & SubscribeCallbackConfig<Any>;
376
- /**
377
- * @description
378
- * This is the final listener of the store changes, it can be a subscription or a setState
379
- * @param {unknown} params - The parameters of the subscription
380
- * @param {unknown} params.state - The new state
381
- * @param {string} params.identifier - Optional identifier for the setState call
382
- */
383
- export type SubscriptionCallback<State = unknown> = (params: {
384
- state: State;
385
- }, args: {
386
- identifier?: string;
387
- }) => void;
388
- export type GlobalStoreContextCallbacks<State, StateMutator, Metadata extends BaseMetadata> = {
389
- /**
390
- * @description Optional callback invoked after the context is created,
391
- */
392
- onCreated?: (
393
- /**
394
- * @description Full context instance
395
- */
396
- storeTools: ContextStoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>,
397
- /**
398
- * @description Underlying store instance
399
- */
400
- store: GlobalStore<State, Metadata, unknown, Any>) => void;
401
- /**
402
- * @description Called when the context provider is mounted
403
- */
404
- onMounted?: (
405
- /**
406
- * @description Full context instance
407
- */
408
- storeTools: ContextStoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>,
409
- /**
410
- * @description Underlying store instance
411
- */
412
- store: GlobalStore<State, Metadata, unknown, Any>) => void | UnsubscribeCallback;
413
- /**
414
- * @description Called synchronously during every Provider render.
415
- *
416
- * Must be idempotent and must not produce external side effects
417
- * or retain references to the provided store.
418
- *
419
- * React may invoke renders that are later discarded.
420
- */
421
- onRender?: (
422
- /**
423
- * @description Full context instance
424
- */
425
- storeTools: ContextStoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>,
426
- /**
427
- * @description Underlying store instance
428
- */
429
- store: GlobalStore<State, Metadata, unknown, Any>) => void;
430
- };
431
- export type ContextStoreCallbacks<State, StateMutator, Metadata extends BaseMetadata> = GlobalStoreCallbacks<State, StateMutator, Metadata> & GlobalStoreContextCallbacks<State, StateMutator, Metadata>;
432
- /**
433
- * @description Resulting type of the action collection configuration
434
- */
435
- export type ContextActionCollectionResult<State, Metadata extends BaseMetadata, ActionsConfig extends ContextActionCollectionConfig<State, Metadata>> = {
436
- [key in keyof ActionsConfig]: {
437
- (...params: Parameters<ActionsConfig[key]>): ReturnType<ReturnType<ActionsConfig[key]>>;
438
- };
439
- };
440
- /**
441
- * contract for the storeActionsConfig configuration
442
- */
443
- export interface ContextActionCollectionConfig<State, Metadata extends BaseMetadata, ThisAPI = Record<string, (...parameters: Any[]) => unknown>> {
444
- readonly [key: string]: {
445
- (this: ThisAPI, ...parameters: Any[]): (this: ThisAPI, storeTools: ContextStoreTools<State, Record<string, (...parameters: Any[]) => unknown | void>, Metadata>) => unknown | void;
446
- };
447
- }
448
- /**
449
- * @description Extensions methods for the context store tools
450
- */
451
- export type ContextStoreToolsExtensions<State, StateMutator, Metadata extends BaseMetadata> = {
452
- /**
453
- * @description Main hook of the context
454
- *
455
- * @example
456
- * ```tsx
457
- * type CounterContext = import('../../stores/counter').CounterContext;
458
- *
459
- * const useLogCount = () => {
460
- * return ({ use }: CounterContext) => {
461
- * const count = use.select(s => s.count);
462
- *
463
- * console.log('Count changed:', count);
464
- * };
465
- * }
466
- *
467
- * // Usage in store
468
- * import useLogCount from './actions/useLogCount';
469
- *
470
- * const counter = createContext({ count: 0 }, {
471
- * actions: {
472
- * useLogCount,
473
- * }
474
- * });
475
- *
476
- * // Usage in component
477
- * import counter from '../stores/counter';
478
- *
479
- * const CounterLogger = () => {
480
- * // access to the actions is NOT-REACTIVE
481
- * const { useLogCount } = counter.use.actions();
482
- *
483
- * useLogCount();
484
- * }
485
- * ```
486
- */
487
- use: ContextHook<State, StateMutator, Metadata>;
488
- };
489
- /**
490
- * @description Store tools specialized for context usage
491
- */
492
- export type ContextStoreTools<State, StateMutator, Metadata extends BaseMetadata> = StoreTools<State, StateMutator, Metadata> & ContextStoreToolsExtensions<State, StateMutator, Metadata>;
493
- /**
494
- * @description Extensions methods for the ContextProvider component
495
- */
496
- export type ContextProviderExtensions<State, StateMutator, Metadata extends BaseMetadata> = {
497
- /**
498
- * Creates a provider wrapper which allows to capture the context value,
499
- * useful for testing purposes.
500
- * @param options configuration options for the provider wrapper
501
- * @param options.value optional initial state or initializer function
502
- * @param options.onCreated optional callback invoked after the context is created
503
- * @returns an object containing the wrapper component and a reference to the context value
504
- */
505
- makeProviderWrapper: (options?: {
506
- /**
507
- * @description Optional initial state or initializer function, useful for testing, storybooks, etc.
508
- */
509
- value?: State | ((initialValue: State) => State);
510
- } & GlobalStoreContextCallbacks<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>) => {
511
- /**
512
- * Provider for the context
513
- */
514
- wrapper: React.FC<PropsWithChildren<{
515
- /**
516
- * @description Optional initial state or initializer function, useful for testing, storybooks, etc.
517
- */
518
- value?: State | ((initialValue: State) => State);
519
- }>>;
520
- /**
521
- * Reference to the current context value
522
- */
523
- context: {
524
- /**
525
- * @description Current context value
526
- */
527
- current: ContextStoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>;
528
- /**
529
- * @description Underlying store instance
530
- */
531
- instance: GlobalStore<State, Metadata, unknown, any>;
532
- };
533
- };
534
- };
535
- /**
536
- * @description Creates a React context provider component for the given global state.
537
- * @param value Optional initial state or initializer function, useful for testing.
538
- * @param onCreated Optional callback invoked after the context is created, receiving the full context instance.
539
- */
540
- export type ContextProvider<State, StateMutator, Metadata extends BaseMetadata> = React.FC<PropsWithChildren<{
541
- /**
542
- * @description Optional initial state or initializer function, useful for testing, storybooks, etc.
543
- */
544
- value?: State | ((initialValue: State) => State);
545
- } & GlobalStoreContextCallbacks<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>>> & ContextProviderExtensions<State, StateMutator, Metadata>;
546
- /**
547
- * @description Represents a hook that returns a readonly state.
548
- */
549
- export interface ReadonlyContextHook<State, StateMutator, Metadata extends BaseMetadata> extends ReadonlyContextPublicApi<State, StateMutator, Metadata> {
550
- /**
551
- * @description Returns the full state.
552
- */
553
- (): State;
554
- /**
555
- * @description Returns a derived value from the state using the provided selector function.
556
- * @param selector A function that selects a part of the state.
557
- * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
558
- * @returns The derived value from the state.
559
- */
560
- <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Derivate;
561
- /**
562
- * @description Returns a derived value from the state using the provided selector function.
563
- * @param selector A function that selects a part of the state.
564
- * @param options Optional configuration for the selector hook.
565
- * @param options.isEqual Optional equality function to compare the selected fragment.
566
- * @param options.isEqualRoot Optional equality function to compare the root state.
567
- * @param options.dependencies Optional array of dependencies to control when the selector is re-evaluated.
568
- * @returns The derived value from the state.
569
- */
570
- <Derivate>(selector: (state: State) => Derivate, options?: UseHookOptions<Derivate, State>): Derivate;
571
- }
572
- /**
573
- * @description Hook for accessing a context's state, mutator (setState or actions), and metadata.
574
- * @returns A read-only tuple containing:
575
- * - state: the current state, or the derived value when a selector is used
576
- * - stateMutator: a function or actions collection to update the state
577
- * - metadata: the current context metadata
578
- *
579
- * @example
580
- * ```tsx
581
- * // Simple usage (full state)
582
- * const [state, setState] = useTodosContext();
583
- *
584
- * // With a selector (preferred for render isolation)
585
- * const [todos, actions] = useTodosContext(s => s.todos);
586
- *
587
- * actions.setTodos(next);
588
- * ```
589
- */
590
- export interface ContextHook<State, StateMutator, Metadata extends BaseMetadata> extends ContextPublicApi<State, StateMutator, Metadata> {
591
- /**
592
- * @description Retrieves the full state, state mutator (setState or actions), and metadata.
593
- */
594
- (): Readonly<[state: State, stateMutator: StateMutator, metadata: Metadata]>;
595
- /**
596
- * @description Retrieves a derived value from the state using the provided selector function.
597
- * @param selector A function that selects a part of the state.
598
- * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
599
- * @returns A read-only tuple containing the derived state, state mutator (setState or actions), and metadata.
600
- */
601
- <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
602
- /**
603
- * @description Retrieves a derived value from the state using the provided selector function.
604
- * @param selector A function that selects a part of the state.
605
- * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
606
- * @returns A read-only tuple containing the derived state, state mutator (setState or actions), and metadata.
607
- */
608
- <Derivate>(selector: (state: State) => Derivate, config?: UseHookOptions<Derivate, State>): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
609
- }
610
- export type ContextPublicApi<State, StateMutator, Metadata extends BaseMetadata> = {
611
- /**
612
- * @description [NOT A HOOK, NON-REACTIVE]
613
- * Creates a derived hook that subscribes to a selected fragment of the context state.
614
- * The selector determines which portion of the state the new hook exposes.
615
- * This hook must be used within the corresponding context provider.
616
- *
617
- * @param selector A function that selects a part of the state.
618
- * @param args Optional configuration for the derived hook, including:
619
- * - isEqual: A function to compare the current and next selected fragment for equality.
620
- * - isEqualRoot: A function to compare the entire state for equality.
621
- * - name: An optional name for debugging purposes.
622
- * @returns A new context hook that provides access to the selected fragment of the state,
623
- * along with the state mutator and metadata.
624
- *
625
- * @example
626
- * ```tsx
627
- * const useTodos = createContext({
628
- * todos: [],
629
- * filter: '',
630
- * }, {
631
- * actions: {
632
- * setFilter(filter: string) {
633
- * ...
634
- * });
635
- *
636
- * const useFilter = useTodos.createSelectorHook((state) => {
637
- * return state.filter;
638
- * });
639
- *
640
- * function FilterComponent() {
641
- * // The selector only listen to the selected fragment (filter)
642
- * // But has access to the full actions collection
643
- * const [filter, { setFilter }] = useFilter();
644
- *
645
- * return (
646
- * <input
647
- * value={filter}
648
- * onChange={(e) => setFilter(e.target.value)}
649
- * />
650
- * );
651
- * }
652
- * ```
653
- */
654
- createSelectorHook: <Derivate>(this: ReadonlyContextPublicApi<State, StateMutator, Metadata>, selector: (state: State) => Derivate, args?: Omit<UseHookOptions<Derivate, State>, 'dependencies'> & {
655
- name?: string;
656
- }) => ReadonlyContextHook<Derivate, StateMutator, Metadata>;
657
- /**
658
- * @description [NON-REACTIVE]
659
- * Hook that provides non-reactive access to the context API.
660
- * This allows direct interaction with the context’s state, metadata, and actions
661
- * without triggering component re-renders.
662
- * @returns An object containing the context API methods and properties.
663
- */
664
- api: () => StateApi<State, StateMutator, Metadata>;
665
- /**
666
- * @description [NON-REACTIVE]
667
- * Provides direct access to the context's actions, if available.
668
- */
669
- actions: () => StateMutator extends AnyFunction ? null : StateMutator;
670
- /**
671
- * @description Selects a fragment of the state using the provided selector function.
672
- */
673
- select: SelectHook<State>;
674
- /**
675
- * @description
676
- * Creates a hook that allows you to subscribe to a fragment of the state
677
- * The observable selection will notify the subscribers only if the fragment changes and the equality function returns false
678
- * you can customize the equality function by passing the isEqualRoot and isEqual parameters
679
- *
680
- * @example
681
- * ```tsx
682
- * const observable = store.use.observable(state => state.count);
683
- *
684
- * useEffect(() => {
685
- * const unsubscribe = observable.subscribe(() => {
686
- * // do something when the selected fragment changes
687
- * });
688
- *
689
- * return () => {
690
- * unsubscribe();
691
- * };
692
- * }, [observable]);
693
- * ```
694
- */
695
- observable: <Selection>(selector: (state: State) => Selection, args?: {
696
- isEqual?: (current: Selection, next: Selection) => boolean;
697
- isEqualRoot?: (current: State, next: State) => boolean;
698
- /**
699
- * @description Name of the observable fragment for debugging purposes
700
- */
701
- name?: string;
702
- }) => ObservableFragment<Selection, StateMutator, Metadata>;
703
- /**
704
- * @description display name for debugging purposes
705
- */
706
- readonly displayName: string;
707
- };
708
- /**
709
- * @description Readonly version of the ContextPublicApi, expose by selectors and observables
710
- */
711
- export type ReadonlyContextPublicApi<State, StateMutator, Metadata extends BaseMetadata> = Pick<ContextPublicApi<State, StateMutator, Metadata>, 'createSelectorHook' | 'displayName'> & {
712
- /**
713
- * @description Hook that provides non-reactive access to the context API.
714
- * This allows direct interaction with the context’s state, metadata, and actions
715
- * without triggering component re-renders.
716
- * @returns An object containing the context API methods and properties.
717
- */
718
- api: () => ReadonlyStateApi<State, StateMutator, Metadata>;
719
- };
720
- export interface CreateContext {
721
- /**
722
- * @description Creates a highly granular React context with its associated provider and state hook.
723
- * @param value Initial state value or initializer function.
724
- * @returns An object containing:
725
- * - **`use`** — A custom hook to read and mutate the context state.
726
- * Supports selectors for granular subscriptions and returns `[state, stateMutator, metadata]`.
727
- * - **`Provider`** — A React component that provides the context to its descendants.
728
- * It accepts an optional initial value and `onCreated` callback.
729
- * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
730
- * external tools or non-React consumers.
731
- */
732
- <State, StateMutator = React.Dispatch<React.SetStateAction<State>>>(value: State | (() => State)): {
733
- /**
734
- * @description Hook and API for interacting with the context.
735
- * This hook provides access to the context state, actions, and metadata.
736
- *
737
- * There are two ways to use the hook
738
- * @example
739
- * The more simple and familiar way is to use it as a regular hook
740
- *
741
- * ```tsx
742
- * const { Context, Provider, user: useUser} = createContext({ name: 'John', age: 30 });
743
- *
744
- * function UserProfile() {
745
- * const [state, setState, metadata] = useUser();
746
- *
747
- * ....
748
- * }
749
- * ```
750
- *
751
- * @example
752
- * The recommended, more sematic and easier to read way:
753
- *
754
- * ```tsx
755
- * const user = createContext({ name: 'John', age: 30 });
756
- *
757
- * <user.Provider>
758
- * <UserProfile />
759
- * </user.Provider>
760
- *
761
- * function UserProfile() {
762
- * const [state, setState, metadata] = user.use();
763
- * const userContext = user.use.api();
764
- * const userName = user.use.select(s => s.name);
765
- * // ...
766
- * }
767
- */
768
- use: ContextHook<State, StateMutator, BaseMetadata>;
769
- /**
770
- * @description Provider for the context
771
- */
772
- Provider: ContextProvider<State, StateMutator, BaseMetadata>;
773
- /**
774
- * @description The raw React Context object
775
- */
776
- Context: ReactContext<ContextHook<State, StateMutator, BaseMetadata> | null>;
777
- };
778
- /**
779
- * @description Creates a highly granular React context with its associated provider and state hook.
780
- * @param value Initial state value or initializer function.
781
- * @param args Additional configuration for the context.
782
- * @param args.name Optional name for debugging purposes.
783
- * @param args.metadata Optional non-reactive metadata associated with the state.
784
- * @param args.callbacks Optional lifecycle callbacks for the context.
785
- * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
786
- * @returns An object containing:
787
- * - **`use`** — A custom hook to read and mutate the context state.
788
- * Supports selectors for granular subscriptions and returns `[state, stateMutator, metadata]`.
789
- * - **`Provider`** — A React component that provides the context to its descendants.
790
- * It accepts an optional initial value and `onCreated` callback.
791
- * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
792
- * external tools or non-React consumers.
793
- */
794
- <State, Metadata extends BaseMetadata, ActionsConfig extends ContextActionCollectionConfig<State, Metadata> | null | {}, StateMutator = keyof ActionsConfig extends never | undefined ? React.Dispatch<React.SetStateAction<State>> : ContextActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(
795
- /**
796
- * @description Initial state value or initializer function.
797
- */
798
- value: State | (() => State),
799
- /**
800
- * @description Additional configuration for the context.
801
- * @param args.name Optional name for debugging purposes.
802
- * @param args.metadata Optional non-reactive metadata associated with the state.
803
- * @param args.callbacks Optional lifecycle callbacks for the context.
804
- * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
805
- */
806
- args: {
807
- name?: string;
808
- metadata?: Metadata | (() => Metadata);
809
- callbacks?: ContextStoreCallbacks<Any, AnyActions, Any>;
810
- actions?: ActionsConfig;
811
- }): {
812
- /**
813
- * @description Hook and API for interacting with the context.
814
- * This hook provides access to the context state, actions, and metadata.
815
- *
816
- * There are two ways to use the hook
817
- * @example
818
- * The more simple and familiar way is to use it as a regular hook
819
- *
820
- * ```tsx
821
- * const { Context, Provider, user: useUser} = createContext({ name: 'John', age: 30 });
822
- *
823
- * function UserProfile() {
824
- * const [state, setState, metadata] = useUser();
825
- *
826
- * ....
827
- * }
828
- * ```
829
- *
830
- * @example
831
- * The recommended, more sematic and easier to read way:
832
- *
833
- * ```tsx
834
- * const user = createContext({ name: 'John', age: 30 });
835
- *
836
- * <user.Provider>
837
- * <UserProfile />
838
- * </user.Provider>
839
- *
840
- * function UserProfile() {
841
- * const [state, setState, metadata] = user.use();
842
- * const userContext = user.use.api();
843
- * const userName = user.use.select(s => s.name);
844
- * // ...
845
- * }
846
- */
847
- use: ContextHook<State, StateMutator, Metadata>;
848
- /**
849
- * @description Provider for the context
850
- */
851
- Provider: ContextProvider<State, StateMutator, Metadata>;
852
- /**
853
- * @description Raw React Context object
854
- */
855
- Context: ReactContext<ContextHook<State, StateMutator, Metadata> | null>;
856
- };
857
- /**
858
- * @description Creates a highly granular React context with its associated provider and state hook.
859
- * @param value Initial state value or initializer function.
860
- * @param args Additional configuration for the context.
861
- * @param args.name Optional name for debugging purposes.
862
- * @param args.metadata Optional non-reactive metadata associated with the state.
863
- * @param args.callbacks Optional lifecycle callbacks for the context.
864
- * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
865
- * @returns An object containing:
866
- * - **`use`** — A custom hook to read and mutate the context state.
867
- * Supports selectors for granular subscriptions and returns `[state, stateMutator, metadata]`.
868
- * - **`Provider`** — A React component that provides the context to its descendants.
869
- * It accepts an optional initial value and `onCreated` callback.
870
- * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
871
- * external tools or non-React consumers.
872
- */
873
- <State, Metadata extends BaseMetadata, ActionsConfig extends ContextActionCollectionConfig<State, Metadata>>(
874
- /**
875
- * @description Initial state value or initializer function.
876
- */
877
- value: State | (() => State),
878
- /**
879
- * @description Additional configuration for the context.
880
- * @param args.name Optional name for debugging purposes.
881
- * @param args.metadata Optional non-reactive metadata associated with the state.
882
- * @param args.callbacks Optional lifecycle callbacks for the context.
883
- * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
884
- */
885
- args: {
886
- name?: string;
887
- metadata?: Metadata | (() => Metadata);
888
- callbacks?: ContextStoreCallbacks<Any, AnyActions, Any>;
889
- actions: ActionsConfig;
890
- }): {
891
- /**
892
- * @description Hook and API for interacting with the context.
893
- * This hook provides access to the context state, actions, and metadata.
894
- *
895
- * There are two ways to use the hook
896
- * @example
897
- * The more simple and familiar way is to use it as a regular hook
898
- *
899
- * ```tsx
900
- * const { Context, Provider, user: useUser} = createContext({ name: 'John', age: 30 });
901
- *
902
- * function UserProfile() {
903
- * const [state, setState, metadata] = useUser();
904
- *
905
- * ....
906
- * }
907
- * ```
908
- *
909
- * @example
910
- * The recommended, more sematic and easier to read way:
911
- *
912
- * ```tsx
913
- * const user = createContext({ name: 'John', age: 30 });
914
- *
915
- * <user.Provider>
916
- * <UserProfile />
917
- * </user.Provider>
918
- *
919
- * function UserProfile() {
920
- * const [state, setState, metadata] = user.use();
921
- * const userContext = user.use.api();
922
- * const userName = user.use.select(s => s.name);
923
- * // ...
924
- * }
925
- */
926
- use: ContextHook<State, ContextActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
927
- /**
928
- * @description Provider for the context
929
- */
930
- Provider: ContextProvider<State, ContextActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
931
- /**
932
- * @description Raw React Context object
933
- */
934
- Context: ReactContext<ContextHook<State, ContextActionCollectionResult<State, Metadata, ActionsConfig>, Metadata> | null>;
935
- };
936
- }
937
- /**
938
- * @description Infers the context API type
939
- *
940
- * @example
941
- * ```ts
942
- * const counter = createContext(0);
943
- *
944
- * type CounterContextApi = InferContextApi<typeof counter.Context>;
945
- *
946
- * // Equivalent to:
947
- * ContextApi<number, React.Dispatch<React.SetStateAction<number>>, BaseMetadata>;
948
- * ```
949
- */
950
- export type InferContextApi<Context extends ReactContext<ContextHook<Any, Any, Any> | null>> = NonNullable<React.ContextType<Context>> extends ContextHook<infer State, infer StateMutator, infer Metadata> ? ContextStoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata> : never;
951
- /**
952
- * Typescript is unable to infer the actions type correctly for the lifecycle callbacks
953
- * so we use a generic AnyActions type here to bypass that limitation.
954
- *
955
- * The parameter could still be typed before using it with
956
- * ```ts
957
- * type StoreTools = InferStateApi<typeof <hook>>;
958
- *
959
- * onInit: (tools) => {
960
- * const storeTools = tools as StoreTools;
961
- * // ...
962
- * }
963
- *
964
- * or when dealing with context:
965
- *
966
- * type ContextApi = InferContextApi<typeof <context>>;
967
- *
968
- * onInit: (tools) => {
969
- * const storeTools = tools as ContextApi;
970
- * // ...
971
- * }
972
- * ```
973
- */
974
- export type AnyActions = Record<string, (...args: Any[]) => Any>;
975
- export interface CreateGlobalState {
976
- /**
977
- * Creates a global state hook.
978
- * @param state initial state value or a callback function that returns the initial state
979
- * @returns a state hook for your components
980
- *
981
- * @example
982
- * ```tsx
983
- * const useCounter = createGlobalState(0);
984
- *
985
- * function Counter() {
986
- * const [count, setCount] = useCounter();
987
- * return (
988
- * <div>
989
- * <p>Count: {count}</p>
990
- * <button onClick={() =>
991
- * setCount(prev => prev + 1)
992
- * }>Increment</button>
993
- * </div>
994
- * );
995
- * }
996
- * ```
997
- *
998
- * @example Using a callback to initialize state
999
- * ```tsx
1000
- * const useCounter = createGlobalState(() => {
1001
- * // Expensive computation or conditional logic
1002
- * return localStorage.getItem('count') ? parseInt(localStorage.getItem('count')) : 0;
1003
- * });
1004
- * ```
1005
- *
1006
- * @example You can also use a more semantic and declarative approach
1007
- * ```tsx
1008
- * const counter = createGlobalState(0);
1009
- *
1010
- * function Counter() {
1011
- * const [count, setCount] = counter.use();
1012
- * const count = counter.use.select();
1013
- *
1014
- * counter.setState(prev => prev + 1);
1015
- *
1016
- * // if you have actions
1017
- * counter.actions.someAction();
1018
- * ```
1019
- */
1020
- <State>(state: State | (() => State)): StateHook<State, React.Dispatch<React.SetStateAction<State>>, BaseMetadata>;
1021
- /**
1022
- * Creates a global state hook that you can use across your application
1023
- * @param state initial state value or a callback function that returns the initial state
1024
- * @param args additional configuration for the global state
1025
- * @param args.name optional name for debugging purposes
1026
- * @param args.metadata optional non-reactive metadata associated with the state (can be a value or callback)
1027
- * @param args.callbacks optional lifecycle callbacks for the global state
1028
- * @param args.actions optional actions to restrict state mutations [if provided `setState` will be nullified]
1029
- * @returns a state hook that you can use in your components
1030
- *
1031
- * @example
1032
- * ```tsx
1033
- * const useCounter = createGlobalState(0, {
1034
- * actions: {
1035
- * increase() {
1036
- * return ({ setState }) => {
1037
- * setState((c) => c + 1);
1038
- * };
1039
- * },
1040
- * decrease(amount: number) {
1041
- * return ({ setState }) => {
1042
- * setState((c) => c - amount);
1043
- * };
1044
- * },
1045
- * },
1046
- * });
1047
- *
1048
- * function Counter() {
1049
- * const [count, {
1050
- * increase,
1051
- * decrease
1052
- * }] = useCounter();
1053
- *
1054
- * return (
1055
- * <div>
1056
- * <p>Count: {count}</p>
1057
- * <button onClick={increase}>
1058
- * Increment
1059
- * </button>
1060
- * <button onClick={() => {
1061
- * decrease(1);
1062
- * }}>
1063
- * Decrement
1064
- * </button>
1065
- * </div>
1066
- * );
1067
- * }
1068
- * ```
1069
- *
1070
- * @example Using callbacks for state and metadata initialization
1071
- * ```tsx
1072
- * const useAuth = createGlobalState(
1073
- * () => ({ user: null, token: localStorage.getItem('token') }),
1074
- * {
1075
- * metadata: () => ({ createdAt: Date.now() }),
1076
- * }
1077
- * );
1078
- * ```
1079
- */
1080
- <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata> | null | {}, PublicStateMutator = keyof ActionsConfig extends never | undefined ? React.Dispatch<React.SetStateAction<State>> : ActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(state: State | (() => State), args: {
1081
- name?: string;
1082
- metadata?: Metadata | (() => Metadata);
1083
- callbacks?: GlobalStoreCallbacks<Any, AnyActions, Any>;
1084
- actions?: ActionsConfig;
1085
- }): StateHook<State, PublicStateMutator, Metadata>;
1086
- /**
1087
- * Creates a global state hook that you can use across your application
1088
- * @param state initial state value or a callback function that returns the initial state
1089
- * @param args additional configuration for the global state
1090
- * @param args.name optional name for debugging purposes
1091
- * @param args.metadata optional non-reactive metadata associated with the state (can be a value or callback)
1092
- * @param args.callbacks optional lifecycle callbacks for the global state
1093
- * @param args.actions optional actions to restrict state mutations [if provided `setState` will be nullified]
1094
- * @returns a state hook that you can use in your components
1095
- *
1096
- * @example
1097
- * ```tsx
1098
- * const useCounter = createGlobalState(0, {
1099
- * actions: {
1100
- * increase() {
1101
- * return ({ setState }) => {
1102
- * setState((c) => c + 1);
1103
- * };
1104
- * },
1105
- * decrease(amount: number) {
1106
- * return ({ setState }) => {
1107
- * setState((c) => c - amount);
1108
- * };
1109
- * },
1110
- * },
1111
- * });
1112
- *
1113
- * function Counter() {
1114
- * const [count, {
1115
- * increase,
1116
- * decrease
1117
- * }] = useCounter();
1118
- *
1119
- * return (
1120
- * <div>
1121
- * <p>Count: {count}</p>
1122
- * <button onClick={increase}>
1123
- * Increment
1124
- * </button>
1125
- * <button onClick={() => {
1126
- * decrease(1);
1127
- * }}>
1128
- * Decrement
1129
- * </button>
1130
- * </div>
1131
- * );
1132
- * }
1133
- * ```
1134
- */
1135
- <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>, PublicStateMutator = ActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(state: State | (() => State), args: {
1136
- name?: string;
1137
- metadata?: Metadata | (() => Metadata);
1138
- callbacks?: GlobalStoreCallbacks<Any, AnyActions, Any>;
1139
- actions: ActionsConfig;
1140
- }): StateHook<State, PublicStateMutator, Metadata>;
1141
- }
1142
- /**
1143
- * Infers the actions type from a StateHook
1144
- * @example
1145
- * ```ts
1146
- * type CounterActions = InferActionsType<typeof useCounter>;
1147
- * ```
1148
- */
1149
- export type InferActionsType<Hook extends StateHook<Any, Any, Any>> = ReturnType<Hook>['1'];
1150
- /**
1151
- * Infers the StoreTools type from a StateHook, useful to split actions code
1152
- *
1153
- * @example
1154
- * ```ts
1155
- * type CounterStoreTools = InferStateApi<typeof useCounter>;
1156
- * ```
1157
- */
1158
- export type InferStateApi<Hook extends StateHook<Any, Any, Any>> = Hook extends StateHook<infer State, infer PublicStateMutator, infer Metadata> ? StoreTools<State, PublicStateMutator, Metadata> : never;
1159
- /**
1160
- * Branded unique identifier
1161
- */
1162
- export type BrandedId<T extends string | undefined> = `${T extends string ? T : ''}${string}` & {
1163
- __brand: T;
1164
- };
1165
- export interface UniqueId {
1166
- /**
1167
- * Generates a unique identifier string, optionally prefixed.
1168
- *
1169
- * @example
1170
- * uniqueId(); // "k9j3n5x8q2"
1171
- * type Id1 = `${string}` & { __brand: undefined };
1172
- *
1173
- * uniqueId('user:'); // "user:k9j3n5x8q2"
1174
- * type Id2 = `user:${string}` & { __brand: 'user:' };
1175
- */
1176
- <T extends string | undefined>(prefix?: T): BrandedId<T>;
1177
- /**
1178
- * Creates a reusable unique ID generator for a specific prefix.
1179
- *
1180
- * @example
1181
- * const makeOrderId = uniqueId.for('order:');
1182
- * const id = makeOrderId(); // "order:k9j3n5x8q2"
1183
- * type OrderId = `order:${string}` & { __brand: 'order:' };
1184
- */
1185
- for<T extends string>(prefix: T): {
1186
- (): `${T}${string}` & {
1187
- __brand: T;
1188
- };
1189
- /**
1190
- * Checks if the given value matches the branded ID for this prefix.
1191
- */
1192
- is(value: unknown): value is `${T}${string}` & {
1193
- __brand: T;
1194
- };
1195
- /**
1196
- * Asserts that the value matches this branded ID, throws otherwise.
1197
- */
1198
- assert(value: unknown): asserts value is `${T}${string}` & {
1199
- __brand: T;
1200
- };
1201
- /**
1202
- * Returns a strictly branded generator using a custom symbol brand.
1203
- */
1204
- strict<Brand extends symbol>(): {
1205
- (): `${T}${string}` & {
1206
- __brand: Brand;
1207
- };
1208
- is(value: unknown): value is `${T}${string}` & {
1209
- __brand: Brand;
1210
- };
1211
- assert(value: unknown): asserts value is `${T}${string}` & {
1212
- __brand: Brand;
1213
- };
1214
- };
1215
- };
1216
- /**
1217
- * Creates a reusable unique ID generator without a prefix.
1218
- */
1219
- of<T extends string>(): () => string & {
1220
- __brand: T;
1221
- };
1222
- /**
1223
- * Creates a strictly branded unique ID generator without a prefix.
1224
- */
1225
- strict<Brand extends symbol>(): () => string & {
1226
- __brand: Brand;
1227
- };
1228
- }
1229
- /**
1230
- * Infers the appropriate API of the store
1231
- */
1232
- export type InferAPI<T> = T extends React.Context<Any> ? InferContextApi<T> : T extends StateHook<Any, Any, Any> ? InferStateApi<T> : T extends {
1233
- Context: React.Context<Any>;
1234
- } ? InferContextApi<T['Context']> : never;
1235
- export type DerivedActionsConfig<ParentApi extends StoreTools<Any, Any, Any>> = {
1236
- readonly [key: string]: {
1237
- (...parameters: Any[]): (storeTools: StoreTools<ReturnType<ParentApi['getState']>, ParentApi['actions'], ReturnType<ParentApi['getMetadata']>>) => Any;
1238
- };
1239
- };
1240
- export type DerivedActionsBuilder<ParentApi extends StoreTools<Any, Any, Any>> = {
1241
- /**
1242
- * @description
1243
- *
1244
- */
1245
- <ActionsConfig extends {
1246
- readonly [key: string]: {
1247
- (...parameters: Any[]): (storeTools: StoreTools<ReturnType<ParentApi['getState']>, ParentApi['actions'], ReturnType<ParentApi['getMetadata']>>) => Any;
1248
- };
1249
- }>(actions: ActionsConfig): (api: StoreTools<Any, Any, Any>) => ActionCollectionResult<ReturnType<ParentApi['getState']>, ReturnType<ParentApi['getMetadata']>, ActionsConfig>;
1250
- };