@hanzogui/use-store 2.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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/dist/cjs/comparators.cjs +37 -0
  4. package/dist/cjs/comparators.native.js +46 -0
  5. package/dist/cjs/comparators.native.js.map +1 -0
  6. package/dist/cjs/configureUseStore.cjs +30 -0
  7. package/dist/cjs/configureUseStore.native.js +33 -0
  8. package/dist/cjs/configureUseStore.native.js.map +1 -0
  9. package/dist/cjs/constants.cjs +31 -0
  10. package/dist/cjs/constants.native.js +34 -0
  11. package/dist/cjs/constants.native.js.map +1 -0
  12. package/dist/cjs/decorators.cjs +30 -0
  13. package/dist/cjs/decorators.native.js +33 -0
  14. package/dist/cjs/decorators.native.js.map +1 -0
  15. package/dist/cjs/helpers.cjs +55 -0
  16. package/dist/cjs/helpers.native.js +65 -0
  17. package/dist/cjs/helpers.native.js.map +1 -0
  18. package/dist/cjs/index.cjs +40 -0
  19. package/dist/cjs/index.native.js +54 -0
  20. package/dist/cjs/index.native.js.map +1 -0
  21. package/dist/cjs/interfaces.cjs +16 -0
  22. package/dist/cjs/interfaces.native.js +19 -0
  23. package/dist/cjs/interfaces.native.js.map +1 -0
  24. package/dist/cjs/observe.cjs +120 -0
  25. package/dist/cjs/observe.native.js +186 -0
  26. package/dist/cjs/observe.native.js.map +1 -0
  27. package/dist/cjs/useStore.cjs +390 -0
  28. package/dist/cjs/useStore.native.js +544 -0
  29. package/dist/cjs/useStore.native.js.map +1 -0
  30. package/dist/cjs/useStoreDebug.cjs +56 -0
  31. package/dist/cjs/useStoreDebug.native.js +65 -0
  32. package/dist/cjs/useStoreDebug.native.js.map +1 -0
  33. package/dist/esm/comparators.mjs +14 -0
  34. package/dist/esm/comparators.mjs.map +1 -0
  35. package/dist/esm/comparators.native.js +20 -0
  36. package/dist/esm/comparators.native.js.map +1 -0
  37. package/dist/esm/configureUseStore.mjs +6 -0
  38. package/dist/esm/configureUseStore.mjs.map +1 -0
  39. package/dist/esm/configureUseStore.native.js +6 -0
  40. package/dist/esm/configureUseStore.native.js.map +1 -0
  41. package/dist/esm/constants.mjs +7 -0
  42. package/dist/esm/constants.mjs.map +1 -0
  43. package/dist/esm/constants.native.js +7 -0
  44. package/dist/esm/constants.native.js.map +1 -0
  45. package/dist/esm/decorators.mjs +7 -0
  46. package/dist/esm/decorators.mjs.map +1 -0
  47. package/dist/esm/decorators.native.js +7 -0
  48. package/dist/esm/decorators.native.js.map +1 -0
  49. package/dist/esm/helpers.mjs +26 -0
  50. package/dist/esm/helpers.mjs.map +1 -0
  51. package/dist/esm/helpers.native.js +33 -0
  52. package/dist/esm/helpers.native.js.map +1 -0
  53. package/dist/esm/index.js +14 -0
  54. package/dist/esm/index.js.map +1 -0
  55. package/dist/esm/index.mjs +14 -0
  56. package/dist/esm/index.mjs.map +1 -0
  57. package/dist/esm/index.native.js +25 -0
  58. package/dist/esm/index.native.js.map +1 -0
  59. package/dist/esm/interfaces.mjs +2 -0
  60. package/dist/esm/interfaces.mjs.map +1 -0
  61. package/dist/esm/interfaces.native.js +2 -0
  62. package/dist/esm/interfaces.native.js.map +1 -0
  63. package/dist/esm/observe.mjs +85 -0
  64. package/dist/esm/observe.mjs.map +1 -0
  65. package/dist/esm/observe.native.js +148 -0
  66. package/dist/esm/observe.native.js.map +1 -0
  67. package/dist/esm/useStore.mjs +342 -0
  68. package/dist/esm/useStore.mjs.map +1 -0
  69. package/dist/esm/useStore.native.js +493 -0
  70. package/dist/esm/useStore.native.js.map +1 -0
  71. package/dist/esm/useStoreDebug.mjs +18 -0
  72. package/dist/esm/useStoreDebug.mjs.map +1 -0
  73. package/dist/esm/useStoreDebug.native.js +24 -0
  74. package/dist/esm/useStoreDebug.native.js.map +1 -0
  75. package/package.json +47 -0
  76. package/src/comparators.tsx +18 -0
  77. package/src/configureUseStore.tsx +7 -0
  78. package/src/constants.tsx +6 -0
  79. package/src/decorators.tsx +8 -0
  80. package/src/helpers.tsx +56 -0
  81. package/src/index.ts +12 -0
  82. package/src/interfaces.tsx +46 -0
  83. package/src/observe.tsx +160 -0
  84. package/src/useStore.tsx +705 -0
  85. package/src/useStoreDebug.tsx +41 -0
