UNPKG

jotai

Version:

👻 Next gen state management that will spook you

368 lines (359 loc) • 14.2 kB
System.register(['react', 'jotai'], (function (exports) { 'use strict'; var useContext, useState, useEffect, useDebugValue, useRef, useCallback, SECRET_INTERNAL_getScopeContext, useAtom; return { setters: [function (module) { useContext = module.useContext; useState = module.useState; useEffect = module.useEffect; useDebugValue = module.useDebugValue; useRef = module.useRef; useCallback = module.useCallback; }, function (module) { SECRET_INTERNAL_getScopeContext = module.SECRET_INTERNAL_getScopeContext; useAtom = module.useAtom; }], execute: (function () { exports({ useAtomDevtools: useAtomDevtools, useAtomsDevtools: useAtomsDevtools, useAtomsSnapshot: useAtomsSnapshot, useGotoAtomsSnapshot: useGotoAtomsSnapshot }); const RESTORE_ATOMS = "h"; const DEV_SUBSCRIBE_STATE = "n"; const DEV_GET_MOUNTED_ATOMS = "l"; const DEV_GET_ATOM_STATE = "a"; const DEV_GET_MOUNTED = "m"; const atomToPrintable$1 = (atom) => atom.debugLabel || atom.toString(); const stateToPrintable = ([store, atoms]) => Object.fromEntries( atoms.flatMap((atom) => { var _a, _b; const mounted = (_a = store[DEV_GET_MOUNTED]) == null ? void 0 : _a.call(store, atom); if (!mounted) { return []; } const dependents = mounted.t; const atomState = ((_b = store[DEV_GET_ATOM_STATE]) == null ? void 0 : _b.call(store, atom)) || {}; return [ [ atomToPrintable$1(atom), { ..."e" in atomState && { error: atomState.e }, ..."p" in atomState && { promise: atomState.p }, ..."v" in atomState && { value: atomState.v }, dependents: Array.from(dependents).map(atomToPrintable$1) } ] ]; }) ); const useAtomsDebugValue = exports('useAtomsDebugValue', (options) => { var _a; const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true; const ScopeContext = SECRET_INTERNAL_getScopeContext(options == null ? void 0 : options.scope); const { s: store } = useContext(ScopeContext); const [atoms, setAtoms] = useState([]); useEffect(() => { var _a2; if (!enabled) { return; } const callback = () => { var _a3; setAtoms(Array.from(((_a3 = store[DEV_GET_MOUNTED_ATOMS]) == null ? void 0 : _a3.call(store)) || [])); }; const unsubscribe = (_a2 = store[DEV_SUBSCRIBE_STATE]) == null ? void 0 : _a2.call(store, callback); callback(); return unsubscribe; }, [enabled, store]); useDebugValue([store, atoms], stateToPrintable); }); function useAtomDevtools(anAtom, options, deprecatedScope) { if (typeof options === "string" || typeof deprecatedScope !== "undefined") { console.warn("DEPRECATED [useAtomDevtools] use DevtoolOptions"); options = { name: options, scope: deprecatedScope }; } const { enabled, name, scope } = options || {}; let extension; try { extension = (enabled != null ? enabled : true) && window.__REDUX_DEVTOOLS_EXTENSION__; } catch { } if (!extension) { if (enabled) { console.warn("Please install/enable Redux devtools extension"); } } const [value, setValue] = useAtom(anAtom, scope); const lastValue = useRef(value); const isTimeTraveling = useRef(false); const devtools = useRef(); const atomName = name || anAtom.debugLabel || anAtom.toString(); useEffect(() => { if (!extension) { return; } const setValueIfWritable = (value2) => { if (typeof setValue === "function") { setValue(value2); return; } console.warn( "[Warn] you cannot do write operations (Time-travelling, etc) in read-only atoms\n", anAtom ); }; devtools.current = extension.connect({ name: atomName }); const unsubscribe = devtools.current.subscribe((message) => { var _a, _b, _c, _d, _e, _f; if (message.type === "ACTION" && message.payload) { try { setValueIfWritable(JSON.parse(message.payload)); } catch (e) { console.error( "please dispatch a serializable value that JSON.parse() support\n", e ); } } else if (message.type === "DISPATCH" && message.state) { if (((_a = message.payload) == null ? void 0 : _a.type) === "JUMP_TO_ACTION" || ((_b = message.payload) == null ? void 0 : _b.type) === "JUMP_TO_STATE") { isTimeTraveling.current = true; setValueIfWritable(JSON.parse(message.state)); } } else if (message.type === "DISPATCH" && ((_c = message.payload) == null ? void 0 : _c.type) === "COMMIT") { (_d = devtools.current) == null ? void 0 : _d.init(lastValue.current); } else if (message.type === "DISPATCH" && ((_e = message.payload) == null ? void 0 : _e.type) === "IMPORT_STATE") { const computedStates = ((_f = message.payload.nextLiftedState) == null ? void 0 : _f.computedStates) || []; computedStates.forEach(({ state }, index) => { var _a2; if (index === 0) { (_a2 = devtools.current) == null ? void 0 : _a2.init(state); } else { setValueIfWritable(state); } }); } }); devtools.current.shouldInit = true; return unsubscribe; }, [anAtom, extension, atomName, setValue]); useEffect(() => { if (!devtools.current) { return; } lastValue.current = value; if (devtools.current.shouldInit) { devtools.current.init(value); devtools.current.shouldInit = false; } else if (isTimeTraveling.current) { isTimeTraveling.current = false; } else { devtools.current.send( `${atomName} - ${new Date().toLocaleString()}`, value ); } }, [anAtom, extension, atomName, value]); } const isEqualAtomsValues = (left, right) => left.size === right.size && Array.from(left).every(([left2, v]) => Object.is(right.get(left2), v)); const isEqualAtomsDependents = (left, right) => left.size === right.size && Array.from(left).every(([a, dLeft]) => { const dRight = right.get(a); return dRight && dLeft.size === dRight.size && Array.from(dLeft).every((d) => dRight.has(d)); }); function useAtomsSnapshot(scope) { const ScopeContext = SECRET_INTERNAL_getScopeContext(scope); const scopeContainer = useContext(ScopeContext); const store = scopeContainer.s; const [atomsSnapshot, setAtomsSnapshot] = useState(() => ({ values: /* @__PURE__ */ new Map(), dependents: /* @__PURE__ */ new Map() })); useEffect(() => { if (!store[DEV_SUBSCRIBE_STATE]) return; let prevValues = /* @__PURE__ */ new Map(); let prevDependents = /* @__PURE__ */ new Map(); const invalidatedAtoms = /* @__PURE__ */ new Set(); const callback = () => { const values = /* @__PURE__ */ new Map(); const dependents = /* @__PURE__ */ new Map(); let hasNewInvalidatedAtoms = false; for (const atom of store[DEV_GET_MOUNTED_ATOMS]() || []) { const atomState = store[DEV_GET_ATOM_STATE](atom); if (atomState) { if (!atomState.y) { if ("p" in atomState) { return; } if (!invalidatedAtoms.has(atom)) { invalidatedAtoms.add(atom); hasNewInvalidatedAtoms = true; } } if ("v" in atomState) { values.set(atom, atomState.v); } } const mounted = store[DEV_GET_MOUNTED](atom); if (mounted) { dependents.set(atom, mounted.t); } } if (hasNewInvalidatedAtoms) { return; } if (isEqualAtomsValues(prevValues, values) && isEqualAtomsDependents(prevDependents, dependents)) { return; } prevValues = values; prevDependents = dependents; invalidatedAtoms.clear(); setAtomsSnapshot({ values, dependents }); }; const unsubscribe = store[DEV_SUBSCRIBE_STATE](callback); callback(); return unsubscribe; }, [store]); return atomsSnapshot; } function useGotoAtomsSnapshot(scope) { const ScopeContext = SECRET_INTERNAL_getScopeContext(scope); const { s: store, w: versionedWrite } = useContext(ScopeContext); return useCallback( (snapshot) => { if (!store[DEV_SUBSCRIBE_STATE]) return; const restoreAtoms = (values) => { if (versionedWrite) { versionedWrite((version) => { store[RESTORE_ATOMS](values, version); }); } else { store[RESTORE_ATOMS](values); } }; if (isIterable(snapshot)) { { console.warn( "snapshot as iterable is deprecated. use an object instead." ); } restoreAtoms(snapshot); return; } restoreAtoms(snapshot.values); }, [store, versionedWrite] ); } const isIterable = (item) => { return typeof item[Symbol.iterator] === "function"; }; const atomToPrintable = (atom) => atom.debugLabel ? `${atom}:${atom.debugLabel}` : `${atom}`; const getDevtoolsState = (atomsSnapshot) => { const values = {}; atomsSnapshot.values.forEach((v, atom) => { values[atomToPrintable(atom)] = v; }); const dependents = {}; atomsSnapshot.dependents.forEach((d, atom) => { dependents[atomToPrintable(atom)] = Array.from(d).map(atomToPrintable); }); return { values, dependents }; }; function useAtomsDevtools(name, options) { if (typeof options !== "undefined" && typeof options !== "object") { console.warn("DEPRECATED [useAtomsDevtools] use DevtoolsOptions"); options = { scope: options }; } const { enabled, scope } = options || {}; let extension; try { extension = (enabled != null ? enabled : true) && window.__REDUX_DEVTOOLS_EXTENSION__; } catch { } if (!extension) { if (enabled) { console.warn("Please install/enable Redux devtools extension"); } } const atomsSnapshot = useAtomsSnapshot(scope); const goToSnapshot = useGotoAtomsSnapshot(scope); const isTimeTraveling = useRef(false); const isRecording = useRef(true); const devtools = useRef(); const snapshots = useRef([]); useEffect(() => { if (!extension) { return; } const getSnapshotAt = (index = snapshots.current.length - 1) => { const snapshot = snapshots.current[index >= 0 ? index : 0]; if (!snapshot) { throw new Error("snaphost index out of bounds"); } return snapshot; }; const connection = extension.connect({ name }); const devtoolsUnsubscribe = connection.subscribe((message) => { var _a; switch (message.type) { case "DISPATCH": switch ((_a = message.payload) == null ? void 0 : _a.type) { case "RESET": break; case "COMMIT": connection.init(getDevtoolsState(getSnapshotAt())); snapshots.current = []; break; case "JUMP_TO_ACTION": case "JUMP_TO_STATE": isTimeTraveling.current = true; goToSnapshot(getSnapshotAt(message.payload.actionId - 1)); break; case "PAUSE_RECORDING": isRecording.current = !isRecording.current; break; } } }); devtools.current = connection; devtools.current.shouldInit = true; return () => { extension.disconnect(); devtoolsUnsubscribe == null ? void 0 : devtoolsUnsubscribe(); }; }, [extension, goToSnapshot, name]); useEffect(() => { if (!devtools.current) { return; } if (devtools.current.shouldInit) { devtools.current.init(void 0); devtools.current.shouldInit = false; return; } if (isTimeTraveling.current) { isTimeTraveling.current = false; } else if (isRecording.current) { snapshots.current.push(atomsSnapshot); devtools.current.send( { type: `${snapshots.current.length}`, updatedAt: new Date().toLocaleString() }, getDevtoolsState(atomsSnapshot) ); } }, [atomsSnapshot]); } }) }; }));