@choksheak/react-utils 0.3.8 → 0.4.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 (87) hide show
  1. package/NoSSR.cjs +7 -30
  2. package/NoSSR.min.cjs +1 -1
  3. package/NoSSR.min.cjs.map +1 -1
  4. package/NoSSR.min.mjs +1 -1
  5. package/NoSSR.min.mjs.map +1 -1
  6. package/NoSSR.mjs +2 -0
  7. package/chunk-33UMQLKY.mjs +43 -0
  8. package/chunk-3V7WBGWQ.mjs +16 -0
  9. package/chunk-3X25NN6X.cjs +195 -0
  10. package/chunk-5DO7KC3L.cjs +43 -0
  11. package/chunk-5PDGU37E.cjs +104 -0
  12. package/chunk-6ZZ54XM5.min.mjs +2 -0
  13. package/chunk-6ZZ54XM5.min.mjs.map +1 -0
  14. package/chunk-74BS2FAO.cjs +12 -0
  15. package/chunk-F5L32IUC.min.cjs +2 -0
  16. package/chunk-F5L32IUC.min.cjs.map +1 -0
  17. package/chunk-GPV6JIQK.mjs +17 -0
  18. package/chunk-KE3RXVMS.min.cjs +2 -0
  19. package/chunk-KE3RXVMS.min.cjs.map +1 -0
  20. package/chunk-KILGR7YA.min.mjs +2 -0
  21. package/chunk-KILGR7YA.min.mjs.map +1 -0
  22. package/chunk-KRXENFK3.mjs +195 -0
  23. package/chunk-MWDH7YON.min.mjs +2 -0
  24. package/chunk-MWDH7YON.min.mjs.map +1 -0
  25. package/chunk-NTFFK7ZH.min.cjs +2 -0
  26. package/chunk-NTFFK7ZH.min.cjs.map +1 -0
  27. package/chunk-O3RBYG3W.min.cjs +2 -0
  28. package/chunk-O3RBYG3W.min.cjs.map +1 -0
  29. package/chunk-PHLY3LR4.mjs +104 -0
  30. package/chunk-RM4ZGGZ2.min.mjs +2 -0
  31. package/chunk-RM4ZGGZ2.min.mjs.map +1 -0
  32. package/chunk-TEZPF6BG.min.cjs +2 -0
  33. package/chunk-TEZPF6BG.min.cjs.map +1 -0
  34. package/chunk-UFJNJ3WV.cjs +16 -0
  35. package/chunk-UFJQLQFI.min.cjs +2 -0
  36. package/chunk-UFJQLQFI.min.cjs.map +1 -0
  37. package/chunk-V7L3UICC.min.mjs +2 -0
  38. package/chunk-V7L3UICC.min.mjs.map +1 -0
  39. package/chunk-VHMO75EY.min.mjs +2 -0
  40. package/chunk-VHMO75EY.min.mjs.map +1 -0
  41. package/chunk-WVLPJPWG.cjs +17 -0
  42. package/chunk-X6BYQHVC.mjs +12 -0
  43. package/fetcher.cjs +8 -50
  44. package/fetcher.d.mts +3 -3
  45. package/fetcher.d.ts +2 -2
  46. package/fetcher.min.cjs +1 -1
  47. package/fetcher.min.cjs.map +1 -1
  48. package/fetcher.min.mjs +1 -1
  49. package/fetcher.min.mjs.map +1 -1
  50. package/fetcher.mjs +5 -11
  51. package/package.json +124 -29
  52. package/sharedQuery.cjs +132 -392
  53. package/sharedQuery.d.mts +58 -13
  54. package/sharedQuery.d.ts +57 -12
  55. package/sharedQuery.min.cjs +1 -1
  56. package/sharedQuery.min.cjs.map +1 -1
  57. package/sharedQuery.min.mjs +1 -1
  58. package/sharedQuery.min.mjs.map +1 -1
  59. package/sharedQuery.mjs +94 -322
  60. package/sharedState.cjs +15 -304
  61. package/sharedState.d.mts +4 -4
  62. package/sharedState.d.ts +4 -4
  63. package/sharedState.min.cjs +1 -1
  64. package/sharedState.min.cjs.map +1 -1
  65. package/sharedState.min.mjs +1 -1
  66. package/sharedState.min.mjs.map +1 -1
  67. package/sharedState.mjs +10 -269
  68. package/storage.cjs +10 -123
  69. package/storage.d.mts +1 -0
  70. package/storage.d.ts +1 -0
  71. package/storage.min.cjs +1 -1
  72. package/storage.min.cjs.map +1 -1
  73. package/storage.min.mjs +1 -1
  74. package/storage.min.mjs.map +1 -1
  75. package/storage.mjs +6 -92
  76. package/stringify.cjs +8 -57
  77. package/stringify.min.cjs +1 -1
  78. package/stringify.min.cjs.map +1 -1
  79. package/stringify.min.mjs +1 -1
  80. package/stringify.min.mjs.map +1 -1
  81. package/stringify.mjs +6 -30
  82. package/useDeepMemo.cjs +6 -50
  83. package/useDeepMemo.min.cjs +1 -1
  84. package/useDeepMemo.min.cjs.map +1 -1
  85. package/useDeepMemo.min.mjs +1 -1
  86. package/useDeepMemo.min.mjs.map +1 -1
  87. package/useDeepMemo.mjs +4 -13
package/NoSSR.cjs CHANGED
@@ -1,37 +1,14 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('./chunk-74BS2FAO.cjs');
19
2
 
20
3
  // src/NoSSR.tsx
21
- var NoSSR_exports = {};
22
- __export(NoSSR_exports, {
23
- NoSSR: () => NoSSR
24
- });
25
- module.exports = __toCommonJS(NoSSR_exports);
26
- var import_react = require("react");
4
+ var _react = require('react');
27
5
  var NoSSR = ({ children, fallback }) => {
28
- const [isClient, setIsClient] = (0, import_react.useState)(false);
29
- (0, import_react.useEffect)(() => {
6
+ const [isClient, setIsClient] = _react.useState.call(void 0, false);
7
+ _react.useEffect.call(void 0, () => {
30
8
  setIsClient(true);
31
9
  }, []);
32
10
  return isClient ? children : fallback;
33
11
  };
34
- // Annotate the CommonJS export names for ESM import in node:
35
- 0 && (module.exports = {
36
- NoSSR
37
- });
12
+
13
+
14
+ exports.NoSSR = NoSSR;
package/NoSSR.min.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var a=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var n=(t,e)=>{for(var o in e)a(t,o,{get:e[o],enumerable:!0})},p=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let c of S(e))!l.call(t,c)&&c!==o&&a(t,c,{get:()=>e[c],enumerable:!(r=R(e,c))||r.enumerable});return t};var N=t=>p(a({},"__esModule",{value:!0}),t);var i={};n(i,{NoSSR:()=>f});module.exports=N(i);var s=require("react"),f=({children:t,fallback:e})=>{let[o,r]=(0,s.useState)(!1);return(0,s.useEffect)(()=>{r(!0)},[]),o?t:e};0&&(module.exports={NoSSR});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('./chunk-KE3RXVMS.min.cjs');var _react = require('react');var l=({children:e,fallback:t})=>{let[o,c]=_react.useState.call(void 0, !1);return _react.useEffect.call(void 0, ()=>{c(!0)},[]),o?e:t};exports.NoSSR = l;
2
2
  //# sourceMappingURL=NoSSR.min.cjs.map
