@choksheak/react-utils 0.3.6 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/NoSSR.cjs +37 -0
  2. package/NoSSR.d.mts +24 -0
  3. package/NoSSR.d.ts +20 -0
  4. package/NoSSR.min.cjs +2 -0
  5. package/NoSSR.min.cjs.map +1 -0
  6. package/NoSSR.min.mjs +2 -0
  7. package/NoSSR.min.mjs.map +1 -0
  8. package/NoSSR.mjs +12 -0
  9. package/README.md +10 -1
  10. package/fetcher.cjs +3 -3
  11. package/fetcher.d.mts +5 -4
  12. package/fetcher.d.ts +4 -3
  13. package/fetcher.min.cjs +1 -1
  14. package/fetcher.min.cjs.map +1 -1
  15. package/fetcher.min.mjs +1 -1
  16. package/fetcher.min.mjs.map +1 -1
  17. package/fetcher.mjs +2 -2
  18. package/package.json +21 -3
  19. package/sharedQuery.cjs +486 -486
  20. package/sharedQuery.d.mts +64 -61
  21. package/sharedQuery.d.ts +62 -59
  22. package/sharedQuery.min.cjs +1 -1
  23. package/sharedQuery.min.cjs.map +1 -1
  24. package/sharedQuery.min.mjs +1 -1
  25. package/sharedQuery.min.mjs.map +1 -1
  26. package/sharedQuery.mjs +487 -486
  27. package/sharedState.cjs +201 -199
  28. package/sharedState.d.mts +48 -38
  29. package/sharedState.d.ts +45 -36
  30. package/sharedState.min.cjs +1 -1
  31. package/sharedState.min.cjs.map +1 -1
  32. package/sharedState.min.mjs +1 -1
  33. package/sharedState.min.mjs.map +1 -1
  34. package/sharedState.mjs +202 -199
  35. package/storage.cjs +79 -65
  36. package/storage.d.mts +39 -2
  37. package/storage.d.ts +37 -1
  38. package/storage.min.cjs +1 -1
  39. package/storage.min.cjs.map +1 -1
  40. package/storage.min.mjs +1 -1
  41. package/storage.min.mjs.map +1 -1
  42. package/storage.mjs +77 -65
  43. package/stringify.d.mts +9 -0
  44. package/stringify.d.ts +9 -0
  45. package/stringify.min.cjs.map +1 -1
  46. package/stringify.min.mjs.map +1 -1
  47. package/useDeepMemo.cjs +1 -1
  48. package/useDeepMemo.d.mts +11 -0
  49. package/useDeepMemo.d.ts +11 -0
  50. package/useDeepMemo.min.cjs +1 -1
  51. package/useDeepMemo.min.cjs.map +1 -1
  52. package/useDeepMemo.min.mjs +1 -1
  53. package/useDeepMemo.min.mjs.map +1 -1
  54. package/useDeepMemo.mjs +1 -1
package/sharedState.cjs CHANGED
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/sharedState.ts
21
21
  var sharedState_exports = {};
