react-shared-states 1.0.8 → 1.0.12

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/README.md CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  # React Shared States
3
2
 
4
3
  **_Global state made as simple as useState, with zero config, built-in async caching, and automatic scoping._**
@@ -24,7 +23,7 @@ Tiny, ergonomic, convention‑over‑configuration state, async function, and re
24
23
  * Predictable: key + scope ⇒ value. That’s it.
25
24
 
26
25
 
27
- ## 🚀 Install
26
+ ## Install
28
27
 
29
28
  ```sh
30
29
  npm install react-shared-states
@@ -34,7 +33,7 @@ or
34
33
  pnpm add react-shared-states
35
34
  ```
36
35
 
37
- ## 60‑Second TL;DR
36
+ ## 60‑Second TL;DR
38
37
  ```tsx
39
38
  import { useSharedState } from 'react-shared-states';
40
39
 
@@ -197,66 +196,105 @@ export default function App(){
197
196
  ```
198
197
 
199
198
 
200
- ## 🧠 Core Concepts
201
- | Concept | Summary |
202
- |------------------------|---------------------------------------------------------------------------------------------------------------------------------|
203
- | Global by default | No provider necessary. Same key => shared state. |
204
- | Scoping | Wrap with `SharedStatesProvider` to isolate. Nearest provider wins. |
205
- | Named scopes | `scopeName` prop lets distant providers sync (same name ⇒ same bucket). Unnamed providers auto‑generate a random isolated name. |
206
- | Manual override | Third param in `useSharedState` / `useSharedFunction` / `useSharedSubscription` enforces a specific scope ignoring tree search. |
207
- | Shared functions | Encapsulate async logic: single flight + cached result + `error` + `isLoading` + opt‑in refresh. |
208
- | Shared subscriptions | Real-time data streams: automatic cleanup + shared connections + `error` + `isLoading` + subscription state. |
209
- | Static APIs | Access state/functions/subscriptions outside components (`sharedStatesApi`, `sharedFunctionsApi`, `sharedSubscriptionsApi`). |
210
- | Static/shared creation | Use `createSharedState`, `createSharedFunction`, `createSharedSubscription` to export reusable, type-safe shared resources. |
211
-
212
-
213
- ## 🏗️ Sharing State (`useSharedState`)
214
- Signature:
215
- - `const [value, setValue] = useSharedState(key, initialValue, scopeName?)`
216
- - `const [value, setValue] = useSharedState(sharedStateCreated)`
217
-
218
- Behavior:
219
- * First hook call (per key + scope) seeds with `initialValue`.
220
- * Subsequent mounts with same key+scope ignore their `initialValue` (consistent source of truth).
221
- * Setter accepts either value or updater `(prev)=>next`.
222
- * React batching + equality check: listeners fire only when the value reference actually changes.
223
-
224
- ### Examples
225
- 1. Global theme (recommended for large apps)
226
- ```tsx
227
- // themeState.ts
228
- export const themeState = createSharedState('light');
229
- // In components
230
- const [theme, setTheme] = useSharedState(themeState);
231
- ```
232
- 2. Isolated wizard progress
233
- ```tsx
234
- const wizardProgress = createSharedState(0);
235
- <SharedStatesProvider>
236
- <Wizard/>
237
- </SharedStatesProvider>
238
- // In Wizard
239
- const [step, setStep] = useSharedState(wizardProgress);
240
- ```
241
- 3. Forcing cross‑portal sync
242
- ```tsx
243
- const navState = createSharedState('closed', 'nav');
244
- <SharedStatesProvider scopeName="nav" children={<PrimaryNav/>} />
245
- <Portal>
246
- <SharedStatesProvider scopeName="nav" children={<MobileNav/>} />
247
- </Portal>
248
- // In both navs
249
- const [navOpen, setNavOpen] = useSharedState(navState);
250
- ```
251
- 4. Overriding nearest provider
252
- ```tsx
253
- // Even if inside a provider, this explicitly binds to global
254
- const globalFlag = createSharedState(false, '_global');
255
- const [flag, setFlag] = useSharedState(globalFlag);
256
- ```
257
-
258
-
259
- ## ⚡ Shared Async Functions (`useSharedFunction`)
199
+ ## Core Concepts
200
+ | Concept | Summary |
201
+ |------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
202
+ | Global by default | No provider necessary. Same key => shared state. |
203
+ | Scoping | Wrap with `SharedStatesProvider` to isolate. Nearest provider wins. |
204
+ | Named scopes | `scopeName` prop lets distant providers sync (same name ⇒ same bucket). Unnamed providers auto‑generate a random isolated name. |
205
+ | Manual override | Third param in `useSharedState` / `useSharedFunction` / `useSharedSubscription` enforces a specific scope ignoring tree search. |
206
+ | Shared functions | Encapsulate async logic: single flight + cached result + `error` + `isLoading` + opt‑in refresh. |
207
+ | Shared subscriptions | Real-time data streams: automatic cleanup + shared connections + `error` + `isLoading` + subscription state. |
208
+ | Static APIs | Access state/functions/subscriptions outside components (`sharedStatesApi`, `sharedFunctionsApi`, `sharedSubscriptionsApi`). |
209
+ | Static/shared creation | Use `createSharedState`, `createSharedFunction`, `createSharedSubscription` to export reusable, type-safe shared resources that persist across `clearAll()` calls. |
210
+
211
+
212
+ ## Selecting State Slices (`useSharedStateSelector`)
213
+
214
+ When a shared state holds an object, you might only need a small piece of it.
215
+ Using `useSharedState` will cause your component to re-render whenever *any* part of the object changes.
216
+ To optimize performance and avoid unnecessary re-renders, you can use the `useSharedStateSelector` hook.
217
+
218
+ This hook allows you to subscribe to a specific, memoized slice of a shared state.
219
+ Your component will only re-render if the selected value changes.
220
+ It uses `react-fast-compare` for efficient deep equality checks.
221
+
222
+ Signature:
223
+ - `const selectedValue = useSharedStateSelector(key, selector, scopeName?)`
224
+ - `const selectedValue = useSharedStateSelector(sharedStateCreated, selector)`
225
+
226
+ The `selector` is a function that receives the full state and returns the desired slice.
227
+
228
+ ### Example: Subscribing to a slice of a user object
229
+
230
+ Imagine a shared state for user settings:
231
+
232
+ ```tsx
233
+ // settingsState.ts
234
+ import { createSharedState } from 'react-shared-states';
235
+
236
+ export const settingsState = createSharedState({
237
+ theme: 'dark',
238
+ notifications: {
239
+ email: true,
240
+ push: false,
241
+ },
242
+ language: 'en',
243
+ });
244
+ ```
245
+
246
+ A component that only cares about the theme can use `useSharedStateSelector` to avoid re-rendering when, for example, the notification settings change.
247
+
248
+ ```tsx
249
+ import { useSharedState, useSharedStateSelector } from 'react-shared-states';
250
+ import { settingsState } from './settingsState';
251
+
252
+ function ThemeDisplay() {
253
+ const theme = useSharedStateSelector(settingsState, (settings) => settings.theme);
254
+
255
+ console.log('ThemeDisplay renders'); // This will only log when the theme changes
256
+
257
+ return <div>Current theme: {theme}</div>;
258
+ }
259
+
260
+ function NotificationToggle() {
261
+ const [settings, setSettings] = useSharedState(settingsState);
262
+
263
+ const togglePush = () => {
264
+ setSettings(s => ({
265
+ ...s,
266
+ notifications: { ...s.notifications, push: !s.notifications.push }
267
+ }));
268
+ };
269
+
270
+ return <button onClick={togglePush}>Toggle Push Notifications</button>;
271
+ }
272
+ ```
273
+
274
+ In this example, clicking the `NotificationToggle` button will **not** cause `ThemeDisplay` to re-render.
275
+
276
+ ### A Note on Type Safety
277
+
278
+ For the best developer experience and full type safety,
279
+ it is **highly recommended** to use `useSharedStateSelector` with a statically created shared state object from `createSharedState`.
280
+
281
+ When you use a string key directly, the hook cannot infer the type of the state object.
282
+ You would have to provide the types explicitly as generic arguments, or they will default to `any`.
283
+
284
+ ```tsx
285
+ // Less safe: using a string key
286
+ // You have to specify the types manually.
287
+ const theme = useSharedStateSelector<{ theme: string; /*...other props*/ }, 'settings', string>(
288
+ 'settings',
289
+ (settings) => settings.theme
290
+ );
291
+
292
+ // Recommended: using a created state object
293
+ // Types are inferred automatically!
294
+ const theme = useSharedStateSelector(settingsState, (settings) => settings.theme);
295
+ ```
296
+
297
+ ## Shared Async Functions (`useSharedFunction`)
260
298
  Signature:
