jotai
Version:
👻 Next gen state management that will spook you
368 lines (359 loc) • 14.2 kB
JavaScript
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]);
}
})
};
}));