UNPKG

react-shared-states

Version:

Global state made as simple as useState, with zero config, built-in async caching, and automatic scoping.

702 lines (700 loc) 20.1 kB
/*! * react-shared-states v1.0.11 * (c) Hichem Taboukouyout * Released under the MIT License. * Github: github.com/HichemTab-tech/react-shared-states */ import he, { createContext as Se, useMemo as L, useContext as ge, useEffect as te, useSyncExternalStore as V } from "react"; var k = { exports: {} }, j = {}; /** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var M; function xe() { if (M) return j; M = 1; var i = Symbol.for("react.transitional.element"), e = Symbol.for("react.fragment"); function r(t, n, c) { var a = null; if (c !== void 0 && (a = "" + c), n.key !== void 0 && (a = "" + n.key), "key" in n) { c = {}; for (var b in n) b !== "key" && (c[b] = n[b]); } else c = n; return n = c.ref, { $$typeof: i, type: t, key: a, ref: n !== void 0 ? n : null, props: c }; } return j.Fragment = e, j.jsx = r, j.jsxs = r, j; } var C = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var Q; function ve() { return Q || (Q = 1, process.env.NODE_ENV !== "production" && function() { function i(s) { if (s == null) return null; if (typeof s == "function") return s.$$typeof === de ? null : s.displayName || s.name || null; if (typeof s == "string") return s; switch (s) { case S: return "Fragment"; case y: return "Profiler"; case P: return "StrictMode"; case ce: return "Suspense"; case ue: return "SuspenseList"; case fe: return "Activity"; } if (typeof s == "object") switch (typeof s.tag == "number" && console.error( "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." ), s.$$typeof) { case p: return "Portal"; case ie: return (s.displayName || "Context") + ".Provider"; case ae: return (s._context.displayName || "Context") + ".Consumer"; case oe: var o = s.render; return s = s.displayName, s || (s = o.displayName || o.name || "", s = s !== "" ? "ForwardRef(" + s + ")" : "ForwardRef"), s; case le: return o = s.displayName || null, o !== null ? o : i(s.type) || "Memo"; case q: o = s._payload, s = s._init; try { return i(s(o)); } catch { } } return null; } function e(s) { return "" + s; } function r(s) { try { e(s); var o = !1; } catch { o = !0; } if (o) { o = console; var f = o.error, g = typeof Symbol == "function" && Symbol.toStringTag && s[Symbol.toStringTag] || s.constructor.name || "Object"; return f.call( o, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", g ), e(s); } } function t(s) { if (s === S) return "<>"; if (typeof s == "object" && s !== null && s.$$typeof === q) return "<...>"; try { var o = i(s); return o ? "<" + o + ">" : "<...>"; } catch { return "<...>"; } } function n() { var s = N.A; return s === null ? null : s.getOwner(); } function c() { return Error("react-stack-top-frame"); } function a(s) { if (J.call(s, "key")) { var o = Object.getOwnPropertyDescriptor(s, "key").get; if (o && o.isReactWarning) return !1; } return s.key !== void 0; } function b(s, o) { function f() { z || (z = !0, console.error( "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", o )); } f.isReactWarning = !0, Object.defineProperty(s, "key", { get: f, configurable: !0 }); } function E() { var s = i(this.type); return X[s] || (X[s] = !0, console.error( "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release." )), s = this.props.ref, s !== void 0 ? s : null; } function A(s, o, f, g, w, _, Y, $) { return f = _.ref, s = { $$typeof: h, type: s, key: o, props: _, _owner: w }, (f !== void 0 ? f : null) !== null ? Object.defineProperty(s, "ref", { enumerable: !1, get: E }) : Object.defineProperty(s, "ref", { enumerable: !1, value: null }), s._store = {}, Object.defineProperty(s._store, "validated", { configurable: !1, enumerable: !1, writable: !0, value: 0 }), Object.defineProperty(s, "_debugInfo", { configurable: !1, enumerable: !1, writable: !0, value: null }), Object.defineProperty(s, "_debugStack", { configurable: !1, enumerable: !1, writable: !0, value: Y }), Object.defineProperty(s, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: $ }), Object.freeze && (Object.freeze(s.props), Object.freeze(s)), s; } function T(s, o, f, g, w, _, Y, $) { var x = o.children; if (x !== void 0) if (g) if (pe(x)) { for (g = 0; g < x.length; g++) l(x[g]); Object.freeze && Object.freeze(x); } else console.error( "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead." ); else l(x); if (J.call(o, "key")) { x = i(s); var O = Object.keys(o).filter(function(be) { return be !== "key"; }); g = 0 < O.length ? "{key: someKey, " + O.join(": ..., ") + ": ...}" : "{key: someKey}", Z[x + g] || (O = 0 < O.length ? "{" + O.join(": ..., ") + ": ...}" : "{}", console.error( `A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`, g, x, O, x ), Z[x + g] = !0); } if (x = null, f !== void 0 && (r(f), x = "" + f), a(o) && (r(o.key), x = "" + o.key), "key" in o) { f = {}; for (var I in o) I !== "key" && (f[I] = o[I]); } else f = o; return x && b( f, typeof s == "function" ? s.displayName || s.name || "Unknown" : s ), A( s, x, _, w, n(), f, Y, $ ); } function l(s) { typeof s == "object" && s !== null && s.$$typeof === h && s._store && (s._store.validated = 1); } var v = he, h = Symbol.for("react.transitional.element"), p = Symbol.for("react.portal"), S = Symbol.for("react.fragment"), P = Symbol.for("react.strict_mode"), y = Symbol.for("react.profiler"), ae = Symbol.for("react.consumer"), ie = Symbol.for("react.context"), oe = Symbol.for("react.forward_ref"), ce = Symbol.for("react.suspense"), ue = Symbol.for("react.suspense_list"), le = Symbol.for("react.memo"), q = Symbol.for("react.lazy"), fe = Symbol.for("react.activity"), de = Symbol.for("react.client.reference"), N = v.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, J = Object.prototype.hasOwnProperty, pe = Array.isArray, F = console.createTask ? console.createTask : function() { return null; }; v = { react_stack_bottom_frame: function(s) { return s(); } }; var z, X = {}, B = v.react_stack_bottom_frame.bind( v, c )(), H = F(t(c)), Z = {}; C.Fragment = S, C.jsx = function(s, o, f, g, w) { var _ = 1e4 > N.recentlyCreatedOwnerStacks++; return T( s, o, f, !1, g, w, _ ? Error("react-stack-top-frame") : B, _ ? F(t(s)) : H ); }, C.jsxs = function(s, o, f, g, w) { var _ = 1e4 > N.recentlyCreatedOwnerStacks++; return T( s, o, f, !0, g, w, _ ? Error("react-stack-top-frame") : B, _ ? F(t(s)) : H ); }; }()), C; } var K; function Ee() { return K || (K = 1, process.env.NODE_ENV === "production" ? k.exports = xe() : k.exports = ve()), k.exports; } var me = Ee(); let re = !1; const Oe = (i) => { re = i; }, W = (...i) => { re && console.log( "%c[react-shared-states]", "color: #007acc; font-weight: bold", ...i ); }, D = (i) => { if (!i) throw new Error("Value is empty"); return i; }, se = () => Math.random().toString(36).substring(2, 15), ne = Se(void 0), je = ({ children: i, scopeName: e }) => { if (e && e.includes("//")) throw new Error("scopeName cannot contain '//'"); return e || (e = L(() => se(), [])), /* @__PURE__ */ me.jsx(ne.Provider, { value: { scopeName: e }, children: i }); }, Re = () => ge(ne), ee = []; class u { data = /* @__PURE__ */ new Map(); defaultValue() { return {}; } addListener(e, r, t) { this.data.has(u.prefix(e, r)) || this.data.set(u.prefix(e, r), { ...this.defaultValue(), listeners: [] }), this.data.get(u.prefix(e, r)).listeners.push(t); } removeListener(e, r, t) { this.data.has(u.prefix(e, r)) && (this.data.get(u.prefix(e, r)).listeners = this.data.get(u.prefix(e, r)).listeners.filter((n) => n !== t)); } callListeners(e, r) { this.data.has(u.prefix(e, r)) && this.data.get(u.prefix(e, r)).listeners.forEach((t) => t()); } init(e, r, t, n = !1) { this.data.has(u.prefix(e, r)) || this.data.set(u.prefix(e, r), { ...t, isStatic: n, listeners: [] }); } createStatic(e, r) { const t = r ?? r ?? "_global", n = { key: se(), prefix: t, ...e }; return ee.push(n), this.initStatic(n), n; } initStatic(e) { const { key: r, prefix: t } = e; this.init(r, t, this.defaultValue(), !0); } clearAll(e = !1, r = !1) { this.data.forEach((t, n) => { const [c, a] = u.extractPrefix(n); this.clear(a, c, e, r); }); } clear(e, r, t = !1, n = !1) { t || this.callListeners(e, r); const c = this.data.get(u.prefix(e, r)); if (!c) return; const a = { ...c }; if (this.data.delete(u.prefix(e, r)), a.isStatic && !n) { const b = ee.find((E) => E.key === e && E.prefix === r); b && this.initStatic(b); } } get(e, r) { let t = this.has(e, r); if (t) return this.data.get(t); } setValue(e, r, t) { this.data.has(u.prefix(e, r)) && this.data.set(u.prefix(e, r), { ...this.data.get(u.prefix(e, r)), ...t }); } has(e, r) { return this.data.has(u.prefix(e, r)) ? u.prefix(e, r) : this.data.has(u.prefix(e, "_global")) ? u.prefix(e, "_global") : void 0; } static prefix(e, r) { if (e.includes("//")) throw new Error("key cannot contain '//'"); return `${r}//${e}`; } static extractPrefix(e) { return e.split("//"); } useEffect(e, r, t = null) { te(() => () => { t?.(), W(`[${u.prefix(e, r)}]`, "unmount effect"), this.data.get(u.prefix(e, r)).listeners?.length === 0 && this.clear(e, r); }, []); } } class U { constructor(e) { this.sharedData = e; } get(e, r) { let t, n = r; if (typeof e != "string") { const { key: b, prefix: E } = e; t = b, n = E; } else t = D(e); const c = n || "_global"; return this.sharedData.get(t, c); } set(e, r, t) { let n, c = t; if (typeof e != "string") { const { key: b, prefix: E } = e; n = b, c = E; } else n = D(e); const a = c || "_global"; this.sharedData.setValue(n, a, r); } /** * clear all values from the shared data */ clearAll() { this.sharedData.clearAll(); } /** * clear all values from the shared data in a scope * @param scopeName */ clearScope(e) { const r = e || "_global"; this.sharedData.data.forEach((t, n) => { const [c, a] = u.extractPrefix(n); if (c === r) { this.sharedData.clear(a, c); return; } }); } /** * resolve a shared created object to a value * @param sharedCreated */ resolve(e) { const { key: r, prefix: t } = e; return this.get(r, t); } clear(e, r) { let t, n; typeof e == "string" ? (t = e, n = r || "_global") : (t = e.key, n = e.prefix), this.sharedData.clear(t, n); } /** * check if a value exists in the shared data * @param key * @param scopeName */ has(e, r = "_global") { const t = r || "_global"; return !!this.sharedData.has(e, t); } /** * get all values from the shared data */ getAll() { const e = {}; return this.sharedData.data.forEach((r, t) => { const [n, c] = u.extractPrefix(t); e[n] = e[n] || {}, e[n][c] = r; }), e; } } const G = (i) => { const e = Re(); return { prefix: i ?? e?.scopeName ?? "_global" }; }; class _e extends u { defaultValue() { return { value: void 0 }; } initValue(e, r, t, n = !1) { super.init(e, r, { value: t }, n); } initStatic(e) { const { key: r, prefix: t, initialValue: n } = e; this.initValue(r, t, n, !0); } } class Te extends U { constructor(e) { super(e); } get(e, r = "_global") { return typeof e != "string" ? super.get(e)?.value : super.get(e, r)?.value; } set(e, r, t = "_global") { if (typeof e != "string") { super.set(e, { value: r }); return; } super.set(e, { value: r }, t); } } const R = new _e(), Ce = new Te(R), De = (i, e) => R.createStatic({ initialValue: i }, e); function ke(i, e, r) { let t, n, c = r; if (typeof i != "string") { const { key: l, initialValue: v, prefix: h } = i; t = l, n = v, c = h; } else t = D(i), n = e; const { prefix: a } = G(c); R.initValue(t, a, n); const b = L(() => (l) => (R.initValue(t, a, e), R.addListener(t, a, l), () => { R.removeListener(t, a, l); }), []), E = L(() => () => R.get(t, a)?.value, []), A = V(b, E), T = (l) => { const v = typeof l == "function" ? l(R.get(t, a)?.value) : l; v !== A && (R.setValue(t, a, { value: v }), R.callListeners(t, a)); }; return R.useEffect(t, a), [ A, T ]; } class Ae extends u { defaultValue() { return { fnState: { results: void 0, isLoading: !1, error: void 0 } }; } initValue(e, r, t = !1) { super.init(e, r, this.defaultValue(), t); } setValue(e, r, t) { super.setValue(e, r, t); } } class we extends U { constructor(e) { super(e); } get(e, r = "_global") { return typeof e != "string" ? super.get(e)?.fnState : super.get(e, r)?.fnState; } set(e, r, t = "_global") { if (typeof e != "string") { super.set(e, r); return; } super.set(e, r, t); } } const m = new Ae(), Ne = new we(m), Fe = (i, e) => m.createStatic({ fn: i }, e); function Ye(i, e, r) { let t, n, c = r; if (typeof i != "string") { const { key: l, fn: v, prefix: h } = i; t = l, n = v, c = h; } else t = D(i), n = e; const { prefix: a } = G(c); m.initValue(t, a); const b = L( () => (l) => (m.initValue(t, a), m.addListener(t, a, l), () => { m.removeListener(t, a, l); }), [] ), E = L( () => () => m.get(t, a).fnState, [] ), A = V(b, E), T = async (l, ...v) => { const h = m.get(t, a); if (!l && (h.fnState.isLoading || h.fnState.results !== void 0)) return h.fnState; h.fnState = { ...h.fnState, isLoading: !0, error: void 0 }, m.callListeners(t, a); try { const p = await n(...v); h.fnState = { results: p, isLoading: !1, error: void 0 }; } catch (p) { h.fnState = { ...h.fnState, isLoading: !1, error: p }; } m.callListeners(t, a); }; return m.useEffect(t, a), { state: A, trigger: (...l) => { T(!1, ...l); }, forceTrigger: (...l) => { T(!0, ...l); }, clear: () => { const l = m.get(t, a); l && (l.fnState = m.defaultValue().fnState, m.callListeners(t, a)); } }; } class Pe extends u { defaultValue() { return { fnState: { data: void 0, isLoading: !1, error: void 0, subscribed: !1 } }; } initValue(e, r, t = !1) { super.init(e, r, this.defaultValue(), t); } setValue(e, r, t) { super.setValue(e, r, t); } useEffect(e, r) { te(() => () => { W(`[${u.prefix(e, r)}]`, "unmount effect2"), this.get(e, r)?.listeners.length === 0 && this.unsubscribe(e, r); }, []), super.useEffect(e, r); } async unsubscribe(e, r) { const t = this.get(e, r); t && (t.unsubscribe && (t.unsubscribe(), t.unsubscribe = void 0), t.fnState = { ...t.fnState, subscribed: !1 }, this.callListeners(e, r)); } } class ye extends U { constructor(e) { super(e); } get(e, r = "_global") { return typeof e != "string" ? super.get(e)?.fnState : super.get(e, r)?.fnState; } set(e, r, t = "_global") { if (typeof e != "string") { super.set(e, r); return; } super.set(e, r, t); } } const d = new Pe(), $e = new ye(d), Ie = (i, e) => d.createStatic({ subscriber: i }, e); function Ve(i, e, r) { let t, n, c = r; if (typeof i != "string") { const { key: p, subscriber: S, prefix: P } = i; t = p, n = S, c = P; } else t = D(i), n = e; const { prefix: a } = G(c); d.initValue(t, a); const b = L( () => (p) => (d.initValue(t, a), d.addListener(t, a, p), () => { d.removeListener(t, a, p); }), [] ), E = L( () => () => d.get(t, a).fnState, [] ), A = V(b, E), T = (p) => { const S = d.get(t, a); S.fnState = { ...S.fnState, data: p }, d.callListeners(t, a); }, l = (p) => { const S = d.get(t, a); S.fnState = { ...S.fnState, isLoading: !1, data: void 0, error: p }, d.callListeners(t, a); }, v = () => { const p = d.get(t, a); p.fnState = { ...p.fnState, isLoading: !1 }, d.callListeners(t, a); }, h = async (p) => { const S = d.get(t, a); if (p && (await d.unsubscribe(t, a), S.fnState = { ...S.fnState, isLoading: !1, data: void 0, error: void 0, subscribed: !1 }), S.fnState.subscribed) return S.fnState; W("triggered !!"), S.fnState = { ...S.fnState, isLoading: !0, error: void 0 }, d.callListeners(t, a); try { const P = await n(T, l, v), y = d.get(t, a); y.unsubscribe = P, y.fnState.subscribed = !0; } catch (P) { const y = d.get(t, a); y.fnState = { ...y.fnState, isLoading: !1, error: P }; } d.callListeners(t, a); }; return d.useEffect(t, a), { state: A, trigger: () => { h(!1); }, forceTrigger: () => { h(!0); }, unsubscribe: () => { d.unsubscribe(t, a); } }; } export { we as SharedFunctionsApi, Te as SharedStatesApi, je as SharedStatesProvider, ye as SharedSubscriptionsApi, Fe as createSharedFunction, De as createSharedState, Ie as createSharedSubscription, re as isDevMode, Oe as setDevMode, Ne as sharedFunctionsApi, Ce as sharedStatesApi, $e as sharedSubscriptionsApi, Ye as useSharedFunction, ke as useSharedState, Ve as useSharedSubscription };