var N = Object.defineProperty; var P = (s, t, e) => t in s ? N(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e; var p = (s, t, e) => P(s, typeof t != "symbol" ? t + "" : t, e); import * as g from "react"; import { jsx as j } from "react/jsx-runtime"; class S { constructor(t = /* @__PURE__ */ new Map()) { this.map = t; } clone() { return new S(new Map(this.map)); } increment(t) { const e = this.map.get(t) ?? 0; this.map.set(t, e + 1); } decrement(t, e) { let n = this.map.get(t); n !== void 0 && (n -= 1, this.map.set(t, n), n === 0 && e()); } } class k { constructor() { p(this, "map", /* @__PURE__ */ new Map()); } getOrCreate(t) { let e = this.map.get(t); return e === void 0 && (e = /* @__PURE__ */ new Set(), this.map.set(t, e)), e; } get(t) { return this.map.get(t); } use(t, e) { const n = this.get(t); n !== void 0 && e(n); } delete(t) { return this.map.delete(t); } } function d(s, t) { return t(s), s; } function x() { } const I = "cell"; function O(s, t) { return s === t; } const C = /* @__PURE__ */ new Map(); let w; class T { /** * Creates a new realm. * @param initialValues - the initial cell values that will populate the realm. * Those values will not trigger a recomputation cycle, and will overwrite the initial values specified for each cell. */ constructor(t = {}) { p(this, "subscriptions", new k()); p(this, "singletonSubscriptions", /* @__PURE__ */ new Map()); p(this, "graph", new k()); p(this, "state", /* @__PURE__ */ new Map()); p(this, "distinctNodes", /* @__PURE__ */ new Map()); p(this, "executionMaps", /* @__PURE__ */ new Map()); p(this, "definitionRegistry", /* @__PURE__ */ new Set()); p(this, "combinedCells", []); for (const e of Object.getOwnPropertySymbols(t)) this.state.set(e, t[e]); } /** * Creates or resolves an existing cell instance in the realm. Useful as a joint point when building your own operators. * @returns a reference to the cell. * @param value - the initial value of the cell * @param distinct - true by default. Pass false to mark the signal as a non-distinct one, meaning that publishing the same value multiple times will re-trigger a recomputation cycle. * @param node - optional, a reference to a cell. If the cell has not been touched in the realm before, the realm will instantiate a reference to it. If it's registered already, the function will return the reference. */ cellInstance(t, e = !0, n = Symbol()) { return this.state.has(n) || this.state.set(n, t), e !== !1 && !this.distinctNodes.has(n) && this.distinctNodes.set(n, e === !0 ? O : e), n; } /** * Creates or resolves an existing signal instance in the realm. Useful as a joint point when building your own operators. * @returns a reference to the signal. * @param distinct - true by default. Pass false to mark the signal as a non-distinct one, meaning that publishing the same value multiple times will re-trigger a recomputation cycle. * @param node - optional, a reference to a signal. If the signal has not been touched in the realm before, the realm will instantiate a reference to it. If it's registered already, the function will return the reference. */ signalInstance(t = !0, e = Symbol()) { return t !== !1 && this.distinctNodes.set(e, t === !0 ? O : t), e; } /** * Subscribes to the values published in the referred node. * @param node - the cell/signal to subscribe to. * @param subscription - the callback to execute when the node receives a new value. * @returns a function that, when called, will cancel the subscription. * * @example * ```ts * const signal$ = Signal() * const r = new Realm() * const unsub = r.sub(signal$, console.log) * r.pub(signal$, 2) * unsub() * r.pub(signal$, 3) * ``` */ sub(t, e) { this.register(t); const n = this.subscriptions.getOrCreate(t); return n.add(e), () => n.delete(e); } /** * Subscribes exclusively to values in the referred node. * Calling this multiple times on a single node will remove the previous subscription created through `singletonSub`. * Subscriptions created through `sub` are not affected. * @returns a function that, when called, will cancel the subscription. * * @example * ```ts * const signal$ = Signal() * const r = new Realm() * // console.log will run only once. * r.singletonSub(signal$, console.log) * r.singletonSub(signal$, console.log) * r.singletonSub(signal$, console.log) * r.pub(signal$, 2) * ``` */ singletonSub(t, e) { return this.register(t), e === void 0 ? this.singletonSubscriptions.delete(t) : this.singletonSubscriptions.set(t, e), () => this.singletonSubscriptions.delete(t); } /** * Clears all exclusive subscriptions. */ resetSingletonSubs() { this.singletonSubscriptions.clear(); } // biome-ignore lint/suspicious/noExplicitAny: I know why we need any here subMultiple(t, e) { const n = this.signalInstance(); return this.connect({ map: (i) => (...r) => { i(r); }, sink: n, sources: t }), this.sub(n, e); } /** * Publishes into multiple nodes simultaneously, triggering a single re-computation cycle. * @param values - a record of node references and their values. * * @example * ```ts * const foo$ = Cell('foo') * const bar$ = Cell('bar') * * const r = new Realm() * r.pubIn({[foo$]: 'foo1', [bar$]: 'bar1'}) * ``` */ pubIn(t) { var a; const e = Reflect.ownKeys(t), n = this.getExecutionMap(e), i = n.refCount.clone(), r = n.participatingNodes.slice(), o = new Map(this.state), l = (h) => { this.graph.use(h, (c) => { for (const { sources: u, sink: y } of c) u.has(h) && i.decrement(y, () => { r.splice(r.indexOf(y), 1), l(y); }); }); }; for (; ; ) { const h = r.shift(); if (h === void 0) break; const c = h; let u = !1; const y = (m) => { const f = this.distinctNodes.get(c); if (f != null && f(o.get(c), m)) { u = !1; return; } u = !0, o.set(c, m), this.state.has(c) && this.state.set(c, m); }; if (Object.prototype.hasOwnProperty.call(t, c) ? y(t[c]) : n.projections.use(c, (m) => { for (const f of m) { const M = [...Array.from(f.sources), ...Array.from(f.pulls)].map((v) => o.get(v)); f.map(y)(...M); } }), u) { const m = o.get(c); this.inContext(() => { this.subscriptions.use(c, (f) => { for (const M of f) M(m); }); }), (a = this.singletonSubscriptions.get(c)) == null || a(m); } else l(c); } } /** * A low-level utility that connects multiple nodes to a sink node with a map function. Used as a foundation for the higher-level operators. * The nodes can be active (sources) or passive (pulls). */ connect({ sources: t, pulls: e = [], map: n, sink: i }) { const r = { map: n, pulls: new Set(e), sink: this.register(i), sources: new Set(t) }; for (const o of [...t, ...e]) this.register(o), this.graph.getOrCreate(o).add(r); this.executionMaps.clear(); } pub(t, e) { this.pubIn({ [t]: e }); } pipe(t, ...e) { return this.combineOperators(...e)(t); } transformer(...t) { return (e) => d(this.signalInstance(), (n) => (this.link(this.pipe(n, ...t), e), n)); } /** * Links the output of a node to the input of another node. */ link(t, e) { this.connect({ map: (n) => (i) => { n(i); }, sink: e, sources: [t] }); } // prettier-ignore combine(...t) { return d(this.signalInstance(), (e) => { this.connect({ map: (n) => (...i) => { n(i); }, sink: e, sources: t }); }); } // prettier-ignore combineCells(...t) { const e = this.combinedCells.find((i) => t.length === i.sources.length && t.every((r, o) => r === i.sources[o])); if (e) return e.cell; const n = this.cellInstance( t.map((i) => this.getValue(i)), !0 ); return this.connect({ map: (i) => (...r) => { i(r); }, sink: n, sources: t }), this.combinedCells.push({ sources: t, cell: n }), n; } /** * Gets the current value of a node. The node must be stateful. * @remark if possible, use {@link withLatestFrom} or {@link combine}, as getValue will not create a dependency to the passed node, * which means that if you call it within a computational cycle, you may not get the correct value. * @param node - the node instance. * @example * ```ts * const foo$ = Cell('foo') * * const r = new Realm() * r.getValue(foo$) // 'foo' * r.pub(foo$, 'bar') * //... * r.getValue(foo$) // 'bar' * ``` */ getValue(t) { return this.register(t), this.state.get(t); } getValues(t) { return t.map((e) => this.getValue(e)); } /** * Explicitly includes the specified cell/signal reference in the realm. * Most of the time you don't need to do that, since any interaction with the node through a realm will register it. * The only exception of that rule should be when the interaction is conditional, and the node definition includes an init function that needs to be eagerly evaluated. */ register(t) { const e = C.get(t); return e === void 0 || this.definitionRegistry.has(t) ? t : (this.definitionRegistry.add(t), d( e.type === I ? this.cellInstance(e.initial, e.distinct, t) : this.signalInstance(e.distinct, t), (n) => { this.inContext(() => { e.init(this, n); }); } )); } inContext(t) { const e = w; w = this; const n = t(); return w = e, n; } /** * Convenient for mutation of cells that contian non-primitive values (e.g. arrays, or objects). * Specifies that the cell value should be changed when source emits, with the result of the map callback parameter. * the map parameter gets called with the current value of the cell and the value published through the source. * @typeParam T - the type of the cell value. * @typeParam K - the type of the value published through the source. * @example * ```ts * const items$ = Cell(false, (r) => { * r.changeWith(items$, addItem$, (items, item) => [...items, item]) * }) * const r = new Realm() * r.pub(addItem$, 'foo') * r.pub(addItem$, 'bar') * r.getValue(items$) // ['foo', 'bar'] * ``` */ changeWith(t, e, n) { this.connect({ sources: [e], pulls: [t], sink: t, map: (i) => (r, o) => { i(n(o, r)); } }); } calculateExecutionMap(t) { const e = [], n = /* @__PURE__ */ new Set(), i = new k(), r = new S(), o = new k(), l = (a, h = 0) => { r.increment(a), !n.has(a) && (this.register(a), i.use(a, (c) => { h = Math.max(...Array.from(c).map((u) => e.indexOf(u))) + 1; }), this.graph.use(a, (c) => { for (const u of c) u.sources.has(a) ? (o.getOrCreate(u.sink).add(u), l(u.sink, h)) : i.getOrCreate(u.sink).add(a); }), n.add(a), e.splice(h, 0, a)); }; return t.forEach(l), { participatingNodes: e, pendingPulls: i, projections: o, refCount: r }; } getExecutionMap(t) { let e = t; if (t.length === 1) { e = t[0]; const i = this.executionMaps.get(e); if (i !== void 0) return i; } else for (const [i, r] of this.executionMaps.entries()) if (Array.isArray(i) && i.length === t.length && i.every((o) => t.includes(o))) return r; const n = this.calculateExecutionMap(t); return this.executionMaps.set(e, n), n; } combineOperators(...t) { return (e) => { for (const n of t) e = n(e, this); return e; }; } } function $(s, t = x, e = !0) { return d(Symbol(), (n) => { C.set(n, { type: I, distinct: e, initial: s, init: t }); }); } function D(s, t, e = !0) { return d(Symbol(), (n) => { C.set(n, { type: I, distinct: e, initial: s, init: (i, r) => { i.link(t(i, r), r); } }); }); } function K(s = x, t = !1) { return d(Symbol(), (e) => { C.set(e, { type: "signal", distinct: t, init: s }); }); } function q(s = x) { return d(Symbol(), (t) => { C.set(t, { type: "signal", distinct: !1, init: s }); }); } function b() { if (!w) throw new Error("This function must be called within a realm instance"); return w; } const F = (s, t) => { b().link(s, t); }, Y = (...s) => { b().pub(...s); }, z = (...s) => b().sub(...s), B = (...s) => { b().pubIn(...s); }, G = (...s) => b().pipe(...s), H = (...s) => { b().changeWith(...s); }, J = (...s) => b().combine(...s), Q = (s) => b().getValue(s), V = g.createContext(null); function U({ children: s, initWith: t, updateWith: e = {} }) { const n = g.useMemo(() => new T(t), []); return g.useEffect(() => { n.pubIn(e); }, [e, n]), /* @__PURE__ */ j(V.Provider, { value: n, children: s }); } function R() { const s = g.useContext(V); if (s === null) throw new Error("useRealm must be used within a RealmContextProvider"); return s; } function E(s) { const t = R(); t.register(s); const e = g.useCallback((n) => t.sub(s, n), [t, s]); return g.useSyncExternalStore( e, () => t.getValue(s), () => t.getValue(s) ); } function X(...s) { const t = R(), e = g.useMemo(() => t.combineCells.apply(t, s), [t, ...s]); return E(e); } function A(s) { const t = R(); return t.register(s), g.useCallback( (e) => { t.pub(s, e); }, [t, s] ); } function Z(s) { return [E(s), A(s)]; } function _(s) { return (t, e) => { const n = e.signalInstance(); return e.connect({ map: (i) => (r) => { i(s(r)); }, sink: n, sources: [t] }), n; }; } function tt(...s) { return (t, e) => { const n = e.signalInstance(); return e.connect({ map: (i) => (...r) => { i(r); }, pulls: s, sink: n, sources: [t] }), n; }; } function et(s) { return (t, e) => { const n = e.signalInstance(); return e.connect({ map: (i) => () => { i(s); }, sink: n, sources: [t] }), n; }; } function nt(s) { return (t, e) => { const n = e.signalInstance(); return e.connect({ map: (i) => (r) => { s(r) && i(r); }, sink: n, sources: [t] }), n; }; } function st() { return (s, t) => { const e = t.signalInstance(); let n = !1; return t.connect({ map: (i) => (r) => { n || (n = !0, i(r)); }, sink: e, sources: [s] }), e; }; } function it(s, t) { return (e, n) => { const i = n.signalInstance(); return n.connect({ map: (r) => (o) => { r(t = s(t, o)); }, sink: i, sources: [e] }), i; }; } function rt(s) { return (t, e) => { const n = e.signalInstance(); let i, r = null; return e.sub(t, (o) => { i = o, r === null && (r = setTimeout(() => { r = null, e.pub(n, i); }, s)); }), n; }; } function ot(s) { return (t, e) => { const n = e.signalInstance(); let i, r = null; return e.sub(t, (o) => { i = o, r !== null && clearTimeout(r), r = setTimeout(() => { e.pub(n, i); }, s); }), n; }; } function ct() { return (s, t) => { const e = t.signalInstance(); return t.sub(s, (n) => { queueMicrotask(() => { t.pub(e, n); }); }), e; }; } function ut(s) { return (t, e) => { const n = e.signalInstance(), i = Symbol(); let r = i; return e.connect({ map: (o) => (l) => { r !== i && (o([r, l]), r = i); }, sink: n, sources: [s] }), e.sub(t, (o) => { r = o; }), n; }; } function at(s, t, e) { return (n, i) => { const r = i.signalInstance(); return i.sub(n, (o) => { o !== null && typeof o == "object" && "then" in o ? (i.pub(r, s()), o.then((l) => { i.pub(r, t(l)); }).catch((l) => { i.pub(r, e(l)); })) : i.pub(r, t(o)); }), r; }; } export { q as Action, $ as Cell, D as DerivedCell, T as Realm, V as RealmContext, U as RealmProvider, K as Signal, H as changeWith, J as combine, ot as debounceTime, O as defaultComparator, ct as delayWithMicrotask, nt as filter, Q as getValue, at as handlePromise, F as link, _ as map, et as mapTo, ut as onNext, st as once, G as pipe, Y as pub, B as pubIn, it as scan, z as sub, rt as throttleTime, Z as useCell, E as useCellValue, X as useCellValues, A as usePublisher, R as useRealm, tt as withLatestFrom };