22
22
  __export(sharedState_exports, {
23
- SharedState: () => SharedState,
24
23
  SharedStateConfig: () => SharedStateConfig,
25
24
  configureSharedState: () => configureSharedState,
26
25
  sharedState: () => sharedState,
@@ -43,70 +42,12 @@ function getStorageAdapter(options, defaultStoreExpiryMs) {
43
42
  }
44
43
  if ("persistTo" in store && typeof store.persistTo === "string" && "key" in store && typeof store.key === "string") {
45
44
  const expiryMs = store.expiryMs || defaultStoreExpiryMs;
46
- const isValid = store.isValid;
45
+ const config = { ...store, expiryMs };
47
46
  switch (store.persistTo) {
48
- case "localStorage": {
49
- const adapter = new import_localStore.LocalStore(store.key, {
50
- defaultExpiryMs: expiryMs
51
- });
52
- return {
53
- set: (key, value) => {
54
- if (IS_NOT_BROWSER) return;
55
- adapter.set(key, value);
56
- },
57
- get: (key) => {
58
- if (IS_NOT_BROWSER) return void 0;
59
- const value = adapter.get(key);
60
- if (isValid && !isValid(value)) {
61
- console.warn(
62
- `localStorage adapter: Auto-discard invalid value for ${key}: ${JSON.stringify(value)}`
63
- );
64
- adapter.delete(key);
65
- return void 0;
66
- }
67
- return value;
68
- },
69
- delete: (key) => {
70
- if (IS_NOT_BROWSER) return;
71
- adapter.delete(key);
72
- },
73
- clear: () => {
74
- if (IS_NOT_BROWSER) return;
75
- adapter.clear();
76
- }
77
- };
78
- }
79
- case "indexedDb": {
80
- const keyPrefix = store.key + ":";
81
- const isValid2 = store.isValid;
82
- return {
83
- set: async (key, value) => {
84
- if (IS_NOT_BROWSER) return;
85
- await import_kvStore.kvStore.set(keyPrefix + key, value, expiryMs);
86
- },
87
- get: async (key) => {
88
- if (IS_NOT_BROWSER) return void 0;
89
- const fullKey = keyPrefix + key;
90
- const value = await import_kvStore.kvStore.get(fullKey);
91
- if (isValid2 && !isValid2(value)) {
92
- console.warn(
93
- `indexedDb adapter: Auto-discard invalid value for ${key}: ${JSON.stringify(value)}`
94
- );
95
- await import_kvStore.kvStore.delete(fullKey);
96
- return void 0;
97
- }
98
- return value;
99
- },
100
- delete: async (key) => {
101
- if (IS_NOT_BROWSER) return;
102
- await import_kvStore.kvStore.delete(keyPrefix + key);
103
- },
104
- clear: async () => {
105
- if (IS_NOT_BROWSER) return;
106
- await import_kvStore.kvStore.clear();
107
- }
108
- };
109
- }
47
+ case "localStorage":
48
+ return localStoreAdapter(config);
49
+ case "indexedDb":
50
+ return kvStoreAdapter(config);
110
51
  default:
111
52
  store.persistTo;
112
53
  throw new Error(`Unknown store.adapter ${store.persistTo}`);
@@ -114,6 +55,74 @@ function getStorageAdapter(options, defaultStoreExpiryMs) {
114
55
  }
115
56
  return store;
116
57
  }
58
+ function localStoreAdapter({
59
+ key,
60
+ expiryMs,
61
+ isValid
62
+ }) {
63
+ const adapter = (0, import_localStore.createLocalStore)(key, { defaultExpiryMs: expiryMs });
64
+ return {
65
+ set: (key2, value) => {
66
+ if (IS_NOT_BROWSER) return;
67
+ adapter.set(key2, value);
68
+ },
69
+ get: (key2) => {
70
+ if (IS_NOT_BROWSER) return void 0;
71
+ const value = adapter.get(key2);
72
+ if (isValid && !isValid(value)) {
73
+ console.warn(
74
+ `localStorage adapter: Auto-discard invalid value for ${key2}: ${JSON.stringify(value)}`
75
+ );
76
+ adapter.delete(key2);
77
+ return void 0;
78
+ }
79
+ return value;
80
+ },
81
+ delete: (key2) => {
82
+ if (IS_NOT_BROWSER) return;
83
+ adapter.delete(key2);
84
+ },
85
+ clear: () => {
86
+ if (IS_NOT_BROWSER) return;
87
+ adapter.clear();
88
+ }
89
+ };
90
+ }
91
+ function kvStoreAdapter({
92
+ key,
93
+ expiryMs,
94
+ isValid
95
+ }) {
96
+ const keyPrefix = key + ":";
97
+ return {
98
+ set: async (key2, value) => {
99
+ if (IS_NOT_BROWSER) return;
100
+ await import_kvStore.kvStore.set(keyPrefix + key2, value, expiryMs);
101
+ },
102
+ get: async (key2) => {
103
+ if (IS_NOT_BROWSER) return void 0;
104
+ const fullKey = keyPrefix + key2;
105
+ const value = await import_kvStore.kvStore.get(fullKey);
106
+ if (value !== void 0 && isValid && !isValid(value)) {
107
+ console.warn(
108
+ `indexedDb adapter: Auto-discard invalid value for ${key2}:`,
109
+ value
110
+ );
111
+ await import_kvStore.kvStore.delete(fullKey);
112
+ return void 0;
113
+ }
114
+ return value;
115
+ },
116
+ delete: async (key2) => {
117
+ if (IS_NOT_BROWSER) return;
118
+ await import_kvStore.kvStore.delete(keyPrefix + key2);
119
+ },
120
+ clear: async () => {
121
+ if (IS_NOT_BROWSER) return;
122
+ await import_kvStore.kvStore.clear();
123
+ }
124
+ };
125
+ }
117
126
 
118
127
  // src/sharedState.ts
119
128
  var SharedStateConfig = {
@@ -131,41 +140,11 @@ var SharedStateConfig = {
131
140
  function configureSharedState(config) {
132
141
  Object.assign(SharedStateConfig, config);
133
142
  }
134
- var PubSubStore = class {
135
- dataByKey = /* @__PURE__ */ new Map();
136
- subscribersByKey = /* @__PURE__ */ new Map();
137
- // This could be undefined if T includes undefined, else it should never
138
- // return undefined because the user has to always specify the default value.
139
- get(key) {
140
- return this.dataByKey.get(key);
141
- }
142
- set(key, value) {
143
- const prev = this.dataByKey.get(key);
144
- if (prev === value) return;
145
- this.dataByKey.set(key, value);
146
- this.notify(key, value, prev);
147
- }
148
- delete(key) {
149
- this.dataByKey.delete(key);
150
- }
151
- setNoNotify(key, value) {
152
- this.dataByKey.set(key, value);
153
- }
154
- // Subscribe to changes of a specific key
155
- subscribe(key, subscriber) {
156
- let subscribers = this.subscribersByKey.get(key);
157
- if (!subscribers) {
158
- subscribers = /* @__PURE__ */ new Set();
159
- this.subscribersByKey.set(key, subscribers);
160
- }
161
- subscribers.add(subscriber);
162
- return () => {
163
- subscribers.delete(subscriber);
164
- if (subscribers.size === 0) this.subscribersByKey.delete(key);
165
- };
166
- }
167
- notify(key, next, prev) {
168
- const subscribers = this.subscribersByKey.get(key);
143
+ function createPubSubStore() {
144
+ const dataByKey = /* @__PURE__ */ new Map();
145
+ const subscribersByKey = /* @__PURE__ */ new Map();
146
+ function notify(key, next, prev) {
147
+ const subscribers = subscribersByKey.get(key);
169
148
  if (!subscribers) return;
170
149
  const copy = Array.from(subscribers.values());
171
150
  for (const subscriber of copy) {
@@ -176,126 +155,149 @@ var PubSubStore = class {
176
155
  }
177
156
  }
178
157
  }
179
- };
180
- var pubSubStore = new PubSubStore();
158
+ return {
159
+ // This could be undefined if T includes undefined, else it should never
160
+ // return undefined because the user has to always specify the default value.
161
+ get(key) {
162
+ return dataByKey.get(key);
163
+ },
164
+ set(key, value) {
165
+ const prev = dataByKey.get(key);
166
+ if (prev === value) return;
167
+ dataByKey.set(key, value);
168
+ notify(key, value, prev);
169
+ },
170
+ delete(key) {
171
+ dataByKey.delete(key);
172
+ },
173
+ setNoNotify(key, value) {
174
+ dataByKey.set(key, value);
175
+ },
176
+ // Subscribe to changes of a specific key
177
+ subscribe(key, subscriber) {
178
+ let subscribers = subscribersByKey.get(key);
179
+ if (!subscribers) {
180
+ subscribers = /* @__PURE__ */ new Set();
181
+ subscribersByKey.set(key, subscribers);
182
+ }
183
+ subscribers.add(subscriber);
184
+ return () => {
185
+ subscribers.delete(subscriber);
186
+ if (subscribers.size === 0) subscribersByKey.delete(key);
187
+ };
188
+ }
189
+ };
190
+ }
191
+ var pubSubStore = createPubSubStore();
181
192
  var STORAGE_KEY = "state";
182
193
  var stateKey = 0;
183
- var SharedState = class {
184
- constructor(defaultValue, options) {
185
- this.defaultValue = defaultValue;
186
- let readyResolve = () => {
187
- };
188
- this.readyPromise = new Promise((resolve) => {
189
- readyResolve = resolve;
190
- });
191
- this.resolveReadyPromise = readyResolve;
192
- this.pubSubKey = String(stateKey++);
193
- this.storageAdapter = getStorageAdapter(
194
- options,
195
- SharedStateConfig.storeExpiryMs
196
- );
197
- this.setValueBounded = (next) => {
198
- this.setValue(next);
199
- };
200
- pubSubStore.setNoNotify(this.pubSubKey, defaultValue);
201
- const lazyLoad = options?.lazyLoad;
202
- const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateConfig.lazyLoad;
203
- if (!lazy) {
204
- void this.initDefaultValueOnce();
205
- }
206
- }
207
- pubSubKey;
208
- storageAdapter;
209
- setValueBounded;
210
- initStarted = false;
211
- initDone = false;
212
- // Allow users to await for the completion of data init.
213
- readyPromise;
214
- resolveReadyPromise;
215
- /** `subscribe` function required by useSyncExternalStore. */
216
- subscribe(subscriber) {
217
- return pubSubStore.subscribe(this.pubSubKey, () => subscriber());
218
- }
219
- /** Returns true if there is a backing store. */
220
- hasStore() {
221
- return Boolean(this.storageAdapter);
222
- }
223
- /**
224
- * Set a value directly into the store. Does nothing if there is no
225
- * backing store.
226
- *
227
- * Warning: If you want to set the value properly, you should use
228
- * `setValue()` instead which also updates the in-memory copy.
229
- */
230
- async setInStore(value) {
231
- return await this.storageAdapter?.set(STORAGE_KEY, value);
232
- }
233
- /**
234
- * Get a value directly from the store. Returns undefined if there is no
235
- * backing store.
236
- */
237
- async getFromStore() {
238
- return await this.storageAdapter?.get(STORAGE_KEY);
239
- }
240
- /**
241
- * Get the value of the shared state.
242
- * `getSnapshot` function — must return same ref if value unchanged.
243
- * Note that this would return the default value if data init from store is
244
- * not completed yet.
245
- */
246
- getSnapshot() {
247
- return pubSubStore.get(this.pubSubKey);
248
- }
249
- /** Set the value of the shared state. */
250
- setValue(next) {
251
- if (typeof next === "function") {
252
- const prev = pubSubStore.get(this.pubSubKey);
253
- next = next(prev);
194
+ function sharedState(defaultValue, options) {
195
+ let readyResolve = () => {
196
+ };
197
+ const readyPromise = new Promise((resolve) => {
198
+ readyResolve = resolve;
199
+ });
200
+ const resolveReadyPromise = readyResolve;
201
+ const pubSubKey = String(stateKey++);
202
+ const storageAdapter = getStorageAdapter(
203
+ options,
204
+ SharedStateConfig.storeExpiryMs
205
+ );
206
+ pubSubStore.setNoNotify(pubSubKey, defaultValue);
207
+ const lazyLoad = options?.lazyLoad;
208
+ const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateConfig.lazyLoad;
209
+ const obj = {
210
+ /** Allow users to await for the completion of data init. */
211
+ readyPromise,
212
+ lazy,
213
+ initStarted: false,
214
+ initDone: false,
215
+ /** `subscribe` function required by useSyncExternalStore. */
216
+ subscribe(subscriber) {
217
+ return pubSubStore.subscribe(pubSubKey, () => subscriber());
218
+ },
219
+ /** Returns true if there is a backing store. */
220
+ hasStore() {
221
+ return Boolean(storageAdapter);
222
+ },
223
+ /**
224
+ * Set a value directly into the store. Does nothing if there is no
225
+ * backing store.
226
+ *
227
+ * Warning: If you want to set the value properly, you should use
228
+ * `setValue()` instead which also updates the in-memory copy.
229
+ */
230
+ async setInStore(value) {
231
+ return await storageAdapter?.set(STORAGE_KEY, value);
232
+ },
233
+ /**
234
+ * Get a value directly from the store. Returns undefined if there is no
235
+ * backing store.
236
+ */
237
+ async getFromStore() {
238
+ return await storageAdapter?.get(STORAGE_KEY);
239
+ },
240
+ /**
241
+ * Get the value of the shared state.
242
+ * `getSnapshot` function — must return same ref if value unchanged.
243
+ * Note that this would return the default value if data init from store is
244
+ * not completed yet.
245
+ */
246
+ getSnapshot() {
247
+ return pubSubStore.get(pubSubKey);
248
+ },
249
+ /** Set the value of the shared state. */
250
+ setValue(next) {
251
+ if (typeof next === "function") {
252
+ const prev = pubSubStore.get(pubSubKey);
253
+ next = next(prev);
254
+ }
255
+ pubSubStore.set(pubSubKey, next);
256
+ void obj.setInStore(next);
257
+ },
258
+ /**
259
+ * Remove the value of the shared state. Actually this just sets the value
260
+ * back to the given default value.
261
+ */
262
+ delete() {
263
+ pubSubStore.set(pubSubKey, defaultValue);
264
+ void storageAdapter?.set(STORAGE_KEY, defaultValue);
265
+ },
266
+ /** Initial default handling. */
267
+ async initDefaultValueOnce() {
268
+ if (obj.initDone || obj.initStarted) return;
269
+ obj.initStarted = true;
270
+ const stored = await obj.getFromStore();
271
+ const value = stored !== void 0 ? stored : defaultValue;
272
+ pubSubStore.set(pubSubKey, value);
273
+ obj.initDone = true;
274
+ resolveReadyPromise();
254
275
  }
255
- pubSubStore.set(this.pubSubKey, next);
256
- void this.setInStore(next);
257
- }
258
- /**
259
- * Remove the value of the shared state. Actually this just sets the value
260
- * back to the given default value.
261
- */
262
- delete() {
263
- pubSubStore.set(this.pubSubKey, this.defaultValue);
264
- void this.storageAdapter?.set(STORAGE_KEY, this.defaultValue);
265
- }
266
- /** Initial default handling. */
267
- async initDefaultValueOnce() {
268
- if (this.initDone || this.initStarted) return;
269
- this.initStarted = true;
270
- const stored = await this.getFromStore();
271
- const value = stored !== void 0 ? stored : this.defaultValue;
272
- pubSubStore.set(this.pubSubKey, value);
273
- this.initDone = true;
274
- this.resolveReadyPromise();
276
+ };
277
+ if (!lazy) {
278
+ void obj.initDefaultValueOnce();
275
279
  }
276
- };
277
- function sharedState(defaultValue, options) {
278
- return new SharedState(defaultValue, options);
280
+ return obj;
279
281
  }
280
282
  function useSharedState(state) {
281
- state.initDefaultValueOnce();
283
+ void state.initDefaultValueOnce();
282
284
  const value = (0, import_react.useSyncExternalStore)(
283
285
  (onStoreChange) => state.subscribe(onStoreChange),
284
286
  () => state.getSnapshot(),
285
287
  // getServerSnapshot is needed to prevent SSR dev errors in nextjs.
286
288
  () => state.getSnapshot()
287
289
  );
288
- return [value, state.setValueBounded];
290
+ return [value, state.setValue];
289
291
  }
290
292
  function useSharedStateValue(state) {
291
293
  return useSharedState(state)[0];
292
294
  }
293
295
  function useSharedStateSetter(state) {
294
- return useSharedState(state)[1];
296
+ void state.initDefaultValueOnce();
297
+ return state.setValue;
295
298
  }
296
299
  // Annotate the CommonJS export names for ESM import in node:
297
300
  0 && (module.exports = {
298
- SharedState,
299
301
  SharedStateConfig,
300
302
  configureSharedState,
301
303
  sharedState,
package/sharedState.d.mts CHANGED
@@ -1,18 +1,31 @@
1
- import { Dispatch, SetStateAction } from 'react';
1
+ import { SetStateAction, Dispatch } from 'react';
2
2
  import { StorageOptions } from './storage.mjs';
3
+ import '@choksheak/ts-utils/duration';
3
4
  import '@choksheak/ts-utils/storageAdapter';
4
5
 
5
6
  /**
6
7
  * @packageDocumentation
7
8
  *
8
9
  * The "shared state" is a React state that shares the same value across the
9
- * entire app. It is largely similar to the jotai library, but is much smaller
10
- * and much easier to work with when used for persisting in local storage or
11
- * indexed db, with an automatic expiration for persisted values.
10
+ * entire app. Users declare a shared state constant that can be reused across
11
+ * multiple components with the same underlying value.
12
12
  *
13
- * This library aims to be the shortest, simplest, easiest to use, and most
14
- * efficient implementation of shared global React states with seamless support
15
- * for client persistence.
13
+ * Shared states provide persistence to local storage and/or indexed DB out of
14
+ * the box, by using "@choksheak/ts-utils". Note that no matter if the shared
15
+ * state uses persistence or not, it will always maintain a copy of the state
16
+ * in memory. Persisted values can be configured with an automatic expiration
17
+ * duration.
18
+ *
19
+ * This module is largely similar to the open source "jotai" npm library. You
20
+ * can use shared states to replace "jotai" in your code, and optionally make
21
+ * use of the persistence mechanism. A quick migration guide from jotai is:
22
+ *
23
+ * ```
24
+ * atom() --> sharedState()
25
+ * useAtom() --> useSharedState()
26
+ * useAtomValue() --> useSharedStateValue()
27
+ * useSetAtom() --> useSharedStateSetter()
28
+ * ```
16
29
  *
17
30
  * Example:
18
31
  * ```
@@ -22,7 +35,9 @@ import '@choksheak/ts-utils/storageAdapter';
22
35
  * // The first argument is the default value, which is required.
23
36
  * // The second argument is an options object, and is optional (defaults
24
37
  * // to storing in memory only without any persistence).
25
- * const usersState = sharedState([], { indexedDbKey: "users" });
38
+ * const usersState = sharedState(
39
+ * [], { store: { persistTo: "indexedDb", key: "users" }}
40
+ * );
26
41
  *
27
42
  * export const UsersComponent: React.FC = () => {
28
43
  * // Get both the value and the setter.
@@ -68,21 +83,24 @@ declare function configureSharedState(config: Partial<SharedStateConfig>): void;
68
83
  type SharedStateOptions<T> = {
69
84
  lazyLoad?: boolean;
70
85
  } & StorageOptions<T>;
71
- /** Please use sharedState() instead. */
72
- declare class SharedState<T> {
73
- private readonly defaultValue;
74
- private readonly pubSubKey;
75
- private readonly storageAdapter;
76
- readonly setValueBounded: Dispatch<SetStateAction<T>>;
77
- initStarted: boolean;
78
- initDone: boolean;
86
+ /**
87
+ * Create a new shared state object. Put this code at the top level scope:
88
+ *
89
+ * Example:
90
+ * ```
91
+ * const counterState = sharedState<number>(0);
92
+ * ```
93
+ */
94
+ declare function sharedState<T>(defaultValue: T, options?: SharedStateOptions<T>): {
95
+ /** Allow users to await for the completion of data init. */
79
96
  readonly readyPromise: Promise<void>;
80
- private readonly resolveReadyPromise;
81
- constructor(defaultValue: T, options?: SharedStateOptions<T>);
97
+ readonly lazy: boolean;
98
+ readonly initStarted: false;
99
+ readonly initDone: false;
82
100
  /** `subscribe` function required by useSyncExternalStore. */
83
- subscribe(subscriber: () => void): () => void;
101
+ readonly subscribe: (subscriber: () => void) => () => void;
84
102
  /** Returns true if there is a backing store. */
85
- hasStore(): boolean;
103
+ readonly hasStore: () => boolean;
86
104
  /**
87
105
  * Set a value directly into the store. Does nothing if there is no
88
106
  * backing store.
@@ -90,38 +108,30 @@ declare class SharedState<T> {
90
108
  * Warning: If you want to set the value properly, you should use
91
109
  * `setValue()` instead which also updates the in-memory copy.
92
110
  */
93
- setInStore(value: T): Promise<void>;
111
+ readonly setInStore: (value: T) => Promise<void>;
94
112
  /**
95
113
  * Get a value directly from the store. Returns undefined if there is no
96
114
  * backing store.
97
115
  */
98
- getFromStore(): Promise<T | undefined>;
116
+ readonly getFromStore: () => Promise<T | undefined>;
99
117
  /**
100
118
  * Get the value of the shared state.
101
119
  * `getSnapshot` function — must return same ref if value unchanged.
102
120
  * Note that this would return the default value if data init from store is
103
121
  * not completed yet.
104
122
  */
105
- getSnapshot(): T;
123
+ readonly getSnapshot: () => T;
106
124
  /** Set the value of the shared state. */
107
- setValue(next: SetStateAction<T>): void;
125
+ readonly setValue: (next: SetStateAction<T>) => void;
108
126
  /**
109
127
  * Remove the value of the shared state. Actually this just sets the value
110
128
  * back to the given default value.
111
129
  */
112
- delete(): void;
130
+ readonly delete: () => void;
113
131
  /** Initial default handling. */
114
- initDefaultValueOnce(): Promise<void>;
115
- }
116
- /**
117
- * Create a new shared state object. Put this code at the top level scope:
118
- *
119
- * Example:
120
- * ```
121
- * const counterState = sharedState<number>(0);
122
- * ```
123
- */
124
- declare function sharedState<T>(defaultValue: T, options?: SharedStateOptions<T>): SharedState<T>;
132
+ readonly initDefaultValueOnce: () => Promise<void>;
133
+ };
134
+ type SharedState<T> = ReturnType<typeof sharedState<T>>;
125
135
  /**
126
136
  * React hook for subscribing to a key in the global store.
127
137
  *
@@ -148,6 +158,6 @@ declare function useSharedStateValue<T>(state: SharedState<T>): T;
148
158
  * const setCounter = useSharedStateSetter(counterState);
149
159
  * ```
150
160
  */
151
- declare function useSharedStateSetter<T>(state: SharedState<T>): Dispatch<SetStateAction<T>>;
161
+ declare function useSharedStateSetter<T>(state: SharedState<T>): (next: SetStateAction<T>) => void;
152
162
 
153
- export { SharedState, SharedStateConfig, type SharedStateOptions, configureSharedState, sharedState, useSharedState, useSharedStateSetter, useSharedStateValue };
163
+ export { type SharedState, SharedStateConfig, type SharedStateOptions, configureSharedState, sharedState, useSharedState, useSharedStateSetter, useSharedStateValue };