261
299
  - `const { state, trigger, forceTrigger, clear } = useSharedFunction(key, asyncFn, scopeName?)`
262
300
  - `const { state, trigger, forceTrigger, clear } = useSharedFunction(sharedFunctionCreated)`
@@ -267,6 +305,7 @@ Semantics:
267
305
  * Multiple components with the same key+scope share one execution + result.
268
306
  * `clear()` deletes the cache (next trigger re-runs).
269
307
  * You decide when to invoke `trigger` (e.g. on mount, on button click, when dependencies change, etc.).
308
+ * Functions created with `createSharedFunction` are **static** and persist across `clearAll()` calls.
270
309
 
271
310
  ### Pattern: lazy load on first render
272
311
  ```tsx
@@ -286,7 +325,7 @@ const refresh = () => forceTrigger();
286
325
  ```
287
326
 
288
327
 
289
- ## 📡 Real-time Subscriptions (`useSharedSubscription`)
328
+ ## Real-time Subscriptions (`useSharedSubscription`)
290
329
  Perfect for Firebase listeners, WebSocket connections,
291
330
  Server-Sent Events, or any streaming data source that needs cleanup.
292
331
 
@@ -298,8 +337,8 @@ Signature:
298
337
 
299
338
  The `subscriber` function receives three callbacks:
300
339
  - `set(data)`: Update the shared data
301
- - `onError(error)`: Handle errors
302
- - `onCompletion()`: Mark loading as complete
340
+ - `error(error)`: Handle errors
341
+ - `complete()`: Mark loading as complete
303
342
  - Returns: Optional cleanup function (called on unsubscribe/unmount)
304
343
 
305
344
  ### Pattern: Firebase Firestore real-time listener
@@ -310,8 +349,23 @@ import { createSharedSubscription } from 'react-shared-states';
310
349
  import { db } from './firebase-config';
311
350
 
312
351
  export const userSubscription = createSharedSubscription(
313
- async (set, onError, onCompletion) => {
314
- // ...same as before
352
+ (set, error, complete) => {
353
+ const userDocRef = doc(db, 'users', 'some-user-id');
354
+ const unsubscribe = onSnapshot(userDocRef,
355
+ (doc) => {
356
+ if (doc.exists()) {
357
+ set(doc.data());
358
+ } else {
359
+ error(new Error('User not found'));
360
+ }
361
+ complete();
362
+ },
363
+ (err) => {
364
+ error(err);
365
+ complete();
366
+ }
367
+ );
368
+ return unsubscribe;
315
369
  }
316
370
  );
317
371
 
@@ -344,15 +398,15 @@ import { useSharedSubscription } from 'react-shared-states';
344
398
  function ChatRoom({ roomId }: { roomId: string }) {
345
399
  const { state, trigger } = useSharedSubscription(
346
400
  `chat-${roomId}`,
347
- (set, onError, onCompletion) => {
401
+ (set, error, complete) => {
348
402
  const ws = new WebSocket(`ws://chat-server/${roomId}`);
349
403
 
350
- ws.onopen = () => onCompletion();
404
+ ws.onopen = () => complete();
351
405
  ws.onmessage = (event) => {
352
406
  const message = JSON.parse(event.data);
353
407
  set(prev => [...(prev || []), message]);
354
408
  };
355
- ws.onerror = onError;
409
+ ws.onerror = error;
356
410
 
357
411
  return () => ws.close();
358
412
  }
@@ -384,14 +438,14 @@ import { useSharedSubscription } from 'react-shared-states';
384
438
  function LiveUpdates() {
385
439
  const { state, trigger } = useSharedSubscription(
386
440
  'live-updates',
387
- (set, onError, onCompletion) => {
441
+ (set, error, complete) => {
388
442
  const eventSource = new EventSource('/api/live-updates');
389
443
 
390
- eventSource.onopen = () => onCompletion();
444
+ eventSource.onopen = () => complete();
391
445
  eventSource.onmessage = (event) => {
392
446
  set(JSON.parse(event.data));
393
447
  };
394
- eventSource.onerror = onError;
448
+ eventSource.onerror = error;
395
449
 
396
450
  return () => eventSource.close();
397
451
  }
@@ -413,10 +467,12 @@ Subscription semantics:
413
467
  * Components mounting later instantly get the latest `data` without re-subscribing.
414
468
 
415
469
 
416
- ## 🛰️ Static APIs (outside React)
417
- ## 🏛️ Static/Global Shared Resource Creation
470
+ ## Static APIs (outside React)
471
+ ## Static/Global Shared Resource Creation
418
472
 
419
- For large apps, you can create and export shared state, function, or subscription objects for type safety and to avoid key collisions. This pattern is similar to Zustand or Jotai stores:
473
+ For large apps, you can create and export shared state, function,
474
+ or subscription objects for type safety and to avoid key collisions.
475
+ This pattern is similar to Zustand or Jotai stores:
420
476
 
421
477
  ```ts
422
478
  import { createSharedState, createSharedFunction, createSharedSubscription, useSharedState, useSharedFunction, useSharedSubscription } from 'react-shared-states';
@@ -424,7 +480,7 @@ import { createSharedState, createSharedFunction, createSharedSubscription, useS
424
480
  // Create and export shared resources
425
481
  export const counterState = createSharedState(0);
426
482
  export const fetchUserFunction = createSharedFunction(() => fetch('/api/me').then(r => r.json()));
427
- export const chatSubscription = createSharedSubscription((set, onError, onCompletion) => {/* ... */});
483
+ export const chatSubscription = createSharedSubscription((set, error, complete) => {/* ... */});
428
484
 
429
485
  // Use anywhere in your app
430
486
  const [count, setCount] = useSharedState(counterState);
@@ -463,16 +519,16 @@ const subStateScoped = sharedSubscriptionsApi.get('live-chat', 'myScope');
463
519
 
464
520
  ## API summary:
465
521
 
466
- | API | Methods |
467
- |--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
468
- | `sharedStatesApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll()`, `clearScope(scopeName?)`, `getAll()` |
469
- | `sharedFunctionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll()`, `clearScope(scopeName?)`, `getAll()` |
470
- | `sharedSubscriptionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll()`, `clearScope(scopeName?)`, `getAll()` |
522
+ | API | Methods |
523
+ |--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
524
+ | `sharedStatesApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
525
+ | `sharedFunctionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
526
+ | `sharedSubscriptionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
471
527
 
472
528
  `scopeName` defaults to `"_global"`. Internally, keys are stored as `${scope}//${key}`. The `.getAll()` method returns a nested object: `{ [scope]: { [key]: value } }`.
473
529
 
474
530
 
475
- ## 🧩 Scoping Rules Deep Dive
531
+ ## Scoping Rules Deep Dive
476
532
  Resolution order used inside hooks:
477
533
  1. Explicit 3rd parameter (`scopeName`)
478
534
  2. Nearest `SharedStatesProvider` above the component
@@ -483,7 +539,7 @@ Unnamed providers auto‑generate a random scope name: each mount = isolated isl
483
539
  Two providers sharing the same `scopeName` act as a single logical scope even if they are disjoint in the tree (great for portals / microfrontends).
484
540
 
485
541
 
486
- ## 🆚 Comparison Snapshot
542
+ ## Comparison Snapshot
487
543
  | Criterion | react-shared-states | Redux Toolkit | Zustand |
488
544
  |----------------|------------------------------------------|----------------------|----------------------------------|
489
545
  | Setup | Install & call hook | Slice + store config | Create store function |
@@ -495,16 +551,16 @@ Two providers sharing the same `scopeName` act as a single logical scope even if
495
551
  | Learning curve | Minutes | Higher | Low |
496
552
 
497
553
 
498
- ## 🧪 Testing Tips
554
+ ## Testing Tips
499
555
  * Use static APIs to assert state after component interactions.
500
- * `sharedStatesApi.clearAll()`, `sharedFunctionsApi.clearAll()`, `sharedSubscriptionsApi.clearAll()` in `afterEach` to isolate tests.
556
+ * `sharedStatesApi.clearAll(false, true)`, `sharedFunctionsApi.clearAll(false, true)`, `sharedSubscriptionsApi.clearAll(false, true)` in `afterEach` to isolate tests and clear static states.
501
557
  * For async functions: trigger once, await UI stabilization, assert `results` present.
502
558
  * For subscriptions: mock the subscription source (Firebase, WebSocket, etc.) and verify data flow.
503
559
 
504
560
 
505
561
  ## ❓ FAQ
506
562
  **Q: How do I reset a single shared state?**
507
- `sharedStatesApi.clear('key')` or inside component: call a setter with the initial value.
563
+ `sharedStatesApi.clear('key')`. If the state was created with `createSharedState`, it will reset to its initial value. Otherwise, it will be removed.
508
564
 
509
565
  **Q: Can I pre-hydrate data on the server?**
510
566
  Yes. Call `sharedStatesApi.set(...)` during bootstrap, then first client hook usage will pick it up.
@@ -522,13 +578,19 @@ Subscriptions auto-cleanup when no components are listening. You can also manual
522
578
  Currently no built-in Suspense wrappers; wrap `useSharedFunction` yourself if desired.
523
579
 
524
580
 
525
- ## 📚 Full API Reference
581
+ ## Full API Reference
526
582
  ### `useSharedState(key, initialValue, scopeName?)`
527
583
  Returns `[value, setValue]`.
528
584
 
529
585
  ### `useSharedState(sharedStateCreated)`
530
586
  Returns `[value, setValue]`.
531
587
 
588
+ ### `useSharedStateSelector(key, selector, scopeName?)`
589
+ Returns the selected value.
590
+
591
+ ### `useSharedStateSelector(sharedStateCreated, selector)`
592
+ Returns the selected value.
593
+
532
594
  ### `useSharedFunction(key, fn, scopeName?)`
533
595
  Returns `{ state, trigger, forceTrigger, clear }`.
534
596
 
@@ -549,7 +611,7 @@ Wrap children; optional `scopeName` (string). If omitted a random unique one is
549
611
 
550
612
 
551
613
 
552
- ## 🤝 Contributions
614
+ ## Contributions
553
615
 
554
616
  We welcome contributions!
555
617
  If you'd like to improve `react-shared-states`,
@@ -567,4 +629,6 @@ feel free to [open an issue](https://github.com/HichemTab-tech/react-shared-stat
567
629
  ## 🌟 Acknowledgements
568
630
 
569
631
  Inspired by React's built-in primitives and the ergonomics of modern lightweight state libraries.
570
- Thanks to early adopters for feedback.
632
+ Thanks to early adopters for feedback.
633
+ If you'd like to improve `react-shared-states`,
634
+ feel free to [open an issue](https://github.com/HichemTab-tech/react-shared-states/issues) or [submit a pull request](https://github.com/HichemTab-tech/react-shared-states/pulls).
@@ -1,37 +1,44 @@
1
- import { AFunction, DataMapValue, Prefix, SharedCreated } from './types';
2
- type SharedDataType<T> = DataMapValue & T;
3
- export declare abstract class SharedData<T> {
4
- data: Map<string, SharedDataType<T>>;
5
- defaultValue(): T;
1
+ import { AFunction, Prefix, SharedCreated, SharedValue } from './types';
2
+ export declare const staticStores: SharedCreated[];
3
+ export declare abstract class SharedValuesManager<T extends SharedValue, V> {
4
+ data: Map<string, T>;
5
+ defaultValue(): V;
6
6
  addListener(key: string, prefix: Prefix, listener: AFunction): void;
7
7
  removeListener(key: string, prefix: Prefix, listener: AFunction): void;
8
8
  callListeners(key: string, prefix: Prefix): void;
9
- init(key: string, prefix: Prefix, data: T): void;
10
- clearAll(withoutListeners?: boolean): void;
11
- clear(key: string, prefix: Prefix, withoutListeners?: boolean): void;
12
- get(key: string, prefix: Prefix): SharedDataType<T> | undefined;
13
- setValue(key: string, prefix: Prefix, data: T): void;
9
+ init(key: string, prefix: Prefix, data: V, isStatic?: boolean): void;
10
+ createStatic<X extends SharedCreated>(rest: Omit<X, 'key' | 'prefix'>, scopeName?: Prefix): {
11
+ key: string;
12
+ prefix: Prefix;
13
+ } & Omit<X, "key" | "prefix">;
14
+ initStatic(sharedCreated: SharedCreated): void;
15
+ clearAll(withoutListeners?: boolean, withStatic?: boolean): void;
16
+ clear(key: string, prefix: Prefix, withoutListeners?: boolean, withStatic?: boolean): void;
17
+ get(key: string, prefix: Prefix): T | undefined;
18
+ setValue(key: string, prefix: Prefix, data: V): void;
14
19
  has(key: string, prefix: Prefix): string | undefined;
15
20
  static prefix(key: string, prefix: Prefix): string;
16
21
  static extractPrefix(mapKey: string): string[];
17
22
  useEffect(key: string, prefix: Prefix, unsub?: (() => void) | null): void;
18
23
  }
19
- export declare class SharedApi<T> {
20
- private sharedData;
21
- constructor(sharedData: SharedData<T>);
24
+ export declare class SharedValuesApi<T extends SharedValue, V, R = T> {
25
+ protected sharedData: SharedValuesManager<T, V>;
26
+ constructor(sharedData: SharedValuesManager<T, V>);
22
27
  /**
23
28
  * get a value from the shared data
24
29
  * @param key
25
30
  * @param scopeName
26
31
  */
27
- get<S extends string = string>(key: S, scopeName: Prefix): T;
32
+ get<S extends string = string>(key: S, scopeName: Prefix): R;
33
+ get<S extends string = string>(sharedCreated: SharedCreated): R;
28
34
  /**
29
35
  * set a value in the shared data
30
36
  * @param key
31
37
  * @param value
32
38
  * @param scopeName
33
39
  */
34
- set<S extends string = string>(key: S, value: T, scopeName: Prefix): void;
40
+ set<S extends string = string>(key: S, value: V, scopeName: Prefix): void;
41
+ set<S extends string = string>(sharedCreated: SharedCreated, value: V): void;
35
42
  /**
36
43
  * clear all values from the shared data
37
44
  */
@@ -45,7 +52,12 @@ export declare class SharedApi<T> {
45
52
  * resolve a shared created object to a value
46
53
  * @param sharedCreated
47
54
  */
48
- resolve(sharedCreated: SharedCreated): T;
55
+ resolve(sharedCreated: SharedCreated): R;
56
+ /**
57
+ * clear a value from the shared data
58
+ * @param key
59
+ * @param scopeName
60
+ */
49
61
  clear(key: string, scopeName: Prefix): void;
50
62
  clear(sharedCreated: SharedCreated): void;
51
63
  /**
@@ -59,4 +71,3 @@ export declare class SharedApi<T> {
59
71
  */
60
72
  getAll(): Record<string, Record<string, any>>;
61
73
  }
62
- export {};
@@ -1,5 +1,5 @@
1
- export { useSharedState, sharedStatesApi, createSharedState, SharedStatesApi } from './use-shared-state';
2
- export type { SharedStateCreated } from './use-shared-state';
1
+ export { useSharedState, sharedStatesApi, createSharedState, SharedStatesApi, useSharedStateSelector } from './use-shared-state';
2
+ export type { SharedStateCreated, SharedStateSelector } from './use-shared-state';
3
3
  export { useSharedFunction, sharedFunctionsApi, createSharedFunction, SharedFunctionsApi } from './use-shared-function';
4
4
  export type { SharedFunctionStateReturn } from './use-shared-function';
5
5
  export { useSharedSubscription, sharedSubscriptionsApi, createSharedSubscription, SharedSubscriptionsApi } from './use-shared-subscription';
@@ -1,15 +1,40 @@
1
- import { AFunction, Prefix, SharedCreated } from '../types';
2
- import { SharedApi } from '../SharedData';
3
- type SharedFunctionsState<T> = {
4
- fnState: {
5
- results?: T;
6
- isLoading: boolean;
7
- error?: unknown;
8
- };
1
+ import { AFunction, Prefix, SharedCreated, SharedValue } from '../types';
2
+ import { SharedValuesApi, SharedValuesManager } from '../SharedValuesManager';
3
+ type SharedFunctionValue<T> = {
4
+ results?: T;
5
+ isLoading: boolean;
6
+ error?: unknown;
9
7
  };
10
- export declare class SharedFunctionsApi extends SharedApi<SharedFunctionsState<unknown>> {
11
- get<T, S extends string = string>(key: S, scopeName?: Prefix): T;
12
- set<T, S extends string = string>(key: S, fnState: SharedFunctionsState<T>, scopeName?: Prefix): void;
8
+ interface SharedFunction<T> extends SharedValue {
9
+ fnState: SharedFunctionValue<T>;
10
+ }
11
+ declare class SharedFunctionsManager extends SharedValuesManager<SharedFunction<unknown>, {
12
+ fnState: SharedFunctionValue<unknown>;
13
+ }> {
14
+ defaultValue(): {
15
+ fnState: {
16
+ results: undefined;
17
+ isLoading: boolean;
18
+ error: undefined;
19
+ };
20
+ };
21
+ initValue(key: string, prefix: Prefix, isStatic?: boolean): void;
22
+ setValue<T>(key: string, prefix: Prefix, data: {
23
+ fnState: SharedFunctionValue<T>;
24
+ }): void;
25
+ }
26
+ export declare class SharedFunctionsApi extends SharedValuesApi<SharedFunction<unknown>, {
27
+ fnState: SharedFunctionValue<unknown>;
28
+ }, SharedFunctionValue<unknown>> {
29
+ constructor(sharedFunctionManager: SharedFunctionsManager);
30
+ get<T, S extends string = string>(key: S, scopeName?: Prefix): SharedFunctionValue<T>;
31
+ get<T, Args extends unknown[]>(sharedFunctionCreated: SharedFunctionCreated<T, Args>): SharedFunctionValue<T>;
32
+ set<T, S extends string = string>(key: S, value: {
33
+ fnState: SharedFunctionValue<T>;
34
+ }, scopeName?: Prefix): void;
35
+ set<T, Args extends unknown[]>(sharedFunctionCreated: SharedFunctionCreated<T, Args>, value: {
36
+ fnState: SharedFunctionValue<T>;
37
+ }): void;
13
38
  }
14
39
  export declare const sharedFunctionsApi: SharedFunctionsApi;
15
40
  interface SharedFunctionCreated<T, Args extends unknown[]> extends SharedCreated {
@@ -17,7 +42,7 @@ interface SharedFunctionCreated<T, Args extends unknown[]> extends SharedCreated
17
42
  }
18
43
  export declare const createSharedFunction: <T, Args extends unknown[]>(fn: AFunction<T, Args>, scopeName?: Prefix) => SharedFunctionCreated<T, Args>;
19
44
  export type SharedFunctionStateReturn<T, Args extends unknown[]> = {
20
- readonly state: NonNullable<SharedFunctionsState<T>['fnState']>;
45
+ readonly state: NonNullable<SharedFunctionValue<T>>;
21
46
  readonly trigger: (...args: Args) => void;
22
47
  readonly forceTrigger: (...args: Args) => void;
23
48
  readonly clear: () => void;
@@ -1,10 +1,25 @@
1
- import { Prefix, SharedCreated } from '../types';
2
- import { SharedApi } from '../SharedData';
3
- export declare class SharedStatesApi extends SharedApi<{
1
+ import { Prefix, SharedCreated, SharedValue } from '../types';
2
+ import { SharedValuesApi, SharedValuesManager } from '../SharedValuesManager';
3
+ interface SharedState<T> extends SharedValue {
4
+ value: T;
5
+ }
6
+ declare class SharedStatesManager extends SharedValuesManager<SharedState<unknown>, {
4
7
  value: unknown;
5
8
  }> {
9
+ defaultValue(): {
10
+ value: undefined;
11
+ };
12
+ initValue(key: string, prefix: Prefix, value: unknown, isStatic?: boolean): void;
13
+ initStatic(sharedStateCreated: SharedStateCreated<any>): void;
14
+ }
15
+ export declare class SharedStatesApi extends SharedValuesApi<SharedState<unknown>, {
16
+ value: unknown;
17
+ }, unknown> {
18
+ constructor(sharedStateManager: SharedStatesManager);
6
19
  get<T, S extends string = string>(key: S, scopeName?: Prefix): T;
20
+ get<T>(sharedStateCreated: SharedStateCreated<T>): T;
7
21
  set<T, S extends string = string>(key: S, value: T, scopeName?: Prefix): void;
22
+ set<T>(sharedStateCreated: SharedStateCreated<T>, value: T): void;
8
23
  }
9
24
  export declare const sharedStatesApi: SharedStatesApi;
10
25
  export interface SharedStateCreated<T> extends SharedCreated {
@@ -13,3 +28,7 @@ export interface SharedStateCreated<T> extends SharedCreated {
13
28
  export declare const createSharedState: <T>(initialValue: T, scopeName?: Prefix) => SharedStateCreated<T>;
14
29
  export declare function useSharedState<T, S extends string>(key: S, initialValue: T, scopeName?: Prefix): readonly [T, (v: T | ((prev: T) => T)) => void];
15
30
  export declare function useSharedState<T>(sharedStateCreated: SharedStateCreated<T>): readonly [T, (v: T | ((prev: T) => T)) => void];
31
+ export type SharedStateSelector<S, T = S> = (original: S) => T;
32
+ export declare function useSharedStateSelector<T, S extends string, R>(key: S, selector: SharedStateSelector<T, R>, scopeName?: Prefix): Readonly<R>;
33
+ export declare function useSharedStateSelector<T, R>(sharedStateCreated: SharedStateCreated<T>, selector: SharedStateSelector<T, R>): Readonly<R>;
34
+ export {};