UNPKG

@mittwald/react-tunnel

Version:

It's like a Portal – but with React components

68 lines (67 loc) 2.16 kB
"use client" /* */ import { jsx as C } from "react/jsx-runtime"; import { useState as m, createContext as g, useContext as f, useId as E, useRef as b, useEffect as u } from "react"; import { observable as p, makeObservable as v, action as a } from "mobx"; import { observer as w } from "mobx-react-lite"; const d = "default"; class l { children = p.map( {}, { deep: !1 } ); preparedChildren = /* @__PURE__ */ new Map(); constructor() { v(this, { deleteChildren: a.bound, setChildren: a.bound }); } static useNew() { return m(() => new l())[0]; } setChildren(e = d, r, n) { const t = this.children.get(e) ?? p.map({}, { deep: !1 }); t.set(r, n), this.preparedChildren.get(e)?.delete(r), this.children.set(e, t); } prepareChildren(e = d, r, n) { const t = this.preparedChildren.get(e) ?? /* @__PURE__ */ new Map(); t.set(r, n), this.preparedChildren.set(e, t); } deleteChildrenFromMap(e, r, n) { const t = e.get(r); t?.delete(n), t?.size === 0 && e.delete(r); } deleteChildren(e = d, r) { this.deleteChildrenFromMap(this.children, e, r), this.deleteChildrenFromMap(this.preparedChildren, e, r); } getChildren(e = d) { const r = this.children.get(e)?.entries() ?? this.preparedChildren.get(e)?.entries(); if (r) return Array.from(r); } } const h = g(new l()), N = (i) => { const { children: e } = i; return /* @__PURE__ */ C(h.Provider, { value: l.useNew(), children: e }); }, P = (i) => { const { children: e, id: r, staticEntryId: n } = i, t = f(h), o = E(), s = n ?? o, c = b(!1); return c.current || t.prepareChildren(r, s, e), u(() => { c.current = !0, t.setChildren(r, s, e); }, [e, r, s]), u(() => () => { t.deleteChildren(r, s); }, [r, s]), null; }, x = (i) => { const { children: e } = i; return typeof e == "function" ? e() : e; }, R = w((i) => { const { children: e, id: r } = i, n = f(h).getChildren(r), t = n ? n.map(([o, s]) => /* @__PURE__ */ C(x, { children: s }, o)) : null; return typeof e == "function" ? e(t) : t ?? e; }); export { P as TunnelEntry, R as TunnelExit, N as TunnelProvider };