package/NoSSR.min.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/NoSSR.tsx"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Wraps components in <NoSSR>...</NoSSR> to make sure they only render on the\n * client side, and not on the server side.\n */\n\nimport React, { ReactNode, useEffect, useState } from \"react\";\n\n/** Props for the NoSSR component. */\nexport type NoSSRProps = {\n /** The content to render only on the client side. */\n children: ReactNode;\n\n /** A component to render during SSR or initial load. */\n fallback?: ReactNode;\n};\n\n/**\n * A component that prevents its children from being rendered during\n * Server-Side Rendering (SSR). It renders a optional fallback during SSR, and\n * only renders its children after the component has mounted on the client.\n */\nexport const NoSSR: React.FC<NoSSRProps> = ({ children, fallback }) => {\n const [isClient, setIsClient] = useState(false);\n\n // 2. useEffect runs ONLY on the client after the initial hydration is complete.\n useEffect(() => {\n // This forces the component to render a second time.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsClient(true);\n }, []);\n\n return isClient ? children : fallback;\n};\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,WAAAE,IAAA,eAAAC,EAAAH,GAOA,IAAAI,EAAsD,iBAgBzCF,EAA8B,CAAC,CAAE,SAAAG,EAAU,SAAAC,CAAS,IAAM,CACrE,GAAM,CAACC,EAAUC,CAAW,KAAI,YAAS,EAAK,EAG9C,sBAAU,IAAM,CAGdA,EAAY,EAAI,CAClB,EAAG,CAAC,CAAC,EAEED,EAAWF,EAAWC,CAC/B","names":["NoSSR_exports","__export","NoSSR","__toCommonJS","import_react","children","fallback","isClient","setIsClient"]}
1
+ {"version":3,"sources":["/Users/choksheaklau/src/react-utils/dist/NoSSR.min.cjs","../src/NoSSR.tsx"],"names":["NoSSR","children","fallback","isClient","setIsClient","useState","useEffect"],"mappings":"AAAA,6GAAgC,8BCOsB,IAgBzCA,CAAAA,CAA8B,CAAC,CAAE,QAAA,CAAAC,CAAAA,CAAU,QAAA,CAAAC,CAAS,CAAA,CAAA,EAAM,CACrE,GAAM,CAACC,CAAAA,CAAUC,CAAW,CAAA,CAAIC,6BAAAA,CAAS,CAAK,CAAA,CAG9C,OAAAC,8BAAAA,CAAU,CAAA,EAAM,CAGdF,CAAAA,CAAY,CAAA,CAAI,CAClB,CAAA,CAAG,CAAC,CAAC,CAAA,CAEED,CAAAA,CAAWF,CAAAA,CAAWC,CAC/B,CAAA,CAAA,kBAAA","file":"/Users/choksheaklau/src/react-utils/dist/NoSSR.min.cjs","sourcesContent":[null,"/**\n * @packageDocumentation\n *\n * Wraps components in <NoSSR>...</NoSSR> to make sure they only render on the\n * client side, and not on the server side.\n */\n\nimport React, { ReactNode, useEffect, useState } from \"react\";\n\n/** Props for the NoSSR component. */\nexport type NoSSRProps = {\n /** The content to render only on the client side. */\n children: ReactNode;\n\n /** A component to render during SSR or initial load. */\n fallback?: ReactNode;\n};\n\n/**\n * A component that prevents its children from being rendered during\n * Server-Side Rendering (SSR). It renders a optional fallback during SSR, and\n * only renders its children after the component has mounted on the client.\n */\nexport const NoSSR: React.FC<NoSSRProps> = ({ children, fallback }) => {\n const [isClient, setIsClient] = useState(false);\n\n // 2. useEffect runs ONLY on the client after the initial hydration is complete.\n useEffect(() => {\n // This forces the component to render a second time.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsClient(true);\n }, []);\n\n return isClient ? children : fallback;\n};\n"]}
package/NoSSR.min.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{useEffect as r,useState as s}from"react";var l=({children:e,fallback:t})=>{let[o,c]=s(!1);return r(()=>{c(!0)},[]),o?e:t};export{l as NoSSR};
1
+ import"./chunk-MWDH7YON.min.mjs";import{useEffect as r,useState as s}from"react";var l=({children:e,fallback:t})=>{let[o,c]=s(!1);return r(()=>{c(!0)},[]),o?e:t};export{l as NoSSR};
2
2
  //# sourceMappingURL=NoSSR.min.mjs.map
package/NoSSR.min.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/NoSSR.tsx"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Wraps components in <NoSSR>...</NoSSR> to make sure they only render on the\n * client side, and not on the server side.\n */\n\nimport React, { ReactNode, useEffect, useState } from \"react\";\n\n/** Props for the NoSSR component. */\nexport type NoSSRProps = {\n /** The content to render only on the client side. */\n children: ReactNode;\n\n /** A component to render during SSR or initial load. */\n fallback?: ReactNode;\n};\n\n/**\n * A component that prevents its children from being rendered during\n * Server-Side Rendering (SSR). It renders a optional fallback during SSR, and\n * only renders its children after the component has mounted on the client.\n */\nexport const NoSSR: React.FC<NoSSRProps> = ({ children, fallback }) => {\n const [isClient, setIsClient] = useState(false);\n\n // 2. useEffect runs ONLY on the client after the initial hydration is complete.\n useEffect(() => {\n // This forces the component to render a second time.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsClient(true);\n }, []);\n\n return isClient ? children : fallback;\n};\n"],"mappings":"AAOA,OAA2B,aAAAA,EAAW,YAAAC,MAAgB,QAgB/C,IAAMC,EAA8B,CAAC,CAAE,SAAAC,EAAU,SAAAC,CAAS,IAAM,CACrE,GAAM,CAACC,EAAUC,CAAW,EAAIL,EAAS,EAAK,EAG9C,OAAAD,EAAU,IAAM,CAGdM,EAAY,EAAI,CAClB,EAAG,CAAC,CAAC,EAEED,EAAWF,EAAWC,CAC/B","names":["useEffect","useState","NoSSR","children","fallback","isClient","setIsClient"]}
1
+ {"version":3,"sources":["../src/NoSSR.tsx"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Wraps components in <NoSSR>...</NoSSR> to make sure they only render on the\n * client side, and not on the server side.\n */\n\nimport React, { ReactNode, useEffect, useState } from \"react\";\n\n/** Props for the NoSSR component. */\nexport type NoSSRProps = {\n /** The content to render only on the client side. */\n children: ReactNode;\n\n /** A component to render during SSR or initial load. */\n fallback?: ReactNode;\n};\n\n/**\n * A component that prevents its children from being rendered during\n * Server-Side Rendering (SSR). It renders a optional fallback during SSR, and\n * only renders its children after the component has mounted on the client.\n */\nexport const NoSSR: React.FC<NoSSRProps> = ({ children, fallback }) => {\n const [isClient, setIsClient] = useState(false);\n\n // 2. useEffect runs ONLY on the client after the initial hydration is complete.\n useEffect(() => {\n // This forces the component to render a second time.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsClient(true);\n }, []);\n\n return isClient ? children : fallback;\n};\n"],"mappings":"iCAOA,OAA2B,aAAAA,EAAW,YAAAC,MAAgB,QAgB/C,IAAMC,EAA8B,CAAC,CAAE,SAAAC,EAAU,SAAAC,CAAS,IAAM,CACrE,GAAM,CAACC,EAAUC,CAAW,EAAIL,EAAS,EAAK,EAG9C,OAAAD,EAAU,IAAM,CAGdM,EAAY,EAAI,CAClB,EAAG,CAAC,CAAC,EAEED,EAAWF,EAAWC,CAC/B","names":["useEffect","useState","NoSSR","children","fallback","isClient","setIsClient"]}
package/NoSSR.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import "./chunk-X6BYQHVC.mjs";
2
+
1
3
  // src/NoSSR.tsx