@@ -0,0 +1,390 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf,
6
+ __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: !0
11
+ });
12
+ },
13
+ __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, {
15
+ get: () => from[key],
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
26
+ value: mod,
27
+ enumerable: !0
28
+ }) : target, mod)),
29
+ __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
30
+ value: !0
31
+ }), mod);
32
+ var useStore_exports = {};
33
+ __export(useStore_exports, {
34
+ allStores: () => allStores,
35
+ createStore: () => createStore,
36
+ createUseStore: () => createUseStore,
37
+ createUseStoreSelector: () => createUseStoreSelector,
38
+ getOrCreateStore: () => getOrCreateStore,
39
+ getStore: () => getStore,
40
+ getStoreInfo: () => getStoreInfo,
41
+ onCreateStore: () => onCreateStore,
42
+ setIsInReaction: () => setIsInReaction,
43
+ trackStoresAccess: () => trackStoresAccess,
44
+ useGlobalStore: () => useGlobalStore,
45
+ useGlobalStoreSelector: () => useGlobalStoreSelector,
46
+ useStore: () => useStore,
47
+ useStoreDebug: () => useStoreDebug,
48
+ useStoreSelector: () => useStoreSelector
49
+ });
50
+ module.exports = __toCommonJS(useStore_exports);
51
+ var import_react = __toESM(require("react"), 1),
52
+ import_comparators = require("./comparators.cjs"),
53
+ import_configureUseStore = require("./configureUseStore.cjs"),
54
+ import_constants = require("./constants.cjs"),
55
+ import_helpers = require("./helpers.cjs"),
56
+ import_useStoreDebug = require("./useStoreDebug.cjs");
57
+ const idFn = _ => _;
58
+ function useStore(StoreKlass, props, options = import_constants.defaultOptions) {
59
+ const info = getOrCreateStoreInfo(StoreKlass, props, options);
60
+ return useStoreFromInfo(info, options.selector, options);
61
+ }
62
+ function useStoreDebug(StoreKlass, props) {
63
+ return useStore(StoreKlass, props, {
64
+ debug: !0
65
+ });
66
+ }
67
+ function createStore(StoreKlass, props, options) {
68
+ return getOrCreateStoreInfo(StoreKlass, props, options)?.store;
69
+ }
70
+ function useGlobalStore(instance, debug) {
71
+ const store = instance[import_constants.UNWRAP_PROXY],
72
+ uid = (0, import_helpers.getStoreUid)(store.constructor, store.props),
73
+ info = import_helpers.cache.get(uid);
74
+ if (!info) throw new Error("This store not created using createStore()");
75
+ return useStoreFromInfo(info, void 0, {
76
+ debug
77
+ });
78
+ }
79
+ function useGlobalStoreSelector(instance, selector, debug) {
80
+ const store = instance[import_constants.UNWRAP_PROXY],
81
+ uid = (0, import_helpers.getStoreUid)(store.constructor, store.props),
82
+ info = import_helpers.cache.get(uid);
83
+ if (!info) throw new Error("This store not created using createStore()");
84
+ return useStoreFromInfo(info, selector, {
85
+ debug
86
+ });
87
+ }
88
+ function createUseStore(StoreKlass) {
89
+ return (props, options) => useStore(StoreKlass, props, options);
90
+ }
91
+ function createUseStoreSelector(StoreKlass, selector) {
92
+ return props => useStore(StoreKlass, props, {
93
+ selector
94
+ });
95
+ }
96
+ function useStoreSelector(StoreKlass, selector, props) {
97
+ return useStore(StoreKlass, props, {
98
+ selector
99
+ });
100
+ }
101
+ const storeAccessTrackers = /* @__PURE__ */new Set();
102
+ function trackStoresAccess(cb) {
103
+ return storeAccessTrackers.add(cb), () => {
104
+ storeAccessTrackers.delete(cb);
105
+ };
106
+ }
107
+ function getStore(StoreKlass, props) {
108
+ return getStoreInfo(StoreKlass, props)?.store;
109
+ }
110
+ function getOrCreateStore(StoreKlass, props) {
111
+ return getOrCreateStoreInfo(StoreKlass, props, {
112
+ refuseCreation: !1
113
+ })?.store;
114
+ }
115
+ function getStoreInfo(StoreKlass, props) {
116
+ return getOrCreateStoreInfo(StoreKlass, props, {
117
+ refuseCreation: !0
118
+ });
119
+ }
120
+ const onCreateListeners = /* @__PURE__ */new Set();
121
+ function onCreateStore(cb) {
122
+ return onCreateListeners.add(cb), () => {
123
+ onCreateListeners.delete(cb);
124
+ };
125
+ }
126
+ function getOrCreateStoreInfo(StoreKlass, props, options, propsKeyCalculated) {
127
+ if (!StoreKlass) return null;
128
+ const uid = (0, import_helpers.getStoreUid)(StoreKlass, propsKeyCalculated ?? props);
129
+ if (!options?.avoidCache && import_helpers.cache.has(uid)) return import_helpers.cache.get(uid);
130
+ if (options?.refuseCreation) throw new Error(`No store exists (${StoreKlass.name}) with props: ${props}`);
131
+ const storeInstance = new StoreKlass(props);
132
+ storeInstance.props = props;
133
+ const getters = {},
134
+ actions = {},
135
+ stateKeys = /* @__PURE__ */new Set(),
136
+ descriptors = (0, import_helpers.getStoreDescriptors)(storeInstance);
137
+ for (const key in descriptors) {
138
+ const descriptor = descriptors[key];
139
+ typeof descriptor.value == "function" ? actions[key] = descriptor.value : typeof descriptor.get == "function" ? getters[key] = descriptor.get : key !== "props" && key[0] !== "_" && stateKeys.add(key);
140
+ }
141
+ const keyComparators = storeInstance._comparators,
142
+ listeners = /* @__PURE__ */new Set(),
143
+ storeInfo = {
144
+ uid,
145
+ keyComparators,
146
+ storeInstance,
147
+ getters,
148
+ stateKeys,
149
+ props,
150
+ actions,
151
+ debug: options?.debug,
152
+ disableTracking: !1,
153
+ gettersState: {
154
+ getCache: /* @__PURE__ */new Map(),
155
+ depsToGetter: /* @__PURE__ */new Map(),
156
+ curGetKeys: /* @__PURE__ */new Set(),
157
+ isGetting: !1
158
+ },
159
+ listeners,
160
+ trackers: /* @__PURE__ */new Set(),
161
+ version: 0,
162
+ subscribe: onChanged => (listeners.add(onChanged), () => {
163
+ listeners.delete(onChanged);
164
+ }),
165
+ triggerUpdate: () => {
166
+ storeInfo.version = (storeInfo.version + 1) % Number.MAX_SAFE_INTEGER;
167
+ for (const cb of listeners) cb();
168
+ }
169
+ },
170
+ store = createProxiedStore(
171
+ // we assign store right after and proxiedStore never accesses it until later on
172
+ storeInfo);
173
+ process.env.NODE_ENV === "development" && (allStores[StoreKlass.name + uid] = store), store.mount?.(), storeInfo.store = store;
174
+ const result = storeInfo;
175
+ return import_helpers.cache.set(uid, result), onCreateListeners.forEach(cb => cb(result)), result;
176
+ }
177
+ const allStores = {};
178
+ process.env.NODE_ENV === "development" && (globalThis.Store ||= allStores);
179
+ const emptyObj = {},
180
+ selectKeys = (obj, keys) => {
181
+ if (!keys.length) return emptyObj;
182
+ const res = {};
183
+ for (const key of keys) res[key] = obj[key];
184
+ return res;
185
+ };
186
+ let isInReaction = !1;
187
+ const setIsInReaction = val => {
188
+ isInReaction = val;
189
+ };
190
+ function useStoreFromInfo(info, userSelector, options) {
191
+ const store = info?.store,
192
+ internal = import_react.default.useRef(void 0),
193
+ component = (0, import_useStoreDebug.useCurrentComponent)();
194
+ internal.current || (internal.current = {
195
+ component,
196
+ tracked: /* @__PURE__ */new Set(),
197
+ last: null,
198
+ lastKeys: null
199
+ });
200
+ const curInternal = internal.current,
201
+ shouldPrintDebug = options?.debug,
202
+ getSnapshot = import_react.default.useCallback(() => {
203
+ if (!info || !store) return;
204
+ const curInternal2 = internal.current,
205
+ isTracking = curInternal2.tracked.size,
206
+ keys = [...(isTracking ? curInternal2.tracked : info.stateKeys)],
207
+ nextKeys = `${info.version}${keys.join("")}${userSelector || ""}`,
208
+ lastKeys = curInternal2.lastKeys;
209
+ if (nextKeys === curInternal2.lastKeys) return curInternal2.last;
210
+ curInternal2.lastKeys = nextKeys;
211
+ let snap;
212
+ info.disableTracking = !0;
213
+ const last = curInternal2.last;
214
+ userSelector ? snap = userSelector(store) : snap = selectKeys(store, keys), info.disableTracking = !1;
215
+ const isUnchanged = !userSelector && !isTracking && last || typeof last < "u" && (0, import_comparators.isEqualSubsetShallow)(last, snap, {
216
+ keyComparators: info.keyComparators
217
+ });
218
+ return shouldPrintDebug && console.info("\u{1F311} getSnapshot", {
219
+ storeState: selectKeys(store, Object.keys(store)),
220
+ userSelector,
221
+ info,
222
+ isUnchanged,
223
+ component,
224
+ keys,
225
+ last,
226
+ snap,
227
+ curInternal: curInternal2,
228
+ nextKeys,
229
+ lastKeys
230
+ }), isUnchanged ? last : (curInternal2.last = snap, snap);
231
+ }, [store]),
232
+ state = import_react.default.useSyncExternalStore(info?.subscribe || idFn, getSnapshot, getSnapshot);
233
+ return !info || !store || !state || userSelector ? state : new Proxy(store, {
234
+ get(target, key) {
235
+ const curVal = Reflect.get(target, key);
236
+ if (isInReaction) return curVal;
237
+ const keyString = key;
238
+ return (info.stateKeys.has(keyString) || keyString in info.getters) && (shouldPrintDebug && console.info("\u{1F440} tracking", keyString), curInternal.tracked.add(keyString)), Reflect.has(state, key) ? Reflect.get(state, key) : curVal;
239
+ }
240
+ });
241
+ }
242
+ let setters = /* @__PURE__ */new Set();
243
+ const logStack = /* @__PURE__ */new Set();
244
+ function createProxiedStore(storeInfo) {
245
+ const {
246
+ actions,
247
+ storeInstance,
248
+ getters,
249
+ gettersState
250
+ } = storeInfo,
251
+ {
252
+ getCache,
253
+ curGetKeys,
254
+ depsToGetter
255
+ } = gettersState,
256
+ constr = storeInstance.constructor,
257
+ shouldDebug2 = storeInfo.debug ?? import_useStoreDebug.DebugStores.has(constr);
258
+ let didSet = !1;
259
+ const wrappedActions = {};
260
+ for (const key in actions) {
261
+ if (key === "subscribe") continue;
262
+ const actionFn = actions[key],
263
+ isGetFn = key.startsWith("get");
264
+ if (wrappedActions[key] = function (...args) {
265
+ let res;
266
+ return isGetFn || gettersState.isGetting ? Reflect.apply(actionFn, proxiedStore, args) : (process.env.NODE_ENV === "development" && shouldDebug2 && console.info("(debug) startAction", key), res = Reflect.apply(actionFn, proxiedStore, args), res instanceof Promise ? res.then(finishAction) : (finishAction(), res));
267
+ }, process.env.NODE_ENV === "development") {
268
+ let hashCode = function (str) {
269
+ let hash = 0;
270
+ for (let i = 0; i < str.length; i++) hash = str.charCodeAt(i) + ((hash << 5) - hash);
271
+ return hash;
272
+ },
273
+ strColor = function (str) {
274
+ return `hsl(${hashCode(str) % 360}, 90%, 40%)`;
275
+ };
276
+ if (!key.startsWith("get") && !key.startsWith("_") && key !== "subscribe") {
277
+ const ogAction = wrappedActions[key];
278
+ wrappedActions[key] = new Proxy(ogAction, {
279
+ apply(target, thisArg, args) {
280
+ const isDebugging = shouldDebug2 || storeInfo.debug;
281
+ if (!(process.env.LOG_LEVEL !== "0" && (isDebugging || import_configureUseStore.configureOpts.logLevel !== "error"))) return Reflect.apply(target, thisArg, args);
282
+ setters = /* @__PURE__ */new Set();
283
+ const curSetters = setters,
284
+ isTopLevelLogger = logStack.size == 0,
285
+ logs = /* @__PURE__ */new Set();
286
+ logStack.add(logs);
287
+ let res;
288
+ const id = counter++;
289
+ try {
290
+ res = Reflect.apply(target, thisArg, args);
291
+ } catch (err) {
292
+ throw console.error("Error", err), err;
293
+ } finally {
294
+ logStack.add("end");
295
+ const name = constr.name,
296
+ color = strColor(name),
297
+ simpleArgs = args.map(import_helpers.simpleStr);
298
+ if (logs.add([`%c \u{1F311} ${id} ${name.padStart(isTopLevelLogger ? 8 : 4)}%c.${key}(${simpleArgs.join(", ")})${isTopLevelLogger && logStack.size > 1 ? ` (+${logStack.size - 1})` : ""}`, `color: ${color};`, "color: black;"]), curSetters.size && curSetters.forEach(({
299
+ key: key2,
300
+ value
301
+ }) => {
302
+ typeof value == "string" || typeof value == "number" || typeof value == "boolean" ? logs.add([` SET ${key2} ${value}`, value]) : logs.add([` SET ${key2}`, value]);
303
+ }), isTopLevelLogger) {
304
+ let error = null;
305
+ try {
306
+ for (const item of logStack) {
307
+ if (item === "end") {
308
+ console.groupEnd();
309
+ continue;
310
+ }
311
+ const [head, ...rest] = item;
312
+ if (head) {
313
+ console.groupCollapsed(...head), console.groupCollapsed("..."), console.info("args", args), console.info("response", res), console.groupCollapsed("trace"), console.trace(), console.groupEnd(), console.groupEnd();
314
+ for (const [name2, ...log] of rest) console.groupCollapsed(name2), console.info(...log), console.groupEnd();
315
+ } else console.info("Weird log", head, ...rest);
316
+ }
317
+ } catch (err) {
318
+ error = err;
319
+ }
320
+ for (const _ of logStack) console.groupEnd();
321
+ error && console.error("error loggin", error), logStack.clear();
322
+ }
323
+ return res;
324
+ }
325
+ }
326
+ });
327
+ }
328
+ }
329
+ }
330
+ const finishAction = val => (process.env.NODE_ENV === "development" && shouldDebug2 && console.info("(debug) finishAction", {
331
+ didSet
332
+ }), didSet && (storeInfo.triggerUpdate(), didSet = !1), val);
333
+ let isTriggering = !1;
334
+ const proxiedStore = new Proxy(storeInstance, {
335
+ // GET
336
+ get(_, key) {
337
+ if (key in wrappedActions) return wrappedActions[key];
338
+ if (key in passThroughKeys) return Reflect.get(storeInstance, key);
339
+ if (key === import_constants.UNWRAP_PROXY) return storeInstance;
340
+ if (key === import_helpers.UNWRAP_STORE_INFO) return storeInfo;
341
+ if (storeAccessTrackers.size && storeAccessTrackers.forEach(cb => cb(storeInfo)), typeof key != "string") return Reflect.get(storeInstance, key);
342
+ if (storeInfo.disableTracking || gettersState.isGetting && gettersState.curGetKeys.add(key), key in getters) {
343
+ if (getCache.has(key)) return getCache.get(key);
344
+ curGetKeys.clear();
345
+ const isSubGetter = gettersState.isGetting;
346
+ gettersState.isGetting = !0;
347
+ const res = getters[key].call(proxiedStore);
348
+ isSubGetter || (gettersState.isGetting = !1);
349
+ for (const gk of curGetKeys) depsToGetter.has(gk) || depsToGetter.set(gk, /* @__PURE__ */new Set()), depsToGetter.get(gk).add(key);
350
+ return getCache.set(key, res), res;
351
+ }
352
+ return Reflect.get(storeInstance, key);
353
+ },
354
+ // SET
355
+ set(target, key, value, receiver) {
356
+ const cur = Reflect.get(target, key),
357
+ res = Reflect.set(target, key, value, receiver);
358
+ return res && cur !== value && (typeof key == "string" && (clearGetterCache(key), shouldDebug2 && (setters.add({
359
+ key,
360
+ value
361
+ }), getShouldDebug(storeInfo) && console.info("(debug) SET", res, key, value)), process.env.NODE_ENV === "development" && shouldDebug2 && console.info("SET...", {
362
+ key,
363
+ value
364
+ })), isTriggering || (isTriggering = !0, waitForEventLoop(() => {
365
+ storeInfo.triggerUpdate(), isTriggering = !1;
366
+ }))), res;
367
+ }
368
+ });
369
+ function clearGetterCache(setKey) {
370
+ const parentGetters = depsToGetter.get(setKey);
371
+ if (getCache.delete(setKey), !!parentGetters) for (const gk of parentGetters) getCache.delete(gk), depsToGetter.has(gk) && clearGetterCache(gk);
372
+ }
373
+ return proxiedStore;
374
+ }
375
+ const waitForEventLoop = process.env.NODE_ENV === "test" ? cb => cb() : queueMicrotask;
376
+ let counter = 0;
377
+ const passThroughKeys = {
378
+ subscribe: !0,
379
+ _version: !0,
380
+ _trackers: !0,
381
+ $$typeof: !0,
382
+ _listeners: !0,
383
+ _enableTracking: !0
384
+ };
385
+ function getShouldDebug(storeInfo) {
386
+ const info = {
387
+ storeInstance: storeInfo.store
388
+ };
389
+ return [...storeInfo.trackers].some(tracker => tracker.component && (0, import_useStoreDebug.shouldDebug)(tracker.component, info));
390
+ }