react-hooks-global-states 10.2.0 → 11.0.0-beta.2

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.
package/bundle.js CHANGED
@@ -1 +1,56 @@
1
- var e,t;e=this,t=(e,t,r,o,a,n,s,l,u,i,c)=>(()=>{"use strict";var b={45:t=>{t.exports=e},78:e=>{e.exports=t},361:e=>{e.exports=r},417:e=>{e.exports=o},487:e=>{e.exports=a},623:e=>{e.exports=n},670:e=>{e.exports=s},673:e=>{e.exports=l},778:e=>{e.exports=u},804:e=>{e.exports=i},923:e=>{e.exports=c}},j={};function S(e){var t=j[e];if(void 0!==t)return t.exports;var r=j[e]={exports:{}};return b[e](r,r.exports,S),r.exports}var p={};return(()=>{var e=p;Object.defineProperty(e,"__esModule",{value:!0}),e.generateStackHash=e.createContext=e.useStableState=e.isRecord=e.throwWrongKeyOnActionCollectionConfig=e.uniqueId=e.shallowCompare=e.createCustomGlobalState=e.createGlobalState=e.GlobalStoreAbstract=e.GlobalStore=void 0;var t=S(778);Object.defineProperty(e,"GlobalStore",{enumerable:!0,get:function(){return t.GlobalStore}});var r=S(804);Object.defineProperty(e,"GlobalStoreAbstract",{enumerable:!0,get:function(){return r.GlobalStoreAbstract}});var o=S(670);Object.defineProperty(e,"createGlobalState",{enumerable:!0,get:function(){return o.createGlobalState}});var a=S(417);Object.defineProperty(e,"createCustomGlobalState",{enumerable:!0,get:function(){return a.createCustomGlobalState}});var n=S(673);Object.defineProperty(e,"shallowCompare",{enumerable:!0,get:function(){return n.shallowCompare}});var s=S(78);Object.defineProperty(e,"uniqueId",{enumerable:!0,get:function(){return s.uniqueId}});var l=S(361);Object.defineProperty(e,"throwWrongKeyOnActionCollectionConfig",{enumerable:!0,get:function(){return l.throwWrongKeyOnActionCollectionConfig}});var u=S(487);Object.defineProperty(e,"isRecord",{enumerable:!0,get:function(){return u.isRecord}});var i=S(923);Object.defineProperty(e,"useStableState",{enumerable:!0,get:function(){return i.useStableState}});var c=S(623);Object.defineProperty(e,"createContext",{enumerable:!0,get:function(){return c.createContext}});var b=S(45);Object.defineProperty(e,"generateStackHash",{enumerable:!0,get:function(){return b.generateStackHash}})})(),p})(),"object"==typeof exports&&"object"==typeof module?module.exports=t(require("./generateStackHash.js"),require("./uniqueId.js"),require("./throwWrongKeyOnActionCollectionConfig.js"),require("./createCustomGlobalState.js"),require("./isRecord.js"),require("./createContext.js"),require("./createGlobalState.js"),require("./shallowCompare.js"),require("./GlobalStore.js"),require("./GlobalStoreAbstract.js"),require("./useStableState.js")):"function"==typeof define&&define.amd?define(["./generateStackHash.js","./uniqueId.js","./throwWrongKeyOnActionCollectionConfig.js","./createCustomGlobalState.js","./isRecord.js","./createContext.js","./createGlobalState.js","./shallowCompare.js","./GlobalStore.js","./GlobalStoreAbstract.js","./useStableState.js"],t):"object"==typeof exports?exports["react-hooks-global-states"]=t(require("./generateStackHash.js"),require("./uniqueId.js"),require("./throwWrongKeyOnActionCollectionConfig.js"),require("./createCustomGlobalState.js"),require("./isRecord.js"),require("./createContext.js"),require("./createGlobalState.js"),require("./shallowCompare.js"),require("./GlobalStore.js"),require("./GlobalStoreAbstract.js"),require("./useStableState.js")):e["react-hooks-global-states"]=t(e["./generateStackHash.js"],e["./uniqueId.js"],e["./throwWrongKeyOnActionCollectionConfig.js"],e["./createCustomGlobalState.js"],e["./isRecord.js"],e["./createContext.js"],e["./createGlobalState.js"],e["./shallowCompare.js"],e["./GlobalStore.js"],e["./GlobalStoreAbstract.js"],e["./useStableState.js"]);
1
+ var e,r;e=this,r=(e,r,t,o,n,a,l,s)=>/******/(()=>{
2
+ /******/"use strict";
3
+ /******/var i={
4
+ /***/78:
5
+ /***/r=>{r.exports=e;
6
+ /***/},
7
+ /***/361:
8
+ /***/e=>{e.exports=r;
9
+ /***/},
10
+ /***/487:
11
+ /***/e=>{e.exports=t;
12
+ /***/},
13
+ /***/623:
14
+ /***/e=>{e.exports=o;
15
+ /***/},
16
+ /***/670:
17
+ /***/e=>{e.exports=n;
18
+ /***/},
19
+ /***/673:
20
+ /***/e=>{e.exports=a;
21
+ /***/},
22
+ /***/778:
23
+ /***/e=>{e.exports=l;
24
+ /***/},
25
+ /***/804:
26
+ /***/e=>{e.exports=s;
27
+ /***/
28
+ /******/}},c={};
29
+ /************************************************************************/
30
+ /******/
31
+ /******/
32
+ /******/
33
+ /******/
34
+ /******/function u(e){
35
+ /******/
36
+ /******/var r=c[e];
37
+ /******/if(void 0!==r)
38
+ /******/return r.exports;
39
+ /******/
40
+ /******/
41
+ /******/var t=c[e]={
42
+ /******/
43
+ /******/
44
+ /******/exports:{}
45
+ /******/};
46
+ /******/
47
+ /******/
48
+ /******/
49
+ /******/
50
+ /******/
51
+ /******/return i[e](t,t.exports,u),t.exports;
52
+ /******/}
53
+ /******/
54
+ /************************************************************************/var b={};
55
+ /******/return(()=>{var e=b;Object.defineProperty(e,"__esModule",{value:!0}),e.createContext=e.isRecord=e.throwWrongKeyOnActionCollectionConfig=e.uniqueId=e.shallowCompare=e.createGlobalState=e.GlobalStoreAbstract=e.GlobalStore=void 0;var r=u(778);Object.defineProperty(e,"GlobalStore",{enumerable:!0,get:function(){return r.GlobalStore}});var t=u(804);Object.defineProperty(e,"GlobalStoreAbstract",{enumerable:!0,get:function(){return t.GlobalStoreAbstract}});var o=u(670);Object.defineProperty(e,"createGlobalState",{enumerable:!0,get:function(){return o.createGlobalState}});var n=u(673);Object.defineProperty(e,"shallowCompare",{enumerable:!0,get:function(){return n.shallowCompare}});var a=u(78);Object.defineProperty(e,"uniqueId",{enumerable:!0,get:function(){return a.uniqueId}});var l=u(361);Object.defineProperty(e,"throwWrongKeyOnActionCollectionConfig",{enumerable:!0,get:function(){return l.throwWrongKeyOnActionCollectionConfig}});var s=u(487);Object.defineProperty(e,"isRecord",{enumerable:!0,get:function(){return s.isRecord}});var i=u(623);Object.defineProperty(e,"createContext",{enumerable:!0,get:function(){return i.createContext}})})(),b;
56
+ /******/})(),"object"==typeof exports&&"object"==typeof module?module.exports=r(require("./uniqueId.js"),require("./throwWrongKeyOnActionCollectionConfig.js"),require("./isRecord.js"),require("./createContext.js"),require("./createGlobalState.js"),require("./shallowCompare.js"),require("./GlobalStore.js"),require("./GlobalStoreAbstract.js")):"function"==typeof define&&define.amd?define(["./uniqueId.js","./throwWrongKeyOnActionCollectionConfig.js","./isRecord.js","./createContext.js","./createGlobalState.js","./shallowCompare.js","./GlobalStore.js","./GlobalStoreAbstract.js"],r):"object"==typeof exports?exports["react-hooks-global-states"]=r(require("./uniqueId.js"),require("./throwWrongKeyOnActionCollectionConfig.js"),require("./isRecord.js"),require("./createContext.js"),require("./createGlobalState.js"),require("./shallowCompare.js"),require("./GlobalStore.js"),require("./GlobalStoreAbstract.js")):e["react-hooks-global-states"]=r(e["./uniqueId.js"],e["./throwWrongKeyOnActionCollectionConfig.js"],e["./isRecord.js"],e["./createContext.js"],e["./createGlobalState.js"],e["./shallowCompare.js"],e["./GlobalStore.js"],e["./GlobalStoreAbstract.js"]);
@@ -1,104 +1,241 @@
1
- import { type PropsWithChildren, Context as ReactContext } from 'react';
2
- import type { ActionCollectionConfig, StateHook, StateSetter, ActionCollectionResult, StateGetter, BaseMetadata, MetadataSetter, GlobalStoreCallbacks, UseHookConfig, ObservableFragment, MetadataGetter } from './types';
3
- export type Context<State, Actions, Metadata extends BaseMetadata | unknown> = {
4
- setMetadata: MetadataSetter<Metadata>;
5
- setState: StateSetter<State>;
6
- getState: StateGetter<State>;
7
- getMetadata: () => Metadata;
1
+ import React, { type PropsWithChildren, Context as ReactContext } from 'react';
2
+ import type { ActionCollectionConfig, ActionCollectionResult, BaseMetadata, MetadataSetter, GlobalStoreCallbacks, UseHookConfig, SubscribeToState, AnyFunction } from './types';
3
+ /**
4
+ * @description Context API
5
+ */
6
+ export type ContextApi<State, Actions, Metadata extends BaseMetadata> = {
8
7
  actions: Actions;
8
+ getMetadata: () => Metadata;
9
+ getState: () => State;
10
+ setMetadata: MetadataSetter<Metadata>;
11
+ setState: React.Dispatch<React.SetStateAction<State>>;
12
+ subscribe: SubscribeToState<State>;
9
13
  };
10
- export type ContextProvider<State, Actions, Metadata extends BaseMetadata | unknown> = React.FC<PropsWithChildren<{
11
- value?: State | ((initialValue: State) => State);
14
+ export type ContextProviderExtensions<State, Actions, Metadata extends BaseMetadata> = {
12
15
  /**
13
- * Callback called when the context is created.
14
- */
15
- onCreated?: (context: Context<State, Actions, Metadata>) => void;
16
- }>> & {
17
- /**F
18
16
  * Creates a provider wrapper which allows to capture the context value,
19
17
  * useful for testing purposes.
18
+ * @param options configuration options for the provider wrapper
19
+ * @param options.value optional initial state or initializer function
20
+ * @param options.onCreated optional callback invoked after the context is created
21
+ * @returns an object containing the wrapper component and a reference to the context value
20
22
  */
21
23
  makeProviderWrapper: (options?: {
22
24
  value?: State | ((initialValue: State) => State);
23
- onCreated?: (context: Context<State, Actions, Metadata>) => void;
25
+ onCreated?: (context: ContextApi<State, Actions, Metadata>) => void;
24
26
  }) => {
27
+ /**
28
+ * Provider for the context
29
+ */
25
30
  wrapper: React.FC<PropsWithChildren<{
26
31
  value?: State | ((initialValue: State) => State);
27
32
  }>>;
28
33
  /**
29
- * Returns access to the created context
30
- * context.current will hold the context value
34
+ * Reference to the current context value
31
35
  */
32
36
  context: {
33
- current: Context<State, Actions, Metadata>;
37
+ current: ContextApi<State, Actions, Metadata>;
34
38
  };
35
39
  };
36
40
  };
37
- export type StateControlsHook<State, StateMutator, Metadata extends BaseMetadata | unknown> = () => Readonly<[
38
- retriever: StateGetter<State>,
39
- mutator: StateMutator,
40
- metadata: MetadataGetter<Metadata>
41
- ]>;
42
- export type ObservableBuilderHook<State, StateMutator, Metadata extends BaseMetadata | unknown> = <Fragment>(this: ContextHook<State, StateMutator, Metadata>, mainSelector: (state: State) => Fragment, args?: {
43
- isEqual?: (current: Fragment, next: Fragment) => boolean;
44
- isEqualRoot?: (current: State, next: State) => boolean;
45
- name?: string;
46
- }) => ObservableFragment<Fragment>;
47
- export interface ContextBaseHook<State, StateMutator, Metadata extends BaseMetadata | unknown> {
41
+ /**
42
+ * @description Creates a React context provider component for the given global state.
43
+ * @param value Optional initial state or initializer function, useful for testing.
44
+ * @param onCreated Optional callback invoked after the context is created, receiving the full context instance.
45
+ */
46
+ export type ContextProvider<State, Actions, Metadata extends BaseMetadata> = React.FC<PropsWithChildren<{
47
+ 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
+ /**
52
+ * @description Retrieves the full state, state mutator (setState or actions), and metadata.
53
+ */
48
54
  (): Readonly<[state: State, stateMutator: StateMutator, metadata: Metadata]>;
49
- <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Readonly<[
50
- state: Derivate,
51
- stateMutator: StateMutator,
52
- metadata: Metadata
53
- ]>;
54
- <Derivate>(selector: (state: State) => Derivate, config?: UseHookConfig<Derivate, State>): Readonly<[
55
- state: Derivate,
56
- stateMutator: StateMutator,
57
- metadata: Metadata
58
- ]>;
55
+ /**
56
+ * @description Retrieves a derived value from the state using the provided selector function.
57
+ * @param selector A function that selects a part of the state.
58
+ * @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.
60
+ */
61
+ <Derivate>(selector: (state: State) => Derivate, dependencies?: unknown[]): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
62
+ /**
63
+ * @description Retrieves a derived value from the state using the provided selector function.
64
+ * @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.
67
+ */
68
+ <Derivate>(selector: (state: State) => Derivate, config?: UseHookConfig<Derivate, State>): Readonly<[state: Derivate, stateMutator: StateMutator, metadata: Metadata]>;
59
69
  }
60
- export interface ContextHook<State, StateMutator, Metadata extends BaseMetadata | unknown> extends HookExtensions<State, StateMutator, Metadata>, ContextBaseHook<State, StateMutator, Metadata> {
70
+ /**
71
+ * @description Hook for accessing a context's state, mutator (setState or actions), and metadata.
72
+ * @returns A read-only tuple containing:
73
+ * - state: the current state, or the derived value when a selector is used
74
+ * - stateMutator: a function or actions collection to update the state
75
+ * - metadata: the current context metadata
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * // Simple usage (full state)
80
+ * const [state, setState] = useTodosContext();
81
+ *
82
+ * // With a selector (preferred for render isolation)
83
+ * const [todos, actions] = useTodosContext(s => s.todos);
84
+ *
85
+ * actions.setTodos(next);
86
+ * ```
87
+ */
88
+ export interface ContextHook<State, StateMutator, Metadata extends BaseMetadata> extends HookExtensions<State, StateMutator, Metadata>, ContextBaseHook<State, StateMutator, Metadata> {
61
89
  }
62
- export type HookExtensions<State, StateMutator, Metadata extends BaseMetadata | unknown> = {
63
- stateControls: () => readonly [
64
- useStateControls: StateControlsHook<State, StateMutator, Metadata>,
65
- useObservableBuilder: ObservableBuilderHook<State, StateMutator, Metadata>
66
- ];
90
+ export type HookExtensions<State, StateMutator, Metadata extends BaseMetadata> = {
91
+ /**
92
+ * @description Creates a derived hook that subscribes to a selected fragment of the context state.
93
+ * The selector determines which portion of the state the new hook exposes.
94
+ * This hook must be used within the corresponding context provider.
95
+ *
96
+ * @param selector A function that selects a part of the state.
97
+ * @param args Optional configuration for the derived hook, including:
98
+ * - isEqual: A function to compare the current and next selected fragment for equality.
99
+ * - isEqualRoot: A function to compare the entire state for equality.
100
+ * - name: An optional name for debugging purposes.
101
+ * @returns A new context hook that provides access to the selected fragment of the state,
102
+ * along with the state mutator and metadata.
103
+ *
104
+ * @example
105
+ * ```tsx
106
+ * const useTodos = createContext({
107
+ * todos: [],
108
+ * filter: '',
109
+ * }, {
110
+ * actions: {
111
+ * setFilter(filter: string) {
112
+ * ...
113
+ * });
114
+ *
115
+ * const useFilter = useTodos.createSelectorHook((state) => {
116
+ * return state.filter;
117
+ * });
118
+ *
119
+ * function FilterComponent() {
120
+ * // The selector only listen to the selected fragment (filter)
121
+ * // But has access to the full actions collection
122
+ * const [filter, { setFilter }] = useFilter();
123
+ *
124
+ * return (
125
+ * <input
126
+ * value={filter}
127
+ * onChange={(e) => setFilter(e.target.value)}
128
+ * />
129
+ * );
130
+ * }
131
+ * ```
132
+ */
67
133
  createSelectorHook: <Derivate>(this: ContextHook<State, StateMutator, Metadata>, selector: (state: State) => Derivate, args?: Omit<UseHookConfig<Derivate, State>, 'dependencies'> & {
68
134
  name?: string;
69
135
  }) => ContextBaseHook<Derivate, StateMutator, Metadata>;
136
+ /**
137
+ * @description Hook that provides non-reactive access to the context API.
138
+ * This allows direct interaction with the context’s state, metadata, and actions
139
+ * without triggering component re-renders.
140
+ * @returns An object containing the context API methods and properties.
141
+ */
142
+ api: () => ContextApi<State, StateMutator, Metadata>;
70
143
  };
71
144
  export interface CreateContext {
72
- <State>(value: State | (() => State)): [
73
- ContextHook<State, StateSetter<State>, BaseMetadata>,
74
- ContextProvider<State, null, BaseMetadata>,
75
- ReactContext<StateHook<State, StateSetter<State>, BaseMetadata> | null>
76
- ];
77
- <State, Metadata extends BaseMetadata | unknown, ActionsConfig extends ActionCollectionConfig<State, Metadata> | null | {}, PublicStateMutator = keyof ActionsConfig extends never | undefined ? StateSetter<State> : ActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(value: State | (() => State), args: {
145
+ /**
146
+ * @description Creates a highly granular React context with its associated provider and state hook.
147
+ * @param value Initial state value or initializer function.
148
+ * @returns An object containing:
149
+ * - **`use`** — A custom hook to read and mutate the context state.
150
+ * Supports selectors for granular subscriptions and returns `[state, stateMutator, metadata]`.
151
+ * - **`Provider`** — A React component that provides the context to its descendants.
152
+ * It accepts an optional initial value and `onCreated` callback.
153
+ * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
154
+ * external tools or non-React consumers.
155
+ */
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>;
160
+ };
161
+ /**
162
+ * @description Creates a highly granular React context with its associated provider and state hook.
163
+ * @param value Initial state value or initializer function.
164
+ * @param args Additional configuration for the context.
165
+ * @param args.name Optional name for debugging purposes.
166
+ * @param args.metadata Optional non-reactive metadata associated with the state.
167
+ * @param args.callbacks Optional lifecycle callbacks for the context.
168
+ * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
169
+ * @returns An object containing:
170
+ * - **`use`** — A custom hook to read and mutate the context state.
171
+ * Supports selectors for granular subscriptions and returns `[state, stateMutator, metadata]`.
172
+ * - **`Provider`** — A React component that provides the context to its descendants.
173
+ * It accepts an optional initial value and `onCreated` callback.
174
+ * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
175
+ * external tools or non-React consumers.
176
+ */
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: {
78
178
  name?: string;
79
179
  metadata?: Metadata | (() => Metadata);
80
180
  callbacks?: GlobalStoreCallbacks<State, Metadata> & {
81
181
  onUnMount?: () => void;
82
182
  };
83
183
  actions?: ActionsConfig;
84
- }): [
85
- ContextHook<State, PublicStateMutator, Metadata>,
86
- ContextProvider<State, PublicStateMutator, Metadata>,
87
- ReactContext<StateHook<State, PublicStateMutator, Metadata> | null>
88
- ];
89
- <State, Metadata extends BaseMetadata | unknown, ActionsConfig extends ActionCollectionConfig<State, Metadata>>(value: State | (() => State), args: {
184
+ }): {
185
+ use: ContextHook<State, PublicStateMutator, Metadata>;
186
+ Provider: ContextProvider<State, PublicStateMutator, Metadata>;
187
+ Context: ReactContext<ContextHook<State, PublicStateMutator, Metadata> | null>;
188
+ };
189
+ /**
190
+ * @description Creates a highly granular React context with its associated provider and state hook.
191
+ * @param value Initial state value or initializer function.
192
+ * @param args Additional configuration for the context.
193
+ * @param args.name Optional name for debugging purposes.
194
+ * @param args.metadata Optional non-reactive metadata associated with the state.
195
+ * @param args.callbacks Optional lifecycle callbacks for the context.
196
+ * @param args.actions Optional actions to restrict state mutations [if provided `setState` will be nullified].
197
+ * @returns An object containing:
198
+ * - **`use`** — A custom hook to read and mutate the context state.
199
+ * Supports selectors for granular subscriptions and returns `[state, stateMutator, metadata]`.
200
+ * - **`Provider`** — A React component that provides the context to its descendants.
201
+ * It accepts an optional initial value and `onCreated` callback.
202
+ * - **`Context`** — The raw React `Context` object for advanced usage, such as integration with
203
+ * external tools or non-React consumers.
204
+ */
205
+ <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>>(value: State | (() => State), args: {
90
206
  name?: string;
91
207
  metadata?: Metadata | (() => Metadata);
92
208
  callbacks?: GlobalStoreCallbacks<State, Metadata> & {
93
209
  onUnMount?: () => void;
94
210
  };
95
211
  actions: ActionsConfig;
96
- }): [
97
- ContextHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>,
98
- ContextProvider<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>,
99
- ReactContext<StateHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata> | null>
100
- ];
212
+ }): {
213
+ use: ContextHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
214
+ Provider: ContextProvider<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
215
+ Context: ReactContext<ContextHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata> | null>;
216
+ };
101
217
  }
218
+ /**
219
+ * @description Creates a highly granular React context with its associated provider and state hook.
220
+ * Unlike the native `React.createContext`, this version provides fine-grained reactivity and supports
221
+ * state selection, metadata handling, and optional custom actions for controlled mutations.
222
+ *
223
+ * Components using the generated hook only re-render when the selected part of the state changes,
224
+ * making it efficient for large or deeply nested state trees.
225
+ */
102
226
  export declare const createContext: CreateContext;
103
- export type InferContextType<Provider extends ContextProvider<any, any, any>> = ReturnType<Provider['makeProviderWrapper']>['context']['current'];
227
+ /**
228
+ * @description Infers the context API type
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * const counter = createContext(0);
233
+ *
234
+ * type CounterContextApi = InferContextApi<typeof counter.Context>;
235
+ *
236
+ * // Equivalent to:
237
+ * ContextApi<number, React.Dispatch<React.SetStateAction<number>>, BaseMetadata>;
238
+ * ```
239
+ */
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;
104
241
  export default createContext;
package/createContext.js CHANGED
@@ -1 +1,70 @@
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);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,s=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:{}})),c=s.getHook();return{store:s,parentHook:c}}),[]),v=f.store,d=f.parentHook;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),null===(o=(r=v).__onUnMountContext)||void 0===o||o.call(r,v,d),v.dispose()}}),[v,d]),null==c||c(v.getConfigCallbackParam()),(0,o.createElement)(r.Provider,{value:d},s)},s=function(){var e=(0,o.useContext)(r);if(!e)throw new Error("ContextHook must be used within a ContextProvider");return e.apply(void 0,arguments)};s.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(0,i.isNil)(e)?n: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)}};var l=function(){var e=(0,o.useContext)(r);if((0,i.isNil)(e))throw new Error("useStateControls must be used within a ContextProvider");return e.stateControls()},c=function(e,t){var n=(0,o.useContext)(r);if((0,i.isNil)(n))throw new Error("useObservableBuilder must be used within a ContextProvider");return n.createObservable(e,t)};return s.stateControls=function(){return[l,c]},u.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}},[s,u,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"]);
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,19 +1,146 @@
1
- import type { ActionCollectionConfig, StateSetter, ActionCollectionResult, StateHook, BaseMetadata, GlobalStoreCallbacks } from './types';
1
+ import type { ActionCollectionConfig, ActionCollectionResult, StateHook, BaseMetadata, GlobalStoreCallbacks } from './types';
2
2
  export interface CreateGlobalState {
3
- <State>(state: State): StateHook<State, StateSetter<State>, BaseMetadata>;
4
- <State, Metadata extends BaseMetadata | unknown, ActionsConfig extends ActionCollectionConfig<State, Metadata> | null | {}, PublicStateMutator = keyof ActionsConfig extends never | undefined ? StateSetter<State> : ActionCollectionResult<State, Metadata, NonNullable<ActionsConfig>>>(state: State, args: {
3
+ /**
4
+ * Creates a global state hook.
5
+ * @param state initial state value
6
+ * @returns a state hook for your components
7
+ * @example
8
+ * const useCounter = createGlobalState(0);
9
+ *
10
+ * function Counter() {
11
+ * const [count, setCount] = useCounter();
12
+ * return (
13
+ * <div>
14
+ * <p>Count: {count}</p>
15
+ * <button onClick={() =>
16
+ * setCount(prev => prev + 1)
17
+ * }>Increment</button>
18
+ * </div>
19
+ * );
20
+ * }
21
+ */
22
+ <State, StateDispatch = React.Dispatch<React.SetStateAction<State>>>(state: State): StateHook<State, StateDispatch, StateDispatch, BaseMetadata>;
23
+ /**
24
+ * Creates a global state hook that you can use across your application
25
+ * @param state initial state value
26
+ * @param args additional configuration for the global state
27
+ * @param args.name optional name for debugging purposes
28
+ * @param args.metadata optional non-reactive metadata associated with the state
29
+ * @param args.callbacks optional lifecycle callbacks for the global state
30
+ * @param args.actions optional actions to restrict state mutations [if provided `setState` will be nullified]
31
+ * @returns a state hook that you can use in your components
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * const useCounter = createGlobalState(0, {
36
+ * actions: {
37
+ * increase() {
38
+ * return ({ setState }) => {
39
+ * setState((c) => c + 1);
40
+ * };
41
+ * },
42
+ * decrease(amount: number) {
43
+ * return ({ setState }) => {
44
+ * setState((c) => c - amount);
45
+ * };
46
+ * },
47
+ * },
48
+ * });
49
+ *
50
+ * function Counter() {
51
+ * const [count, {
52
+ * increase,
53
+ * decrease
54
+ * }] = useCounter();
55
+ *
56
+ * return (
57
+ * <div>
58
+ * <p>Count: {count}</p>
59
+ * <button onClick={increase}>
60
+ * Increment
61
+ * </button>
62
+ * <button onClick={() => {
63
+ * decrease(1);
64
+ * }}>
65
+ * Decrement
66
+ * </button>
67
+ * </div>
68
+ * );
69
+ * }
70
+ * ```
71
+ */
72
+ <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: {
5
73
  name?: string;
6
74
  metadata?: Metadata;
7
75
  callbacks?: GlobalStoreCallbacks<State, Metadata>;
8
76
  actions?: ActionsConfig;
9
- }): StateHook<State, PublicStateMutator, Metadata>;
10
- <State, Metadata extends BaseMetadata | unknown, ActionsConfig extends ActionCollectionConfig<State, Metadata>>(state: State, args: {
77
+ }): StateHook<State, StateDispatch, PublicStateMutator, Metadata>;
78
+ /**
79
+ * Creates a global state hook that you can use across your application
80
+ * @param state initial state value
81
+ * @param args additional configuration for the global state
82
+ * @param args.name optional name for debugging purposes
83
+ * @param args.metadata optional non-reactive metadata associated with the state
84
+ * @param args.callbacks optional lifecycle callbacks for the global state
85
+ * @param args.actions optional actions to restrict state mutations [if provided `setState` will be nullified]
86
+ * @returns a state hook that you can use in your components
87
+ *
88
+ * @example
89
+ * ```tsx
90
+ * const useCounter = createGlobalState(0, {
91
+ * actions: {
92
+ * increase() {
93
+ * return ({ setState }) => {
94
+ * setState((c) => c + 1);
95
+ * };
96
+ * },
97
+ * decrease(amount: number) {
98
+ * return ({ setState }) => {
99
+ * setState((c) => c - amount);
100
+ * };
101
+ * },
102
+ * },
103
+ * });
104
+ *
105
+ * function Counter() {
106
+ * const [count, {
107
+ * increase,
108
+ * decrease
109
+ * }] = useCounter();
110
+ *
111
+ * return (
112
+ * <div>
113
+ * <p>Count: {count}</p>
114
+ * <button onClick={increase}>
115
+ * Increment
116
+ * </button>
117
+ * <button onClick={() => {
118
+ * decrease(1);
119
+ * }}>
120
+ * Decrement
121
+ * </button>
122
+ * </div>
123
+ * );
124
+ * }
125
+ * ```
126
+ */
127
+ <State, Metadata extends BaseMetadata, ActionsConfig extends ActionCollectionConfig<State, Metadata>, StateDispatch = React.Dispatch<React.SetStateAction<State>>>(state: State, args: {
11
128
  name?: string;
12
129
  metadata?: Metadata;
13
130
  callbacks?: GlobalStoreCallbacks<State, Metadata>;
14
131
  actions: ActionsConfig;
15
- }): StateHook<State, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
132
+ }): StateHook<State, StateDispatch, ActionCollectionResult<State, Metadata, ActionsConfig>, Metadata>;
16
133
  }
134
+ /**
135
+ * Creates a global state hook
136
+ */
17
137
  export declare const createGlobalState: CreateGlobalState;
18
- export type InferActionsType<Hook extends StateHook<any, any, any>> = ReturnType<Hook['stateControls']>['1'];
138
+ /**
139
+ * Infers the actions type from a StateHook
140
+ * @example
141
+ * ```ts
142
+ * type CounterActions = InferActionsType<typeof useCounter>;
143
+ * ```
144
+ */
145
+ export type InferActionsType<Hook extends StateHook<any, any, any, any>> = ReturnType<Hook['actions']>['1'];
19
146
  export default createGlobalState;