2
4
  import { useEffect, useState } from "react";
3
5
  var NoSSR = ({ children, fallback }) => {
@@ -0,0 +1,43 @@
1
+ import {
2
+ __esm
3
+ } from "./chunk-X6BYQHVC.mjs";
4
+
5
+ // src/stringify.ts
6
+ function stringifyDeterministicForKeys(params) {
7
+ const cache = /* @__PURE__ */ new Set();
8
+ return JSON.stringify(params, (_, value) => {
9
+ if (typeof value === "function") {
10
+ throw new Error(`Functions should not be passed into query parameters`);
11
+ }
12
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
13
+ return value;
14
+ }
15
+ if (cache.has(value)) {
16
+ return "[Circular]";
17
+ }
18
+ cache.add(value);
19
+ if (value !== params) {
20
+ try {
21
+ JSON.stringify(value);
22
+ } catch {
23
+ return "[Unserializable]";
24
+ }
25
+ }
26
+ return Object.keys(value).sort().reduce(
27
+ (result, key) => {
28
+ result[key] = value[key];
29
+ return result;
30
+ },
31
+ {}
32
+ );
33
+ });
34
+ }
35
+ var init_stringify = __esm({
36
+ "src/stringify.ts"() {
37
+ }
38
+ });
39
+
40
+ export {
41
+ stringifyDeterministicForKeys,
42
+ init_stringify
43
+ };
@@ -0,0 +1,16 @@
1
+ // src/fetcher.ts
2
+ import wretch from "wretch";
3
+ import { retry } from "wretch/middlewares";
4
+ var fetcher = wretch().middlewares([
5
+ retry({
6
+ maxAttempts: 3,
7
+ delayTimer: 1e3,
8
+ retryOnNetworkError: true
9
+ })
10
+ ]);
11
+ var fetcherNoRetries = wretch();
12
+
13
+ export {
14
+ fetcher,
15
+ fetcherNoRetries
16
+ };
@@ -0,0 +1,195 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+ var _chunk5PDGU37Ecjs = require('./chunk-5PDGU37E.cjs');
4
+
5
+ // src/sharedState.ts
6
+ var _timeConstants = require('@choksheak/ts-utils/timeConstants');
7
+ var _react = require('react');
8
+ var SharedStateConfig = {
9
+ /**
10
+ * Default duration for storage expiration in milliseconds. Initial value
11
+ * is 30 days, but can be changed to anything.
12
+ */
13
+ storeExpiryMs: 30 * _timeConstants.MS_PER_DAY,
14
+ /**
15
+ * True to load from storage only on mount, false (default) to load in
16
+ * the top level scope when the shared state is defined.
17
+ */
18
+ lazyLoad: false
19
+ };
20
+ function configureSharedState(config) {
21
+ Object.assign(SharedStateConfig, config);
22
+ }
23
+ function createPubSubStore() {
24
+ const dataByKey = /* @__PURE__ */ new Map();
25
+ const subscribersByKey = /* @__PURE__ */ new Map();
26
+ function notify(key, next, prev) {
27
+ const subscribers = subscribersByKey.get(key);
28
+ if (!subscribers) return;
29
+ const copy = Array.from(subscribers.values());
30
+ for (const subscriber of copy) {
31
+ try {
32
+ subscriber(next, prev);
33
+ } catch (e) {
34
+ console.error(`Error invoking subscriber:`, e);
35
+ }
36
+ }
37
+ }
38
+ return {
39
+ // This could be undefined if T includes undefined, else it should never
40
+ // return undefined because the user has to always specify the default value.
41
+ get(key) {
42
+ return dataByKey.get(key);
43
+ },
44
+ set(key, value) {
45
+ const prev = dataByKey.get(key);
46
+ if (prev === value) return;
47
+ dataByKey.set(key, value);
48
+ notify(key, value, prev);
49
+ },
50
+ delete(key) {
51
+ dataByKey.delete(key);
52
+ },
53
+ setNoNotify(key, value) {
54
+ dataByKey.set(key, value);
55
+ },
56
+ // Subscribe to changes of a specific key
57
+ subscribe(key, subscriber) {
58
+ let subscribers = subscribersByKey.get(key);
59
+ if (!subscribers) {
60
+ subscribers = /* @__PURE__ */ new Set();
61
+ subscribersByKey.set(key, subscribers);
62
+ }
63
+ subscribers.add(subscriber);
64
+ return () => {
65
+ subscribers.delete(subscriber);
66
+ if (subscribers.size === 0) subscribersByKey.delete(key);
67
+ };
68
+ }
69
+ };
70
+ }
71
+ var pubSubStore = createPubSubStore();
72
+ var STORAGE_KEY = "state";
73
+ var stateKey = 0;
74
+ function sharedState(defaultValue, options) {
75
+ let readyResolve = () => {
76
+ };
77
+ const readyPromise = new Promise((resolve) => {
78
+ readyResolve = resolve;
79
+ });
80
+ const resolveReadyPromise = readyResolve;
81
+ const pubSubKey = String(stateKey++);
82
+ const storageAdapter = _chunk5PDGU37Ecjs.getStorageAdapter.call(void 0,
83
+ options,
84
+ SharedStateConfig.storeExpiryMs
85
+ );
86
+ pubSubStore.setNoNotify(pubSubKey, defaultValue);
87
+ const lazyLoad = _optionalChain([options, 'optionalAccess', _ => _.lazyLoad]);
88
+ const lazy = lazyLoad !== void 0 ? lazyLoad : SharedStateConfig.lazyLoad;
89
+ function completeInit(stored) {
90
+ const value = stored !== void 0 ? stored : defaultValue;
91
+ pubSubStore.set(pubSubKey, value);
92
+ obj.initDone = true;
93
+ resolveReadyPromise();
94
+ }
95
+ const obj = {
96
+ /** Allow users to await for the completion of data init. */
97
+ readyPromise,
98
+ lazy,
99
+ initStarted: false,
100
+ initDone: false,
101
+ /** `subscribe` function required by useSyncExternalStore. */
102
+ subscribe(subscriber) {
103
+ return pubSubStore.subscribe(pubSubKey, () => subscriber());
104
+ },
105
+ /** Returns true if there is a backing store. */
106
+ hasStore() {
107
+ return Boolean(storageAdapter);
108
+ },
109
+ /**
110
+ * Set a value directly into the store. Does nothing if there is no
111
+ * backing store.
112
+ *
113
+ * Warning: If you want to set the value properly, you should use
114
+ * `setValue()` instead which also updates the in-memory copy.
115
+ */
116
+ setInStore(value) {
117
+ return _optionalChain([storageAdapter, 'optionalAccess', _2 => _2.set, 'call', _3 => _3(STORAGE_KEY, value)]);
118
+ },
119
+ /**
120
+ * Get a value directly from the store. Returns undefined if there is no
121
+ * backing store.
122
+ */
123
+ getFromStore() {
124
+ return _optionalChain([storageAdapter, 'optionalAccess', _4 => _4.get, 'call', _5 => _5(STORAGE_KEY)]);
125
+ },
126
+ /**
127
+ * Get the value of the shared state.
128
+ * `getSnapshot` function — must return same ref if value unchanged.
129
+ * Note that this would return the default value if data init from store is
130
+ * not completed yet.
131
+ */
132
+ getSnapshot() {
133
+ return pubSubStore.get(pubSubKey);
134
+ },
135
+ /** Set the value of the shared state. */
136
+ setValue(next) {
137
+ if (typeof next === "function") {
138
+ const prev = pubSubStore.get(pubSubKey);
139
+ next = next(prev);
140
+ }
141
+ pubSubStore.set(pubSubKey, next);
142
+ void obj.setInStore(next);
143
+ },
144
+ /**
145
+ * Remove the value of the shared state. Actually this just sets the value
146
+ * back to the given default value.
147
+ */
148
+ delete() {
149
+ pubSubStore.set(pubSubKey, defaultValue);
150
+ return _optionalChain([storageAdapter, 'optionalAccess', _6 => _6.set, 'call', _7 => _7(STORAGE_KEY, defaultValue)]);
151
+ },
152
+ /** Initial default handling. */
153
+ initDefaultValueOnce() {
154
+ if (obj.initDone || obj.initStarted) return;
155
+ obj.initStarted = true;
156
+ const maybePromise = obj.getFromStore();
157
+ if (maybePromise instanceof Promise) {
158
+ return maybePromise.then(completeInit);
159
+ } else {
160
+ const stored = maybePromise;
161
+ completeInit(stored);
162
+ }
163
+ }
164
+ };
165
+ if (!lazy) {
166
+ obj.initDefaultValueOnce();
167
+ }
168
+ return obj;
169
+ }
170
+ function useSharedState(state) {
171
+ void state.initDefaultValueOnce();
172
+ const value = _react.useSyncExternalStore.call(void 0,
173
+ (onStoreChange) => state.subscribe(onStoreChange),
174
+ () => state.getSnapshot(),
175
+ // getServerSnapshot is needed to prevent SSR dev errors in nextjs.
176
+ () => state.getSnapshot()
177
+ );
178
+ return [value, state.setValue];
179
+ }
180
+ function useSharedStateValue(state) {
181
+ return useSharedState(state)[0];
182
+ }
183
+ function useSharedStateSetter(state) {
184
+ void state.initDefaultValueOnce();
185
+ return state.setValue;
186
+ }
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+ exports.SharedStateConfig = SharedStateConfig; exports.configureSharedState = configureSharedState; exports.sharedState = sharedState; exports.useSharedState = useSharedState; exports.useSharedStateValue = useSharedStateValue; exports.useSharedStateSetter = useSharedStateSetter;
@@ -0,0 +1,43 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunk74BS2FAOcjs = require('./chunk-74BS2FAO.cjs');
4
+
5
+ // src/stringify.ts
6
+ function stringifyDeterministicForKeys(params) {
7
+ const cache = /* @__PURE__ */ new Set();
8
+ return JSON.stringify(params, (_, value) => {
9
+ if (typeof value === "function") {
10
+ throw new Error(`Functions should not be passed into query parameters`);
11
+ }
12
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
13
+ return value;
14
+ }
15
+ if (cache.has(value)) {
16
+ return "[Circular]";
17
+ }
18
+ cache.add(value);
19
+ if (value !== params) {
20
+ try {
21
+ JSON.stringify(value);
22
+ } catch (e) {
23
+ return "[Unserializable]";
24
+ }
25
+ }
26
+ return Object.keys(value).sort().reduce(
27
+ (result, key) => {
28
+ result[key] = value[key];
29
+ return result;
30
+ },
31
+ {}
32
+ );
33
+ });
34
+ }
35
+ var init_stringify = _chunk74BS2FAOcjs.__esm.call(void 0, {
36
+ "src/stringify.ts"() {
37
+ }
38
+ });
39
+
40
+
41
+
42
+
43
+ exports.stringifyDeterministicForKeys = stringifyDeterministicForKeys; exports.init_stringify = init_stringify;
@@ -0,0 +1,104 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/storage.ts
2
+ var _kvStore = require('@choksheak/ts-utils/kvStore');
3
+ var _localStore = require('@choksheak/ts-utils/localStore');
4
+ var IS_NOT_BROWSER = typeof window === "undefined";
5
+ function getStorageAdapter(options, defaultStoreExpiryMs) {
6
+ const { store } = _nullishCoalesce(options, () => ( {}));
7
+ if (!store) {
8
+ return null;
9
+ }
10
+ if ("persistTo" in store && typeof store.persistTo === "string" && "key" in store && typeof store.key === "string") {
11
+ const expiryMs = store.expiryMs || defaultStoreExpiryMs;
12
+ const config = { ...store, expiryMs };
13
+ switch (store.persistTo) {
14
+ case "localStorage":
15
+ return localStoreAdapter(config);
16
+ case "indexedDb":
17
+ return kvStoreAdapter(config);
18
+ default:
19
+ store.persistTo;
20
+ throw new Error(`Unknown store.adapter ${store.persistTo}`);
21
+ }
22
+ }
23
+ return store;
24
+ }
25
+ function localStoreAdapter({
26
+ key,
27
+ expiryMs,
28
+ isValid
29
+ }) {
30
+ const STORE_NAME = "react-utils";
31
+ const adapter = _localStore.createLocalStore.call(void 0, STORE_NAME, {
32
+ defaultExpiryMs: expiryMs
33
+ });
34
+ const keyPrefix = key + ":";
35
+ return {
36
+ set: (key2, value) => {
37
+ if (IS_NOT_BROWSER) return;
38
+ adapter.set(keyPrefix + key2, value);
39
+ },
40
+ get: (key2) => {
41
+ if (IS_NOT_BROWSER) return void 0;
42
+ const fullKey = keyPrefix + key2;
43
+ const value = adapter.get(fullKey);
44
+ if (value !== void 0 && isValid && !isValid(value)) {
45
+ console.warn(
46
+ `localStorage adapter: Auto-discard invalid value for ${fullKey}: ${JSON.stringify(value)}`
47
+ );
48
+ adapter.delete(fullKey);
49
+ return void 0;
50
+ }
51
+ return value;
52
+ },
53
+ delete: (key2) => {
54
+ if (IS_NOT_BROWSER) return;
55
+ adapter.delete(keyPrefix + key2);
56
+ },
57
+ /** Note that this will clear all keys in all shared states. */
58
+ clear: () => {
59
+ if (IS_NOT_BROWSER) return;
60
+ adapter.clear();
61
+ }
62
+ };
63
+ }
64
+ function kvStoreAdapter({
65
+ key,
66
+ expiryMs,
67
+ isValid
68
+ }) {
69
+ const keyPrefix = key + ":";
70
+ return {
71
+ set: async (key2, value) => {
72
+ if (IS_NOT_BROWSER) return;
73
+ await _kvStore.kvStore.set(keyPrefix + key2, value, expiryMs);
74
+ },
75
+ get: async (key2) => {
76
+ if (IS_NOT_BROWSER) return void 0;
77
+ const fullKey = keyPrefix + key2;
78
+ const value = await _kvStore.kvStore.get(fullKey);
79
+ if (value !== void 0 && isValid && !isValid(value)) {
80
+ console.warn(
81
+ `indexedDb adapter: Auto-discard invalid value for ${key2}:`,
82
+ value
83
+ );
84
+ await _kvStore.kvStore.delete(fullKey);
85
+ return void 0;
86
+ }
87
+ return value;
88
+ },
89
+ delete: async (key2) => {
90
+ if (IS_NOT_BROWSER) return;
91
+ await _kvStore.kvStore.delete(keyPrefix + key2);
92
+ },
93
+ clear: async () => {
94
+ if (IS_NOT_BROWSER) return;
95
+ await _kvStore.kvStore.clear();
96
+ }
97
+ };
98
+ }
99
+
100
+
101
+
102
+
103
+
104
+ exports.getStorageAdapter = getStorageAdapter; exports.localStoreAdapter = localStoreAdapter; exports.kvStoreAdapter = kvStoreAdapter;
@@ -0,0 +1,2 @@
1
+ import r from"wretch";import{retry as e}from"wretch/middlewares";var m=r().middlewares([e({maxAttempts:3,delayTimer:1e3,retryOnNetworkError:!0})]),c=r();export{m as a,c as b};
2
+ //# sourceMappingURL=chunk-6ZZ54XM5.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fetcher.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * An alternate syntax to fetch() that allows function chaining to compose the\n * entire fetch request. One can also compose partial fetcher objects to be\n * reused in future requests.\n *\n * Examples:\n * ```\n * const userFetcher = fetcher\n * .auth(\"Bearer TOPSECRET\")\n * .content(\"application/json\")\n * .url(\"/api/user\");\n *\n * const user = await userFetcher.get();\n *\n * const updateResult = await userFetcher\n * .body({ id: user.id, name: \"New name\"})\n * .post();\n * ```\n */\n\nimport wretch from \"wretch\";\nimport { retry } from \"wretch/middlewares\";\n\n/**\n * Fetcher with default short retries. Use this to make your queries more\n * robust without any additional work.\n */\nexport const fetcher = wretch().middlewares([\n retry({\n maxAttempts: 3,\n delayTimer: 1000,\n retryOnNetworkError: true,\n }),\n]);\n\n/**\n * Name this as `fetcherNoRetries` to make it easier to understand than\n * `wretch`. Use this if you don't want retries. Use `fetcher` if you want\n * retries.\n */\nexport const fetcherNoRetries = wretch();\n"],"mappings":"AAsBA,OAAOA,MAAY,SACnB,OAAS,SAAAC,MAAa,qBAMf,IAAMC,EAAUF,EAAO,EAAE,YAAY,CAC1CC,EAAM,CACJ,YAAa,EACb,WAAY,IACZ,oBAAqB,EACvB,CAAC,CACH,CAAC,EAOYE,EAAmBH,EAAO","names":["wretch","retry","fetcher","fetcherNoRetries"]}
@@ -0,0 +1,12 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __esm = (fn, res) => function __init() {
3
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ };
5
+ var __commonJS = (cb, mod) => function __require() {
6
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
7
+ };
8
+
9
+
10
+
11
+
12
+ exports.__esm = __esm; exports.__commonJS = __commonJS;
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _isEqual = require('lodash/isEqual'); var _isEqual2 = _interopRequireDefault(_isEqual);var _react = require('react');function f(t){let[e,r]=_react.useState.call(void 0, t);return _react.useMemo.call(void 0, ()=>_isEqual2.default.call(void 0, e,t)?e:(r(t),t),[e,t])}exports.a = f;
2
+ //# sourceMappingURL=chunk-F5L32IUC.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useDeepMemo.ts"],"names":["useDeepMemo","value","state","setState","useState","useMemo","isEqual"],"mappings":"AAYA,oQAAoB,8BACc,SAMlBA,CAAAA,CAAeC,CAAAA,CAAa,CAC1C,GAAM,CAACC,CAAAA,CAAOC,CAAQ,CAAA,CAAIC,6BAAAA,CAAiB,CAAA,CAE3C,OAAOC,4BAAAA,CAAQ,CAAA,EACTC,+BAAAA,CAAQJ,CAAOD,CAAK,CAAA,CACfC,CAAAA,CAAAA,CAKTC,CAAAA,CAASF,CAAK,CAAA,CAEPA,CAAAA,CAAAA,CACN,CAACC,CAAAA,CAAOD,CAAK,CAAC,CACnB,CAAA,cAAA","file":"/Users/choksheaklau/src/react-utils/dist/chunk-F5L32IUC.min.cjs","sourcesContent":["/**\n * @packageDocumentation\n *\n * Provides a memoized value in React where the value is checked for deep\n * equality. If the value has changed, but is deeply equal to the previous\n * value, then useDeepMemo will return the same reference to the previous\n * value and ignore the latest value.\n *\n * This is mainly used in shared queries to check for changes in the query\n * arguments, but it might be useful for your own use cases.\n */\n\nimport isEqual from \"lodash/isEqual\";\nimport { useMemo, useState } from \"react\";\n\n/**\n * Provides a stable value for T based on deep equality. The deep equality is\n * determined by the `isEqual()` function in lodash.\n */\nexport function useDeepMemo<T>(value: T): T {\n const [state, setState] = useState<T>(value);\n\n return useMemo(() => {\n if (isEqual(state, value)) {\n return state;\n }\n\n // We check equality, so this should be safe.\n // eslint-disable-next-line react-hooks/set-state-in-render\n setState(value);\n\n return value;\n }, [state, value]);\n}\n"]}
@@ -0,0 +1,17 @@
1
+ // src/useDeepMemo.ts
2
+ import isEqual from "lodash/isEqual";
3
+ import { useMemo, useState } from "react";
4
+ function useDeepMemo(value) {
5
+ const [state, setState] = useState(value);
6
+ return useMemo(() => {
7
+ if (isEqual(state, value)) {
8
+ return state;
9
+ }
10
+ setState(value);
11
+ return value;
12
+ }, [state, value]);
13
+ }
14
+
15
+ export {
16
+ useDeepMemo
17
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var c=(b,a)=>()=>(b&&(a=b(b=0)),a);var d=(b,a)=>()=>(a||b((a={exports:{}}).exports,a),a.exports);exports.a = c; exports.b = d;
2
+ //# sourceMappingURL=chunk-KE3RXVMS.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/choksheaklau/src/react-utils/dist/chunk-KE3RXVMS.min.cjs"],"names":[],"mappings":"AAAA,6EAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,6BAAqB","file":"/Users/choksheaklau/src/react-utils/dist/chunk-KE3RXVMS.min.cjs"}
@@ -0,0 +1,2 @@
1
+ import{a as l}from"./chunk-VHMO75EY.min.mjs";import{MS_PER_DAY as g}from"@choksheak/ts-utils/timeConstants";import{useSyncExternalStore as y}from"react";var b={storeExpiryMs:30*g,lazyLoad:!1};function z(e){Object.assign(b,e)}function v(){let e=new Map,i=new Map;function S(o,n,t){let a=i.get(o);if(!a)return;let d=Array.from(a.values());for(let c of d)try{c(n,t)}catch(f){console.error("Error invoking subscriber:",f)}}return{get(o){return e.get(o)},set(o,n){let t=e.get(o);t!==n&&(e.set(o,n),S(o,n,t))},delete(o){e.delete(o)},setNoNotify(o,n){e.set(o,n)},subscribe(o,n){let t=i.get(o);return t||(t=new Set,i.set(o,t)),t.add(n),()=>{t.delete(n),t.size===0&&i.delete(o)}}}}var u=v(),T="state",h=0;function E(e,i){let S=()=>{},o=new Promise(r=>{S=r}),n=S,t=String(h++),a=l(i,b.storeExpiryMs);u.setNoNotify(t,e);let d=i?.lazyLoad,c=d!==void 0?d:b.lazyLoad;function f(r){let p=r!==void 0?r:e;u.set(t,p),s.initDone=!0,n()}let s={readyPromise:o,lazy:c,initStarted:!1,initDone:!1,subscribe(r){return u.subscribe(t,()=>r())},hasStore(){return!!a},setInStore(r){return a?.set(T,r)},getFromStore(){return a?.get(T)},getSnapshot(){return u.get(t)},setValue(r){if(typeof r=="function"){let p=u.get(t);r=r(p)}u.set(t,r),s.setInStore(r)},delete(){return u.set(t,e),a?.set(T,e)},initDefaultValueOnce(){if(s.initDone||s.initStarted)return;s.initStarted=!0;let r=s.getFromStore();if(r instanceof Promise)return r.then(f);f(r)}};return c||s.initDefaultValueOnce(),s}function m(e){return e.initDefaultValueOnce(),[y(S=>e.subscribe(S),()=>e.getSnapshot(),()=>e.getSnapshot()),e.setValue]}function K(e){return m(e)[0]}function L(e){return e.initDefaultValueOnce(),e.setValue}export{b as a,z as b,E as c,m as d,K as e,L as f};
2
+ //# sourceMappingURL=chunk-KILGR7YA.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sharedState.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * The \"shared state\" is a React state that shares the same value across the\n * entire app. Users declare a shared state constant that can be reused across\n * multiple components with the same underlying value.\n *\n * Shared states provide persistence to local storage and/or indexed DB out of\n * the box, by using \"@choksheak/ts-utils\". Note that no matter if the shared\n * state uses persistence or not, it will always maintain a copy of the state\n * in memory. Persisted values can be configured with an automatic expiration\n * duration.\n *\n * This module is largely similar to the open source \"jotai\" npm library. You\n * can use shared states to replace \"jotai\" in your code, and optionally make\n * use of the persistence mechanism. A quick migration guide from jotai is:\n *\n * ```\n * atom() --> sharedState()\n * useAtom() --> useSharedState()\n * useAtomValue() --> useSharedStateValue()\n * useSetAtom() --> useSharedStateSetter()\n * ```\n *\n * Example:\n * ```\n * import { sharedState, useSharedState } from \"@choksheak/react-utils/sharedState\";\n *\n * // Create a new shared state in the top level scope.\n * // The first argument is the default value, which is required.\n * // The second argument is an options object, and is optional (defaults\n * // to storing in memory only without any persistence).\n * const usersState = sharedState(\n * [], { store: { persistTo: \"indexedDb\", key: \"users\" }}\n * );\n *\n * export const UsersComponent: React.FC = () => {\n * // Get both the value and the setter.\n * const [users, setUsers] = useSharedState(usersState);\n * ...\n * };\n *\n * export const ReadOnlyComponent: React.FC = () => {\n * // Get the value only.\n * const users = useSharedStateValue(usersState);\n * ...\n * };\n *\n * export const WriteOnlyComponent: React.FC = () => {\n * // Get the setter only.\n * const setUsers = useSharedStateSetter(usersState);\n * ...\n * };\n * ```\n */\n\nimport { MS_PER_DAY } from \"@choksheak/ts-utils/timeConstants\";\nimport { Dispatch, SetStateAction, useSyncExternalStore } from \"react\";\n\nimport { getStorageAdapter, StorageOptions } from \"./storage\";\n\n/************************************************************************/\n/* Global config */\n/************************************************************************/\n\n/**\n * These values are configurable by the user at any time.\n */\nexport const SharedStateConfig = {\n /**\n * Default duration for storage expiration in milliseconds. Initial value\n * is 30 days, but can be changed to anything.\n */\n storeExpiryMs: 30 * MS_PER_DAY,\n\n /**\n * True to load from storage only on mount, false (default) to load in\n * the top level scope when the shared state is defined.\n */\n lazyLoad: false,\n};\n\nexport type SharedStateConfig = typeof SharedStateConfig;\n\n/** Convenience function to update global defaults. */\nexport function configureSharedState(config: Partial<SharedStateConfig>) {\n Object.assign(SharedStateConfig, config);\n}\n\n/************************************************************************/\n/* Pub-sub store\n/************************************************************************/\n\ntype Subscriber<T> = (next: T, prev: T) => void;\n\nfunction createPubSubStore() {\n const dataByKey = new Map<string, unknown>();\n const subscribersByKey = new Map<string, Set<Subscriber<unknown>>>();\n\n function notify<T>(key: string, next: T, prev: T): void {\n const subscribers = subscribersByKey.get(key);\n if (!subscribers) return;\n\n // Make copy to protect against mutation during iteration.\n const copy = Array.from(subscribers.values());\n for (const subscriber of copy) {\n try {\n subscriber(next, prev);\n } catch (e) {\n console.error(`Error invoking subscriber:`, e);\n }\n }\n }\n\n return {\n // This could be undefined if T includes undefined, else it should never\n // return undefined because the user has to always specify the default value.\n get<T>(key: string): T {\n return dataByKey.get(key) as T;\n },\n\n set<T>(key: string, value: T): void {\n const prev = dataByKey.get(key) as T;\n\n // Do nothing if no change.\n if (prev === value) return;\n\n dataByKey.set(key, value);\n notify(key, value, prev);\n },\n\n delete(key: string): void {\n dataByKey.delete(key);\n },\n\n setNoNotify<T>(key: string, value: T): void {\n dataByKey.set(key, value);\n },\n\n // Subscribe to changes of a specific key\n subscribe<T>(key: string, subscriber: Subscriber<T>): () => void {\n let subscribers = subscribersByKey.get(key);\n if (!subscribers) {\n subscribers = new Set();\n subscribersByKey.set(key, subscribers);\n }\n\n // Type coercion: we store Subscriber<unknown>\n subscribers.add(subscriber as Subscriber<unknown>);\n\n // Return unsubscribe function\n return () => {\n subscribers.delete(subscriber as Subscriber<unknown>);\n if (subscribers.size === 0) subscribersByKey.delete(key);\n };\n },\n } as const;\n}\n\nconst pubSubStore = createPubSubStore();\n\n/************************************************************************/\n/* Shared state implementation */\n/************************************************************************/\n\nconst STORAGE_KEY = \"state\";\n\n/** Options to configure a shared state. */\nexport type SharedStateOptions<T> = {\n lazyLoad?: boolean;\n} & StorageOptions<T>;\n\nlet stateKey = 0;\n\n/**\n * Create a new shared state object. Put this code at the top level scope:\n *\n * Example:\n * ```\n * const counterState = sharedState<number>(0);\n * ```\n */\nexport function sharedState<T>(\n defaultValue: T,\n options?: SharedStateOptions<T>,\n) {\n let readyResolve: () => void = () => {};\n\n const readyPromise = new Promise<void>((resolve) => {\n readyResolve = resolve;\n });\n\n const resolveReadyPromise = readyResolve;\n\n const pubSubKey = String(stateKey++);\n\n // Use max of 1 storage adapter per shared state.\n const storageAdapter = getStorageAdapter(\n options,\n SharedStateConfig.storeExpiryMs,\n );\n\n // Always set the default value first to avoid returning undefineds if that\n // is not part of T. Don't notify with the default value.\n pubSubStore.setNoNotify(pubSubKey, defaultValue);\n\n const lazyLoad = options?.lazyLoad;\n const lazy = lazyLoad !== undefined ? lazyLoad : SharedStateConfig.lazyLoad;\n\n function completeInit(stored: T | undefined) {\n const value = stored !== undefined ? stored : defaultValue;\n\n pubSubStore.set(pubSubKey, value);\n\n // @ts-expect-error ts(2540) - Assign to readonly property.\n obj.initDone = true;\n resolveReadyPromise();\n }\n\n const obj = {\n /** Allow users to await for the completion of data init. */\n readyPromise,\n\n lazy,\n\n initStarted: false,\n initDone: false,\n\n /** `subscribe` function required by useSyncExternalStore. */\n subscribe(subscriber: () => void): () => void {\n return pubSubStore.subscribe(pubSubKey, () => subscriber());\n },\n\n /** Returns true if there is a backing store. */\n hasStore(): boolean {\n return Boolean(storageAdapter);\n },\n\n /**\n * Set a value directly into the store. Does nothing if there is no\n * backing store.\n *\n * Warning: If you want to set the value properly, you should use\n * `setValue()` instead which also updates the in-memory copy.\n */\n setInStore(value: T): Promise<void> | void {\n return storageAdapter?.set(STORAGE_KEY, value);\n },\n\n /**\n * Get a value directly from the store. Returns undefined if there is no\n * backing store.\n */\n getFromStore(): Promise<T | undefined> | T | undefined {\n return storageAdapter?.get(STORAGE_KEY);\n },\n\n /**\n * Get the value of the shared state.\n * `getSnapshot` function — must return same ref if value unchanged.\n * Note that this would return the default value if data init from store is\n * not completed yet.\n */\n getSnapshot(): T {\n return pubSubStore.get(pubSubKey);\n },\n\n /** Set the value of the shared state. */\n setValue(next: SetStateAction<T>): void {\n if (typeof next === \"function\") {\n const prev = pubSubStore.get<T>(pubSubKey);\n next = (next as (p: T) => T)(prev);\n }\n\n pubSubStore.set(pubSubKey, next);\n void obj.setInStore(next);\n },\n\n /**\n * Remove the value of the shared state. Actually this just sets the value\n * back to the given default value.\n */\n delete(): Promise<void> | void {\n pubSubStore.set(pubSubKey, defaultValue);\n return storageAdapter?.set(STORAGE_KEY, defaultValue);\n },\n\n /** Initial default handling. */\n initDefaultValueOnce(): Promise<void> | void {\n if (obj.initDone || obj.initStarted) return;\n // @ts-expect-error ts(2540) - Assign to readonly property.\n obj.initStarted = true;\n\n const maybePromise = obj.getFromStore();\n\n // Allow sync vs async code paths. This allows init to be fully completed\n // from store before the sharedState() function returns.\n if (maybePromise instanceof Promise) {\n return maybePromise.then(completeInit);\n } else {\n const stored = maybePromise;\n completeInit(stored);\n }\n },\n } as const;\n\n if (!lazy) {\n obj.initDefaultValueOnce();\n }\n\n return obj;\n}\n\nexport type SharedState<T> = ReturnType<typeof sharedState<T>>;\n\n/**\n * React hook for subscribing to a key in the global store.\n *\n * Example:\n * ```\n * const [counter, setCounter] = useSharedState(counterState);\n * ```\n */\nexport function useSharedState<T>(\n state: SharedState<T>,\n): [T, Dispatch<SetStateAction<T>>] {\n void state.initDefaultValueOnce();\n\n const value = useSyncExternalStore(\n (onStoreChange) => state.subscribe(onStoreChange),\n () => state.getSnapshot(),\n // getServerSnapshot is needed to prevent SSR dev errors in nextjs.\n () => state.getSnapshot(),\n );\n\n return [value, state.setValue];\n}\n\n/**\n * Same as useSharedState(), but returns the value only.\n *\n * Example:\n * ```\n * const counter = useSharedStateValue(counterState);\n * ```\n */\nexport function useSharedStateValue<T>(state: SharedState<T>) {\n return useSharedState(state)[0];\n}\n\n/**\n * Same as useSharedState(), but returns the setter only.\n *\n * Example:\n * ```\n * const setCounter = useSharedStateSetter(counterState);\n * ```\n */\nexport function useSharedStateSetter<T>(state: SharedState<T>) {\n void state.initDefaultValueOnce();\n\n return state.setValue;\n}\n"],"mappings":"6CAwDA,OAAS,cAAAA,MAAkB,oCAC3B,OAAmC,wBAAAC,MAA4B,QAWxD,IAAMC,EAAoB,CAK/B,cAAe,GAAKC,EAMpB,SAAU,EACZ,EAKO,SAASC,EAAqBC,EAAoC,CACvE,OAAO,OAAOH,EAAmBG,CAAM,CACzC,CAQA,SAASC,GAAoB,CAC3B,IAAMC,EAAY,IAAI,IAChBC,EAAmB,IAAI,IAE7B,SAASC,EAAUC,EAAaC,EAASC,EAAe,CACtD,IAAMC,EAAcL,EAAiB,IAAIE,CAAG,EAC5C,GAAI,CAACG,EAAa,OAGlB,IAAMC,EAAO,MAAM,KAAKD,EAAY,OAAO,CAAC,EAC5C,QAAWE,KAAcD,EACvB,GAAI,CACFC,EAAWJ,EAAMC,CAAI,CACvB,OAASI,EAAG,CACV,QAAQ,MAAM,6BAA8BA,CAAC,CAC/C,CAEJ,CAEA,MAAO,CAGL,IAAON,EAAgB,CACrB,OAAOH,EAAU,IAAIG,CAAG,CAC1B,EAEA,IAAOA,EAAaO,EAAgB,CAClC,IAAML,EAAOL,EAAU,IAAIG,CAAG,EAG1BE,IAASK,IAEbV,EAAU,IAAIG,EAAKO,CAAK,EACxBR,EAAOC,EAAKO,EAAOL,CAAI,EACzB,EAEA,OAAOF,EAAmB,CACxBH,EAAU,OAAOG,CAAG,CACtB,EAEA,YAAeA,EAAaO,EAAgB,CAC1CV,EAAU,IAAIG,EAAKO,CAAK,CAC1B,EAGA,UAAaP,EAAaK,EAAuC,CAC/D,IAAIF,EAAcL,EAAiB,IAAIE,CAAG,EAC1C,OAAKG,IACHA,EAAc,IAAI,IAClBL,EAAiB,IAAIE,EAAKG,CAAW,GAIvCA,EAAY,IAAIE,CAAiC,EAG1C,IAAM,CACXF,EAAY,OAAOE,CAAiC,EAChDF,EAAY,OAAS,GAAGL,EAAiB,OAAOE,CAAG,CACzD,CACF,CACF,CACF,CAEA,IAAMQ,EAAcZ,EAAkB,EAMhCa,EAAc,QAOhBC,EAAW,EAUR,SAASC,EACdC,EACAC,EACA,CACA,IAAIC,EAA2B,IAAM,CAAC,EAEhCC,EAAe,IAAI,QAAeC,GAAY,CAClDF,EAAeE,CACjB,CAAC,EAEKC,EAAsBH,EAEtBI,EAAY,OAAOR,GAAU,EAG7BS,EAAiBC,EACrBP,EACArB,EAAkB,aACpB,EAIAgB,EAAY,YAAYU,EAAWN,CAAY,EAE/C,IAAMS,EAAWR,GAAS,SACpBS,EAAOD,IAAa,OAAYA,EAAW7B,EAAkB,SAEnE,SAAS+B,EAAaC,EAAuB,CAC3C,IAAMjB,EAAQiB,IAAW,OAAYA,EAASZ,EAE9CJ,EAAY,IAAIU,EAAWX,CAAK,EAGhCkB,EAAI,SAAW,GACfR,EAAoB,CACtB,CAEA,IAAMQ,EAAM,CAEV,aAAAV,EAEA,KAAAO,EAEA,YAAa,GACb,SAAU,GAGV,UAAUjB,EAAoC,CAC5C,OAAOG,EAAY,UAAUU,EAAW,IAAMb,EAAW,CAAC,CAC5D,EAGA,UAAoB,CAClB,MAAO,EAAQc,CACjB,EASA,WAAWZ,EAAgC,CACzC,OAAOY,GAAgB,IAAIV,EAAaF,CAAK,CAC/C,EAMA,cAAuD,CACrD,OAAOY,GAAgB,IAAIV,CAAW,CACxC,EAQA,aAAiB,CACf,OAAOD,EAAY,IAAIU,CAAS,CAClC,EAGA,SAASjB,EAA+B,CACtC,GAAI,OAAOA,GAAS,WAAY,CAC9B,IAAMC,EAAOM,EAAY,IAAOU,CAAS,EACzCjB,EAAQA,EAAqBC,CAAI,CACnC,CAEAM,EAAY,IAAIU,EAAWjB,CAAI,EAC1BwB,EAAI,WAAWxB,CAAI,CAC1B,EAMA,QAA+B,CAC7B,OAAAO,EAAY,IAAIU,EAAWN,CAAY,EAChCO,GAAgB,IAAIV,EAAaG,CAAY,CACtD,EAGA,sBAA6C,CAC3C,GAAIa,EAAI,UAAYA,EAAI,YAAa,OAErCA,EAAI,YAAc,GAElB,IAAMC,EAAeD,EAAI,aAAa,EAItC,GAAIC,aAAwB,QAC1B,OAAOA,EAAa,KAAKH,CAAY,EAGrCA,EADeG,CACI,CAEvB,CACF,EAEA,OAAKJ,GACHG,EAAI,qBAAqB,EAGpBA,CACT,CAYO,SAASE,EACdC,EACkC,CAClC,OAAKA,EAAM,qBAAqB,EASzB,CAPOC,EACXC,GAAkBF,EAAM,UAAUE,CAAa,EAChD,IAAMF,EAAM,YAAY,EAExB,IAAMA,EAAM,YAAY,CAC1B,EAEeA,EAAM,QAAQ,CAC/B,CAUO,SAASG,EAAuBH,EAAuB,CAC5D,OAAOD,EAAeC,CAAK,EAAE,CAAC,CAChC,CAUO,SAASI,EAAwBJ,EAAuB,CAC7D,OAAKA,EAAM,qBAAqB,EAEzBA,EAAM,QACf","names":["MS_PER_DAY","useSyncExternalStore","SharedStateConfig","MS_PER_DAY","configureSharedState","config","createPubSubStore","dataByKey","subscribersByKey","notify","key","next","prev","subscribers","copy","subscriber","e","value","pubSubStore","STORAGE_KEY","stateKey","sharedState","defaultValue","options","readyResolve","readyPromise","resolve","resolveReadyPromise","pubSubKey","storageAdapter","getStorageAdapter","lazyLoad","lazy","completeInit","stored","obj","maybePromise","useSharedState","state","useSyncExternalStore","onStoreChange","useSharedStateValue","useSharedStateSetter"]}