react-hooks-global-states 11.0.0 → 12.0.0

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.
@@ -1,17 +1,9 @@
1
1
  import React, { type PropsWithChildren, Context as ReactContext } from 'react';
2
- import type { ActionCollectionConfig, ActionCollectionResult, BaseMetadata, MetadataSetter, GlobalStoreCallbacks, UseHookConfig, SubscribeToState, AnyFunction } from './types';
2
+ import type { ActionCollectionConfig, ActionCollectionResult, BaseMetadata, GlobalStoreCallbacks, UseHookOptions, AnyFunction, StateApi, StoreTools, ReadonlyStateApi, SelectHook, ObservableFragment } from './types';
3
3
  /**
4
- * @description Context API
4
+ * @description Extensions methods for the ContextProvider component
5
5
  */
6
- export type ContextApi<State, Actions, Metadata extends BaseMetadata> = {
7
- actions: Actions;
8
- getMetadata: () => Metadata;
9
- getState: () => State;
10
- setMetadata: MetadataSetter<Metadata>;
11
- setState: React.Dispatch<React.SetStateAction<State>>;
12
- subscribe: SubscribeToState<State>;
13
- };
14
- export type ContextProviderExtensions<State, Actions, Metadata extends BaseMetadata> = {
6
+ export type ContextProviderExtensions<State, StateMutator, Metadata extends BaseMetadata> = {
15
7
  /**
16
8
  * Creates a provider wrapper which allows to capture the context value,
17
9
  * useful for testing purposes.
@@ -21,20 +13,36 @@ export type ContextProviderExtensions<State, Actions, Metadata extends BaseMetad
21
13
  * @returns an object containing the wrapper component and a reference to the context value
22
14
  */
23
15
  makeProviderWrapper: (options?: {
16
+ /**
17
+ * @description Optional initial state or initializer function, useful for testing, storybooks, etc.
18
+ */
24
19
  value?: State | ((initialValue: State) => State);
25
- onCreated?: (context: ContextApi<State, Actions, Metadata>) => void;
20
+ /**
21
+ * @description Optional callback invoked after the context is created,
22
+ */
23
+ onCreated?: (
24
+ /**
25
+ * @description Full context instance
26
+ */
27
+ context: StoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>) => void;
26
28
  }) => {
27
29
  /**
28
30
  * Provider for the context
29
31
  */
30
32
  wrapper: React.FC<PropsWithChildren<{
33
+ /**
34
+ * @description Optional initial state or initializer function, useful for testing, storybooks, etc.
35
+ */
31
36
  value?: State | ((initialValue: State) => State);
32
37
  }>>;
33
38
  /**
34
39
  * Reference to the current context value
35
40
  */
36
41
  context: {
37
- current: ContextApi<State, Actions, Metadata>;
42
+ /**
43
+ * @description Current context value
44
+ */
45
+ current: StoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>;
38
46
  };
39
47
  };
40
48
  };
@@ -43,29 +51,45 @@ export type ContextProviderExtensions<State, Actions, Metadata extends BaseMetad
43
51
  * @param value Optional initial state or initializer function, useful for testing.
44
52
  * @param onCreated Optional callback invoked after the context is created, receiving the full context instance.
45
53
  */
46
- export type ContextProvider<State, Actions, Metadata extends BaseMetadata> = React.FC<PropsWithChildren<{
54
+ export type ContextProvider<State, StateMutator, Metadata extends BaseMetadata> = React.FC<PropsWithChildren<{
55
+ /**
56
+ * @description Optional initial state or initializer function, useful for testing, storybooks, etc.
57
+ */
47
58
  value?: State | ((initialValue: State) => State);
48
- onCreated?: (context: ContextApi<State, Actions, Metadata>) => void;
49
- }>> & ContextProviderExtensions<State, Actions, Metadata>;
50
- export interface ContextBaseHook<State, StateMutator, Metadata extends BaseMetadata> {
51
59
  /**
52
- * @description Retrieves the full state, state mutator (setState or actions), and metadata.
60
+ * @description Optional callback invoked after the context is created,
53
61
  */
54
- (): Readonly<[state: State, stateMutator: StateMutator, metadata: Metadata]>;
62
+ onCreated?: (
55
63
  /**
56
- * @description Retrieves a derived value from the state using the provided selector function.
64
+ * @description Full context instance
65
+ */
66
+ context: StoreTools<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata>) => void;
67
+ }>> & ContextProviderExtensions<State, StateMutator, Metadata>;
68
+ /**
69
+ * @description Represents a hook that returns a readonly state.
70
+ */
71
+ interface ReadonlyContextHook<State, StateMutator, Metadata extends BaseMetadata> extends ReadonlyContextPublicApi<State, StateMutator, Metadata> {
72
+ /**
73
+ * @description Returns the full state.
74
+ */
75
+ (): State;
76
+ /**
77
+ * @description Returns a derived value from the state using the provided selector function.
57
78
  * @param selector A function that selects a part of the state.
58
79
  * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
59
- * @returns A read-only tuple containing the derived state, state mutator (setState or actions), and metadata.
80
+ * @returns The derived value from the state.
60
81
  */
61
- <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
82
+ <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Derivate;
62
83
  /**
63
- * @description Retrieves a derived value from the state using the provided selector function.
84
+ * @description Returns a derived value from the state using the provided selector function.
64
85
  * @param selector A function that selects a part of the state.
65
- * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
66
- * @returns A read-only tuple containing the derived state, state mutator (setState or actions), and metadata.
86
+ * @param options Optional configuration for the selector hook.
87
+ * @param options.isEqual Optional equality function to compare the selected fragment.
88
+ * @param options.isEqualRoot Optional equality function to compare the root state.
89
+ * @param options.dependencies Optional array of dependencies to control when the selector is re-evaluated.
90
+ * @returns The derived value from the state.
67
91
  */
68
- <Derivate>(selector: (state: State) => Derivate, config?: UseHookConfig<Derivate, State>): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
92
+ <Derivate>(selector: (state: State) => Derivate, options?: UseHookOptions<Derivate, State>): Derivate;
69
93
  }
70
94
  /**
71
95
  * @description Hook for accessing a context's state, mutator (setState or actions), and metadata.
@@ -85,11 +109,30 @@ export interface ContextBaseHook<State, StateMutator, Metadata extends BaseMetad
85
109
  * actions.setTodos(next);
86
110
  * ```
87
111
  */
88
- export interface ContextHook<State, StateMutator, Metadata extends BaseMetadata> extends HookExtensions<State, StateMutator, Metadata>, ContextBaseHook<State, StateMutator, Metadata> {
112
+ export interface ContextHook<State, StateMutator, Metadata extends BaseMetadata> extends ContextPublicApi<State, StateMutator, Metadata> {
113
+ /**
114
+ * @description Retrieves the full state, state mutator (setState or actions), and metadata.
115
+ */
116
+ (): Readonly<[state: State, stateMutator: StateMutator, metadata: Metadata]>;
117
+ /**
118
+ * @description Retrieves a derived value from the state using the provided selector function.
119
+ * @param selector A function that selects a part of the state.
120
+ * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
121
+ * @returns A read-only tuple containing the derived state, state mutator (setState or actions), and metadata.
122
+ */
123
+ <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
124
+ /**
125
+ * @description Retrieves a derived value from the state using the provided selector function.
126
+ * @param selector A function that selects a part of the state.
127
+ * @param dependencies Optional array of dependencies to control when the selector is re-evaluated.
128
+ * @returns A read-only tuple containing the derived state, state mutator (setState or actions), and metadata.
129
+ */
130
+ <Derivate>(selector: (state: State) => Derivate, config?: UseHookOptions<Derivate, State>): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
89
131
  }
90
- export type HookExtensions<State, StateMutator, Metadata extends BaseMetadata> = {
132
+ export type ContextPublicApi<State, StateMutator, Metadata extends BaseMetadata> = {
91
133
  /**
92
- * @description Creates a derived hook that subscribes to a selected fragment of the context state.
134
+ * @description [NOT A HOOK, NON-REACTIVE]
135
+ * Creates a derived hook that subscribes to a selected fragment of the context state.
93
136
  * The selector determines which portion of the state the new hook exposes.
94
137
  * This hook must be used within the corresponding context provider.
95
138
  *
@@ -130,16 +173,67 @@ export type HookExtensions<State, StateMutator, Metadata extends BaseMetadata> =
130
173
  * }
131
174
  * ```
132
175
  */
133
- createSelectorHook: <Derivate>(this: ContextHook<State, StateMutator, Metadata>, selector: (state: State) => Derivate, args?: Omit<UseHookConfig<Derivate, State>, 'dependencies'> & {
176
+ createSelectorHook: <Derivate>(this: ReadonlyContextPublicApi<State, StateMutator, Metadata>, selector: (state: State) => Derivate, args?: Omit<UseHookOptions<Derivate, State>, 'dependencies'> & {
134
177
  name?: string;
135
- }) => ContextBaseHook<Derivate, StateMutator, Metadata>;
178
+ }) => ReadonlyContextHook<Derivate, StateMutator, Metadata>;
179
+ /**
180
+ * @description [NON-REACTIVE]
181
+ * Hook that provides non-reactive access to the context API.
182
+ * This allows direct interaction with the context’s state, metadata, and actions
183
+ * without triggering component re-renders.
184
+ * @returns An object containing the context API methods and properties.
185
+ */
186
+ api: () => StateApi<State, StateMutator, Metadata>;
187
+ /**
188
+ * @description [NON-REACTIVE]
189
+ * Provides direct access to the context's actions, if available.
190
+ */
191
+ actions: () => StateMutator extends AnyFunction ? null : StateMutator;
192
+ /**
193
+ * @description Selects a fragment of the state using the provided selector function.
194
+ */
195
+ select: SelectHook<State>;
196
+ /**
197
+ * @description
198
+ * Creates a hook that allows you to subscribe to a fragment of the state
199
+ * The observable selection will notify the subscribers only if the fragment changes and the equality function returns false
200
+ * you can customize the equality function by passing the isEqualRoot and isEqual parameters
201
+ *
202
+ * @example
203
+ * ```tsx
204
+ * const observable = store.use.observable(state => state.count);
205
+ *
206
+ * useEffect(() => {
207
+ * const unsubscribe = observable.subscribe(() => {
208
+ * // do something when the selected fragment changes
209
+ * });
210
+ *
211
+ * return () => {
212
+ * unsubscribe();
213
+ * };
214
+ * }, [observable]);
215
+ * ```
216
+ */
217
+ observable: <Selection>(selector: (state: State) => Selection, args?: {
218
+ isEqual?: (current: Selection, next: Selection) => boolean;
219
+ isEqualRoot?: (current: State, next: State) => boolean;
220
+ /**
221
+ * @description Name of the observable fragment for debugging purposes
222
+ */
223
+ name?: string;
224
+ }) => ObservableFragment<Selection, StateMutator, Metadata>;
225
+ };
226
+ /**
227
+ * @description Readonly version of the ContextPublicApi, expose by selectors and observables
228
+ */
229
+ export type ReadonlyContextPublicApi<State, StateMutator, Metadata extends BaseMetadata> = Pick<ContextPublicApi<State, StateMutator, Metadata>, 'createSelectorHook'> & {
136
230
  /**
137
231
  * @description Hook that provides non-reactive access to the context API.
138
232
  * This allows direct interaction with the context’s state, metadata, and actions
139
233
  * without triggering component re-renders.
140
234
  * @returns An object containing the context API methods and properties.
141
235
  */
142
- api: () => ContextApi<State, StateMutator, Metadata>;
236
+ api: () => ReadonlyStateApi<State, StateMutator, Metadata>;
143
237
  };
144
238
  interface CreateContext {
145
239
  /**
@@ -153,10 +247,51 @@ interface CreateContext {
153
247
  * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
154
248
  * external tools or non-React consumers.
155
249
  */
156
- <State>(value: State | (() => State)): {
157
- use: ContextHook<State, React.Dispatch<React.SetStateAction<State>>, BaseMetadata>;
158
- Provider: ContextProvider<State, null, BaseMetadata>;
159
- Context: ReactContext<ContextHook<State, React.Dispatch<React.SetStateAction<State>>, BaseMetadata> | null>;
250
+ <State, StateMutator = React.Dispatch<React.SetStateAction<State>>>(value: State | (() => State)): {
251
+ /**
252
+ * @description Hook and API for interacting with the context.
253
+ * This hook provides access to the context state, actions, and metadata.
254
+ *
255
+ * There are two ways to use the hook
256
+ * @example
257
+ * The more simple and familiar way is to use it as a regular hook
258
+ *
259
+ * ```tsx
260
+ * const { Context, Provider, user: useUser} = createContext({ name: 'John', age: 30 });
261
+ *
262
+ * function UserProfile() {
263
+ * const [state, setState, metadata] = useUser();
264
+ *
265
+ * ....
266
+ * }
267
+ * ```
268
+ *
269
+ * @example
270
+ * The recommended, more sematic and easier to read way:
271
+ *
272
+ * ```tsx
273
+ * const user = createContext({ name: 'John', age: 30 });
274
+ *
275
+ * <user.Provider>
276
+ * <UserProfile />
277
+ * </user.Provider>
278
+ *
279
+ * function UserProfile() {
280
+ * const [state, setState, metadata] = user.use();
281
+ * const userContext = user.use.api();
282
+ * const userName = user.use.select(s => s.name);
283
+ * // ...
284
+ * }
285
+ */
286
+ use: ContextHook<State, StateMutator, BaseMetadata>;
287
+ /**
288
+ * @description Provider for the context
289
+ */
290
+ Provider: ContextProvider<State, StateMutator, BaseMetadata>;
291
+ /**
292
+ * @description The raw React Context object
293
+ */
294
+ Context: ReactContext<ContextHook<State, StateMutator, BaseMetadata> | null>;
160
295
  };
161
296
  /**
162
297
  * @description Creates a highly granular React context with its associated provider and state hook.
@@ -174,17 +309,70 @@ interface CreateContext {
174
309
  * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
175
310
  * external tools or non-React consumers.
176
311
  */
177
- <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>>>(value: State | (() => State), args: {
312
+ <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata> | null | {}, StateMutator = keyof ActionsConfig extends never | undefined ? React.Dispatch<React.SetStateAction<State>> : ActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(
313
+ /**
314
+ * @description Initial state value or initializer function.
315
+ */
316
+ value: State | (() => State),
317
+ /**
318
+ * @description Additional configuration for the context.
319
+ * @param args.name Optional name for debugging purposes.
320
+ * @param args.metadata Optional non-reactive metadata associated with the state.
321
+ * @param args.callbacks Optional lifecycle callbacks for the context.
322
+ * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
323
+ */
324
+ args: {
178
325
  name?: string;
179
326
  metadata?: Metadata | (() => Metadata);
180
- callbacks?: GlobalStoreCallbacks<State, Metadata> & {
327
+ callbacks?: GlobalStoreCallbacks<State, StateMutator, Metadata> & {
181
328
  onUnMount?: () => void;
182
329
  };
183
330
  actions?: ActionsConfig;
184
331
  }): {
185
- use: ContextHook<State, PublicStateMutator, Metadata>;
186
- Provider: ContextProvider<State, PublicStateMutator, Metadata>;
187
- Context: ReactContext<ContextHook<State, PublicStateMutator, Metadata> | null>;
332
+ /**
333
+ * @description Hook and API for interacting with the context.
334
+ * This hook provides access to the context state, actions, and metadata.
335
+ *
336
+ * There are two ways to use the hook
337
+ * @example
338
+ * The more simple and familiar way is to use it as a regular hook
339
+ *
340
+ * ```tsx
341
+ * const { Context, Provider, user: useUser} = createContext({ name: 'John', age: 30 });
342
+ *
343
+ * function UserProfile() {
344
+ * const [state, setState, metadata] = useUser();
345
+ *
346
+ * ....
347
+ * }
348
+ * ```
349
+ *
350
+ * @example
351
+ * The recommended, more sematic and easier to read way:
352
+ *
353
+ * ```tsx
354
+ * const user = createContext({ name: 'John', age: 30 });
355
+ *
356
+ * <user.Provider>
357
+ * <UserProfile />
358
+ * </user.Provider>
359
+ *
360
+ * function UserProfile() {
361
+ * const [state, setState, metadata] = user.use();
362
+ * const userContext = user.use.api();
363
+ * const userName = user.use.select(s => s.name);
364
+ * // ...
365
+ * }
366
+ */
367
+ use: ContextHook<State, StateMutator, Metadata>;
368
+ /**
369
+ * @description Provider for the context
370
+ */
371
+ Provider: ContextProvider<State, StateMutator, Metadata>;
372
+ /**
373
+ * @description Raw React Context object
374
+ */
375
+ Context: ReactContext<ContextHook<State, StateMutator, Metadata> | null>;
188
376
  };
189
377
  /**
190
378
  * @description Creates a highly granular React context with its associated provider and state hook.
@@ -202,16 +390,69 @@ interface CreateContext {
202
390
  * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
203
391
  * external tools or non-React consumers.
204
392
  */
205
- <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>>(value: State | (() => State), args: {
393
+ <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>, StateMutator = React.Dispatch<React.SetStateAction<State>>>(
394
+ /**
395
+ * @description Initial state value or initializer function.
396
+ */
397
+ value: State | (() => State),
398
+ /**
399
+ * @description Additional configuration for the context.
400
+ * @param args.name Optional name for debugging purposes.
401
+ * @param args.metadata Optional non-reactive metadata associated with the state.
402
+ * @param args.callbacks Optional lifecycle callbacks for the context.
403
+ * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
404
+ */
405
+ args: {
206
406
  name?: string;
207
407
  metadata?: Metadata | (() => Metadata);
208
- callbacks?: GlobalStoreCallbacks<State, Metadata> & {
408
+ callbacks?: GlobalStoreCallbacks<State, StateMutator, Metadata> & {
209
409
  onUnMount?: () => void;
210
410
  };
211
411
  actions: ActionsConfig;
212
412
  }): {
413
+ /**
414
+ * @description Hook and API for interacting with the context.
415
+ * This hook provides access to the context state, actions, and metadata.
416
+ *
417
+ * There are two ways to use the hook
418
+ * @example
419
+ * The more simple and familiar way is to use it as a regular hook
420
+ *
421
+ * ```tsx
422
+ * const { Context, Provider, user: useUser} = createContext({ name: 'John', age: 30 });
423
+ *
424
+ * function UserProfile() {
425
+ * const [state, setState, metadata] = useUser();
426
+ *
427
+ * ....
428
+ * }
429
+ * ```
430
+ *
431
+ * @example
432
+ * The recommended, more sematic and easier to read way:
433
+ *
434
+ * ```tsx
435
+ * const user = createContext({ name: 'John', age: 30 });
436
+ *
437
+ * <user.Provider>
438
+ * <UserProfile />
439
+ * </user.Provider>
440
+ *
441
+ * function UserProfile() {
442
+ * const [state, setState, metadata] = user.use();
443
+ * const userContext = user.use.api();
444
+ * const userName = user.use.select(s => s.name);
445
+ * // ...
446
+ * }
447
+ */
213
448
  use: ContextHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
449
+ /**
450
+ * @description Provider for the context
451
+ */
214
452
  Provider: ContextProvider<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
453
+ /**
454
+ * @description Raw React Context object
455
+ */
215
456
  Context: ReactContext<ContextHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata> | null>;
216
457
  };
217
458
  }
@@ -237,5 +478,5 @@ export declare const createContext: CreateContext;
237
478
  * ContextApi<number, React.Dispatch<React.SetStateAction<number>>, BaseMetadata>;
238
479
  * ```
239
480
  */
240
- export type InferContextApi<Context extends ReactContext<ContextHook<any, any, any> | null>> = NonNullable<React.ContextType<Context>> extends ContextHook<infer State, infer StateMutator, infer Metadata> ? ContextApi<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata> : never;
481
+ export type InferContextApi<Context extends ReactContext<ContextHook<any, any, BaseMetadata> | null>> = NonNullable<React.ContextType<Context>> extends ContextHook<infer State, infer StateMutator, infer Metadata> ? StateApi<State, StateMutator extends AnyFunction ? null : StateMutator, Metadata> : never;
241
482
  export default createContext;
package/createContext.js CHANGED
@@ -1,70 +1 @@
1
- var e,t;e=this,t=(e,t,r,o)=>/******/(()=>{
2
- /******/"use strict";
3
- /******/var n={
4
- /***/155:
5
- /***/t=>{t.exports=e;
6
- /***/},
7
- /***/506:
8
- /***/e=>{e.exports=t;
9
- /***/},
10
- /***/639:
11
- /***/(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createContext=void 0;var o=r(155),n=r(778),a=r(506),i=r(773);
12
- /**
13
- * @description Creates a highly granular React context with its associated provider and state hook.
14
- * Unlike the native `React.createContext`, this version provides fine-grained reactivity and supports
15
- * state selection, metadata handling, and optional custom actions for controlled mutations.
16
- *
17
- * Components using the generated hook only re-render when the selected part of the state changes,
18
- * making it efficient for large or deeply nested state trees.
19
- */
20
- t.createContext=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=(0,o.createContext)(null),u=function(u){var s=u.children,l=u.value,c=u.onCreated,f=(0,o.useMemo)((function(){var r,o=function(){return(0,a.isFunction)(e)?e():e},u=(0,i.isNil)(l)?o():(0,a.isFunction)(l)?l(o()):l;return new n.GlobalStore(u,Object.assign(Object.assign({},t),{metadata:null!==(r=(0,a.isFunction)(t.metadata)?t.metadata():t.metadata)&&void 0!==r?r:{}}))}),[]);return(0,o.useEffect)((function(){return function(){var e,t,r,o;null===(t=null===(e=f.callbacks)||void 0===e?void 0:e.onUnMount)||void 0===t||t.call(e,f),
21
- /**
22
- * Required by the global hooks developer tools
23
- */
24
- null===(o=(r=f).__onUnMountContext)||void 0===o||o.call(r,f),f.dispose()}}),[f]),null==c||c(f.getConfigCallbackParam()),(0,o.createElement)(r.Provider,{value:f.use},s)},s={makeProviderWrapper:function(e){var t={current:void 0};return{wrapper:function(r){var n=r.children;return(0,o.createElement)(u,{value:null==e?void 0:e.value,onCreated:function(r){var o;t.current=r,null===(o=null==e?void 0:e.onCreated)||void 0===o||o.call(e,r)}},n)},context:t}}},l=function(){var e=(0,o.useContext)(r);if(!e)throw new Error("use hook must be used within a ContextProvider");return e.apply(void 0,arguments)},c={
25
- /**
26
- * Store selectors are not created until the first time they are used
27
- */
28
- createSelectorHook:function(e,t){return function(){var n=(0,o.useContext)(r);if((0,i.isNil)(n))throw new Error("SelectorHook must be used within a ContextProvider");var a=(0,o.useRef)(e);a.current=e;var u=(0,o.useMemo)((function(){return n.createSelectorHook((function(){return a.current.apply(a,arguments)}),t)}),[n]);return(0,o.useEffect)((function(){return function(){null==u||u.dispose()}}),[u]),u.apply(void 0,arguments)}},api:function(){var e=(0,o.useContext)(r);if(!e)throw new Error("api hook must be used within a ContextProvider");return e}};return Object.assign(u,s),Object.assign(l,c),{use:l,Provider:u,Context:r}},t.default=t.createContext}
29
- /***/,
30
- /***/773:
31
- /***/e=>{e.exports=r;
32
- /***/},
33
- /***/778:
34
- /***/e=>{e.exports=o;
35
- /***/
36
- /******/}},a={};
37
- /************************************************************************/
38
- /******/
39
- /******/
40
- /******/
41
- /******/
42
- /******/
43
- /******/
44
- /******/return function e(t){
45
- /******/
46
- /******/var r=a[t];
47
- /******/if(void 0!==r)
48
- /******/return r.exports;
49
- /******/
50
- /******/
51
- /******/var o=a[t]={
52
- /******/
53
- /******/
54
- /******/exports:{}
55
- /******/};
56
- /******/
57
- /******/
58
- /******/
59
- /******/
60
- /******/
61
- /******/return n[t](o,o.exports,e),o.exports;
62
- /******/}
63
- /******/
64
- /************************************************************************/
65
- /******/
66
- /******/
67
- /******/
68
- /******/
69
- /******/(639);
70
- /******/})(),"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("json-storage-formatter/isFunction"),require("json-storage-formatter/isNil"),require("./GlobalStore.js")):"function"==typeof define&&define.amd?define(["react","json-storage-formatter/isFunction","json-storage-formatter/isNil","./GlobalStore.js"],t):"object"==typeof exports?exports["react-hooks-global-states"]=t(require("react"),require("json-storage-formatter/isFunction"),require("json-storage-formatter/isNil"),require("./GlobalStore.js")):e["react-hooks-global-states"]=t(e.react,e["json-storage-formatter/isFunction"],e["json-storage-formatter/isNil"],e["./GlobalStore.js"]);
1
+ var e,t;e=this,t=(e,t,r,o)=>(()=>{"use strict";var n={155:t=>{t.exports=e},506:e=>{e.exports=t},639:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createContext=void 0;var o=r(155),n=r(778),a=r(506),i=r(773);function u(e,t){var r=this,a=function(){var n=r.api();return(0,o.useMemo)((function(){return n.createSelectorHook(e,t)}),[n]).apply(void 0,arguments)},i={createSelectorHook:u.bind(a),api:function(){var a=r.api();return(0,o.useMemo)((function(){var r=a.createObservable(e,t);return Object.assign(Object.assign({},a),{getState:function(){return r.getState()},subscribe:r.subscribe.bind(r),createSelectorHook:n.createSelectorHook.bind(r),createObservable:n.createObservable.bind(r)})}),[a])}};return Object.assign(a,i),a}t.createContext=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=(0,o.createContext)(null),s=function(u){var s=u.children,l=u.value,c=u.onCreated,v=(0,o.useMemo)((function(){var r,o=function(){return(0,a.isFunction)(e)?e():e},u=(0,i.isNil)(l)?o():(0,a.isFunction)(l)?l(o()):l;return new n.GlobalStore(u,Object.assign(Object.assign({},t),{metadata:null!==(r=(0,a.isFunction)(t.metadata)?t.metadata():t.metadata)&&void 0!==r?r:{}}))}),[]);return(0,o.useEffect)((function(){return function(){var e,t,r,o;null===(t=null===(e=v.callbacks)||void 0===e?void 0:e.onUnMount)||void 0===t||t.call(e,v),null===(o=(r=v).__onUnMountContext)||void 0===o||o.call(r,v),v.dispose()}}),[v]),null==c||c(v.getConfigCallbackParam()),(0,o.createElement)(r.Provider,{value:v.use},s)},l={makeProviderWrapper:function(e){var t={current:void 0};return{wrapper:function(r){var n=r.children;return(0,o.createElement)(s,{value:null==e?void 0:e.value,onCreated:function(r){var o;t.current=r,null===(o=null==e?void 0:e.onCreated)||void 0===o||o.call(e,r)}},n)},context:t}}},c=function(){var e=(0,o.useContext)(r);if(!e)throw new Error("use hook must be used within a ContextProvider");return e.apply(void 0,arguments)},v=function(){var e=(0,o.useContext)(r);if(!e)throw new Error("api hook must be used within a ContextProvider");return e},d={createSelectorHook:u.bind(c),api:v,select:function(){return c.apply(void 0,arguments)[0]},observable:function(){for(var e=v(),t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];var a=(0,o.useRef)(r);return a.current=r,(0,o.useMemo)((function(){var t,r,o;return e.createObservable((function(e){return(0,a.current[0])(e)}),{isEqualRoot:Boolean(null===(t=a.current[1])||void 0===t?void 0:t.isEqualRoot)?function(e,t){var r,o=null===(r=a.current[1])||void 0===r?void 0:r.isEqualRoot;return Boolean(o(e,t))}:void 0,isEqual:Boolean(null===(r=a.current[1])||void 0===r?void 0:r.isEqual)?function(e,t){var r,o=null===(r=a.current[1])||void 0===r?void 0:r.isEqual;return Boolean(o(e,t))}:void 0,name:null===(o=a.current[1])||void 0===o?void 0:o.name})}),[e])},actions:function(){return v().actions}};return Object.assign(s,l),Object.assign(c,d),{use:c,Provider:s,Context:r}},t.default=t.createContext},773:e=>{e.exports=r},778:e=>{e.exports=o}},a={};return function e(t){var r=a[t];if(void 0!==r)return r.exports;var o=a[t]={exports:{}};return n[t](o,o.exports,e),o.exports}(639)})(),"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("json-storage-formatter/isFunction"),require("json-storage-formatter/isNil"),require("./GlobalStore.js")):"function"==typeof define&&define.amd?define(["react","json-storage-formatter/isFunction","json-storage-formatter/isNil","./GlobalStore.js"],t):"object"==typeof exports?exports["react-hooks-global-states"]=t(require("react"),require("json-storage-formatter/isFunction"),require("json-storage-formatter/isNil"),require("./GlobalStore.js")):e["react-hooks-global-states"]=t(e.react,e["json-storage-formatter/isFunction"],e["json-storage-formatter/isNil"],e["./GlobalStore.js"]);
@@ -4,7 +4,9 @@ interface CreateGlobalState {
4
4
  * Creates a global state hook.
5
5
  * @param state initial state value
6
6
  * @returns a state hook for your components
7
+ *
7
8
  * @example
9
+ * ```tsx
8
10
  * const useCounter = createGlobalState(0);
9
11
  *
10
12
  * function Counter() {
@@ -18,8 +20,23 @@ interface CreateGlobalState {
18
20
  * </div>
19
21
  * );
20
22
  * }
23
+ * ```
24
+ *
25
+ * @example You can also use a more semantic and declarative approach
26
+ * ```tsx
27
+ * const counter = createGlobalState(0);
28
+ *
29
+ * function Counter() {
30
+ * const [count, setCount] = counter.use();
31
+ * const count = counter.use.select();
32
+ *
33
+ * counter.setState(prev => prev + 1);
34
+ *
35
+ * // if you have actions
36
+ * counter.actions.someAction();
37
+ * ```
21
38
  */
22
- <State, StateDispatch = React.Dispatch<React.SetStateAction<State>>>(state: State): StateHook<State, StateDispatch, StateDispatch, BaseMetadata>;
39
+ <State>(state: State): StateHook<State, React.Dispatch<React.SetStateAction<State>>, BaseMetadata>;
23
40
  /**
24
41
  * Creates a global state hook that you can use across your application
25
42
  * @param state initial state value
@@ -72,9 +89,9 @@ interface CreateGlobalState {
72
89
  <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>>, StateDispatch = React.Dispatch<React.SetStateAction<State>>>(state: State, args: {
73
90
  name?: string;
74
91
  metadata?: Metadata;
75
- callbacks?: GlobalStoreCallbacks<State, Metadata>;
92
+ callbacks?: GlobalStoreCallbacks<State, PublicStateMutator, Metadata>;
76
93
  actions?: ActionsConfig;
77
- }): StateHook<State, StateDispatch, PublicStateMutator, Metadata>;
94
+ }): StateHook<State, PublicStateMutator, Metadata>;
78
95
  /**
79
96
  * Creates a global state hook that you can use across your application
80
97
  * @param state initial state value
@@ -124,12 +141,12 @@ interface CreateGlobalState {
124
141
  * }
125
142
  * ```
126
143
  */
127
- <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>, StateDispatch = React.Dispatch<React.SetStateAction<State>>>(state: State, args: {
144
+ <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>, PublicStateMutator = ActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(state: State, args: {
128
145
  name?: string;
129
146
  metadata?: Metadata;
130
- callbacks?: GlobalStoreCallbacks<State, Metadata>;
147
+ callbacks?: GlobalStoreCallbacks<State, PublicStateMutator, Metadata>;
131
148
  actions: ActionsConfig;
132
- }): StateHook<State, StateDispatch, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
149
+ }): StateHook<State, PublicStateMutator, Metadata>;
133
150
  }
134
151
  /**
135
152
  * Creates a global state hook
@@ -142,5 +159,5 @@ export declare const createGlobalState: CreateGlobalState;
142
159
  * type CounterActions = InferActionsType<typeof useCounter>;
143
160
  * ```
144
161
  */
145
- export type InferActionsType<Hook extends StateHook<any, any, any, any>> = ReturnType<Hook['actions']>['1'];
162
+ export type InferActionsType<Hook extends StateHook<any, any, any>> = ReturnType<Hook['actions']>['1'];
146
163
  export default createGlobalState;
@@ -1,47 +1 @@
1
- var e;e=e=>/******/(()=>{
2
- /******/"use strict";
3
- /******/var t={
4
- /***/778:
5
- /***/t=>{t.exports=e;
6
- /***/},
7
- /***/840:
8
- /***/(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createGlobalState=void 0;var r=o(778);
9
- /**
10
- * Creates a global state hook
11
- */t.createGlobalState=function(){for(var e=arguments.length,t=new Array(e),o=0;o<e;o++)t[o]=arguments[o];var a=t[0],l=t[1];return new r.GlobalStore(a,l).use},t.default=t.createGlobalState}
12
- /***/
13
- /******/},o={};
14
- /************************************************************************/
15
- /******/
16
- /******/
17
- /******/
18
- /******/
19
- /******/
20
- /******/
21
- /******/return function e(r){
22
- /******/
23
- /******/var a=o[r];
24
- /******/if(void 0!==a)
25
- /******/return a.exports;
26
- /******/
27
- /******/
28
- /******/var l=o[r]={
29
- /******/
30
- /******/
31
- /******/exports:{}
32
- /******/};
33
- /******/
34
- /******/
35
- /******/
36
- /******/
37
- /******/
38
- /******/return t[r](l,l.exports,e),l.exports;
39
- /******/}
40
- /******/
41
- /************************************************************************/
42
- /******/
43
- /******/
44
- /******/
45
- /******/
46
- /******/(840);
47
- /******/})(),"object"==typeof exports&&"object"==typeof module?module.exports=e(require("./GlobalStore.js")):"function"==typeof define&&define.amd?define(["./GlobalStore.js"],e):"object"==typeof exports?exports["react-hooks-global-states"]=e(require("./GlobalStore.js")):this["react-hooks-global-states"]=e(this["./GlobalStore.js"]);
1
+ var e;e=e=>(()=>{"use strict";var t={778:t=>{t.exports=e},840:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createGlobalState=void 0;var r=o(778);t.createGlobalState=function(){for(var e=arguments.length,t=new Array(e),o=0;o<e;o++)t[o]=arguments[o];var a=t[0],l=t[1];return new r.GlobalStore(a,l).use},t.default=t.createGlobalState}},o={};return function e(r){var a=o[r];if(void 0!==a)return a.exports;var l=o[r]={exports:{}};return t[r](l,l.exports,e),l.exports}(840)})(),"object"==typeof exports&&"object"==typeof module?module.exports=e(require("./GlobalStore.js")):"function"==typeof define&&define.amd?define(["./GlobalStore.js"],e):"object"==typeof exports?exports["react-hooks-global-states"]=e(require("./GlobalStore.js")):this["react-hooks-global-states"]=e(this["./GlobalStore.js"]);
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { StateApi, ObservableFragment, MetadataSetter, StateChanges, StoreTools, ActionCollectionResult, GlobalStoreCallbacks, UseHookConfig, UnsubscribeCallback, SubscribeCallbackConfig, SubscribeCallback, BaseMetadata, MetadataGetter, CustomGlobalHookBuilderParams, SelectorCallback, SubscriberParameters, SubscriptionCallback, StateHook, ActionCollectionConfig, } from './types';
1
+ export { StateApi, ObservableFragment, MetadataSetter, StateChanges, StoreTools, ActionCollectionResult, GlobalStoreCallbacks, UseHookOptions, UnsubscribeCallback, SubscribeCallbackConfig, SubscribeCallback, BaseMetadata, MetadataGetter, SelectorCallback, SubscriberParameters, SubscriptionCallback, StateHook, ActionCollectionConfig, } from './types';
2
2
  export { GlobalStore } from './GlobalStore';
3
3
  export { GlobalStoreAbstract } from './GlobalStoreAbstract';
4
4
  export { createGlobalState, type InferActionsType } from './createGlobalState';
@@ -6,4 +6,4 @@ export { shallowCompare } from './shallowCompare';
6
6
  export { uniqueId } from './uniqueId';
7
7
  export { throwWrongKeyOnActionCollectionConfig } from './throwWrongKeyOnActionCollectionConfig';
8
8
  export { isRecord } from './isRecord';
9
- export { type ContextApi, type ContextProvider, type ContextHook, type InferContextApi, createContext, } from './createContext';
9
+ export { type ContextProvider, type ContextHook, type InferContextApi, createContext } from './createContext';