UNPKG

jotai

Version:

👻 Next gen state management that will spook you

584 lines (569 loc) • 20.8 kB
System.register(['jotai/vanilla'], (function (exports) { 'use strict'; var atom; return { setters: [function (module) { atom = module.atom; }], execute: (function () { exports({ atomFamily: atomFamily, atomWithDefault: atomWithDefault, atomWithObservable: atomWithObservable, atomWithReducer: atomWithReducer, atomWithReset: atomWithReset, atomWithStorage: atomWithStorage, createJSONStorage: createJSONStorage, freezeAtom: freezeAtom, freezeAtomCreator: freezeAtomCreator, loadable: loadable, selectAtom: selectAtom, splitAtom: splitAtom, unstable_unwrap: unwrap }); const RESET = exports('RESET', Symbol()); function atomWithReset(initialValue) { const anAtom = atom( initialValue, (get, set, update) => { const nextValue = typeof update === "function" ? update(get(anAtom)) : update; set(anAtom, nextValue === RESET ? initialValue : nextValue); } ); return anAtom; } function atomWithReducer(initialValue, reducer) { const anAtom = atom( initialValue, (get, set, action) => set(anAtom, reducer(get(anAtom), action)) ); return anAtom; } function atomFamily(initializeAtom, areEqual) { let shouldRemove = null; const atoms = /* @__PURE__ */ new Map(); const createAtom = (param) => { let item; if (areEqual === void 0) { item = atoms.get(param); } else { for (const [key, value] of atoms) { if (areEqual(key, param)) { item = value; break; } } } if (item !== void 0) { if (shouldRemove == null ? void 0 : shouldRemove(item[1], param)) { createAtom.remove(param); } else { return item[0]; } } const newAtom = initializeAtom(param); atoms.set(param, [newAtom, Date.now()]); return newAtom; }; createAtom.remove = (param) => { if (areEqual === void 0) { atoms.delete(param); } else { for (const [key] of atoms) { if (areEqual(key, param)) { atoms.delete(key); break; } } } }; createAtom.setShouldRemove = (fn) => { shouldRemove = fn; if (!shouldRemove) return; for (const [key, value] of atoms) { if (shouldRemove(value[1], key)) { atoms.delete(key); } } }; return createAtom; } const getCached$1 = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k); const cache1$4 = /* @__PURE__ */ new WeakMap(); const memo3 = (create, dep1, dep2, dep3) => { const cache2 = getCached$1(() => /* @__PURE__ */ new WeakMap(), cache1$4, dep1); const cache3 = getCached$1(() => /* @__PURE__ */ new WeakMap(), cache2, dep2); return getCached$1(create, cache3, dep3); }; function selectAtom(anAtom, selector, equalityFn = Object.is) { return memo3( () => { const refAtom = atom(() => ({})); const derivedAtom = atom((get) => { const ref = get(refAtom); const selectValue = (value2) => { const slice = selector(value2); if ("prev" in ref && equalityFn(ref.prev, slice)) { return ref.prev; } return ref.prev = slice; }; const value = get(anAtom); if (value instanceof Promise) { return value.then(selectValue); } return selectValue(value); }); return derivedAtom; }, anAtom, selector, equalityFn ); } const cache1$3 = /* @__PURE__ */ new WeakMap(); const memo1$2 = (create, dep1) => (cache1$3.has(dep1) ? cache1$3 : cache1$3.set(dep1, create())).get(dep1); const deepFreeze = (obj) => { if (typeof obj !== "object" || obj === null) return; Object.freeze(obj); const propNames = Object.getOwnPropertyNames(obj); for (const name of propNames) { const value = obj[name]; deepFreeze(value); } return obj; }; function freezeAtom(anAtom) { return memo1$2(() => { const frozenAtom = atom( (get) => deepFreeze(get(anAtom)), (_get, set, arg) => set(anAtom, arg) ); return frozenAtom; }, anAtom); } function freezeAtomCreator(createAtom) { return (...params) => { const anAtom = createAtom(...params); const origRead = anAtom.read; anAtom.read = (get, options) => deepFreeze(origRead(get, options)); return anAtom; }; } const getCached = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k); const cache1$2 = /* @__PURE__ */ new WeakMap(); const memo2 = (create, dep1, dep2) => { const cache2 = getCached(() => /* @__PURE__ */ new WeakMap(), cache1$2, dep1); return getCached(create, cache2, dep2); }; const cacheKeyForEmptyKeyExtractor = {}; const isWritable = (atom2) => !!atom2.write; const isFunction = (x) => typeof x === "function"; function splitAtom(arrAtom, keyExtractor) { return memo2( () => { const mappingCache = /* @__PURE__ */ new WeakMap(); const getMapping = (arr, prev) => { let mapping = mappingCache.get(arr); if (mapping) { return mapping; } const prevMapping = prev && mappingCache.get(prev); const atomList = []; const keyList = []; arr.forEach((item, index) => { const key = keyExtractor ? keyExtractor(item) : index; keyList[index] = key; const cachedAtom = prevMapping && prevMapping.atomList[prevMapping.keyList.indexOf(key)]; if (cachedAtom) { atomList[index] = cachedAtom; return; } const read2 = (get) => { const ref = get(refAtom); const currArr = get(arrAtom); const mapping2 = getMapping(currArr, ref.prev); const index2 = mapping2.keyList.indexOf(key); if (index2 < 0 || index2 >= currArr.length) { const prevItem = arr[getMapping(arr).keyList.indexOf(key)]; if (prevItem) { return prevItem; } throw new Error("splitAtom: index out of bounds for read"); } return currArr[index2]; }; const write2 = (get, set, update) => { const ref = get(refAtom); const arr2 = get(arrAtom); const mapping2 = getMapping(arr2, ref.prev); const index2 = mapping2.keyList.indexOf(key); if (index2 < 0 || index2 >= arr2.length) { throw new Error("splitAtom: index out of bounds for write"); } const nextItem = isFunction(update) ? update(arr2[index2]) : update; set(arrAtom, [ ...arr2.slice(0, index2), nextItem, ...arr2.slice(index2 + 1) ]); }; atomList[index] = isWritable(arrAtom) ? atom(read2, write2) : atom(read2); }); if (prevMapping && prevMapping.keyList.length === keyList.length && prevMapping.keyList.every((x, i) => x === keyList[i])) { mapping = prevMapping; } else { mapping = { atomList, keyList }; } mappingCache.set(arr, mapping); return mapping; }; const refAtom = atom(() => ({})); const read = (get) => { const ref = get(refAtom); const arr = get(arrAtom); const mapping = getMapping(arr, ref.prev); ref.prev = arr; return mapping.atomList; }; const write = (get, set, action) => { switch (action.type) { case "remove": { const index = get(splittedAtom).indexOf(action.atom); if (index >= 0) { const arr = get(arrAtom); set(arrAtom, [ ...arr.slice(0, index), ...arr.slice(index + 1) ]); } break; } case "insert": { const index = action.before ? get(splittedAtom).indexOf(action.before) : get(splittedAtom).length; if (index >= 0) { const arr = get(arrAtom); set(arrAtom, [ ...arr.slice(0, index), action.value, ...arr.slice(index) ]); } break; } case "move": { const index1 = get(splittedAtom).indexOf(action.atom); const index2 = action.before ? get(splittedAtom).indexOf(action.before) : get(splittedAtom).length; if (index1 >= 0 && index2 >= 0) { const arr = get(arrAtom); if (index1 < index2) { set(arrAtom, [ ...arr.slice(0, index1), ...arr.slice(index1 + 1, index2), arr[index1], ...arr.slice(index2) ]); } else { set(arrAtom, [ ...arr.slice(0, index2), arr[index1], ...arr.slice(index2, index1), ...arr.slice(index1 + 1) ]); } } break; } } }; const splittedAtom = isWritable(arrAtom) ? atom(read, write) : atom(read); return splittedAtom; }, arrAtom, keyExtractor || cacheKeyForEmptyKeyExtractor ); } const updateValue = (prevValue, update) => typeof update === "function" ? update(prevValue) : update; function atomWithDefault(getDefault) { const EMPTY = Symbol(); const overwrittenAtom = atom(EMPTY); const anAtom = atom( (get, options) => { const overwritten = get(overwrittenAtom); if (overwritten !== EMPTY) { return overwritten; } return getDefault(get, options); }, (get, set, update) => { if (update === RESET) { return set(overwrittenAtom, EMPTY); } const prevValue = get(anAtom); if (prevValue instanceof Promise) { return prevValue.then( (v) => set(overwrittenAtom, updateValue(v, update)) ); } return set( overwrittenAtom, updateValue(prevValue, update) ); } ); return anAtom; } const NO_STORAGE_VALUE = exports('unstable_NO_STORAGE_VALUE', Symbol()); function createJSONStorage(getStringStorage) { let lastStr; let lastValue; const storage = { getItem: (key) => { var _a, _b; const parse = (str2) => { str2 = str2 || ""; if (lastStr !== str2) { try { lastValue = JSON.parse(str2); } catch { return NO_STORAGE_VALUE; } lastStr = str2; } return lastValue; }; const str = (_b = (_a = getStringStorage()) == null ? void 0 : _a.getItem(key)) != null ? _b : null; if (str instanceof Promise) { return str.then(parse); } return parse(str); }, setItem: (key, newValue) => { var _a; return (_a = getStringStorage()) == null ? void 0 : _a.setItem(key, JSON.stringify(newValue)); }, removeItem: (key) => { var _a; return (_a = getStringStorage()) == null ? void 0 : _a.removeItem(key); } }; if (typeof window !== "undefined" && typeof window.addEventListener === "function") { storage.subscribe = (key, callback) => { const storageEventCallback = (e) => { if (e.key === key && e.newValue) { callback(JSON.parse(e.newValue)); } }; window.addEventListener("storage", storageEventCallback); return () => { window.removeEventListener("storage", storageEventCallback); }; }; } return storage; } const defaultStorage = createJSONStorage( () => typeof window !== "undefined" ? window.localStorage : void 0 ); function atomWithStorage(key, initialValue, storage = defaultStorage) { const baseAtom = atom(initialValue); baseAtom.onMount = (setAtom) => { const value = storage.getItem(key); if (value instanceof Promise) { value.then((v) => setAtom(v === NO_STORAGE_VALUE ? initialValue : v)); } else { setAtom(value === NO_STORAGE_VALUE ? initialValue : value); } let unsub; if (storage.subscribe) { unsub = storage.subscribe(key, setAtom); } return unsub; }; const anAtom = atom( (get) => get(baseAtom), (get, set, update) => { const nextValue = typeof update === "function" ? update(get(baseAtom)) : update; if (nextValue === RESET) { set(baseAtom, initialValue); return storage.removeItem(key); } set(baseAtom, nextValue); return storage.setItem(key, nextValue); } ); return anAtom; } function atomWithObservable(getObservable, options) { const returnResultData = (result) => { if ("e" in result) { throw result.e; } return result.d; }; const observableResultAtom = atom((get) => { var _a; let observable = getObservable(get); const itself = (_a = observable[Symbol.observable]) == null ? void 0 : _a.call(observable); if (itself) { observable = itself; } let resolve; const makePending = () => new Promise((r) => { resolve = r; }); const initialResult = options && "initialValue" in options ? { d: typeof options.initialValue === "function" ? options.initialValue() : options.initialValue } : makePending(); let setResult; let lastResult; const listener = (result) => { lastResult = result; resolve == null ? void 0 : resolve(result); setResult == null ? void 0 : setResult(result); }; let subscription; let timer; const isNotMounted = () => !setResult; const start = () => { if (subscription) { clearTimeout(timer); subscription.unsubscribe(); } subscription = observable.subscribe({ next: (d) => listener({ d }), error: (e) => listener({ e }), complete: () => { } }); if (isNotMounted() && (options == null ? void 0 : options.unstable_timeout)) { timer = setTimeout(() => { if (subscription) { subscription.unsubscribe(); subscription = void 0; } }, options.unstable_timeout); } }; start(); const resultAtom = atom(lastResult || initialResult); resultAtom.onMount = (update) => { setResult = update; if (lastResult) { update(lastResult); } if (subscription) { clearTimeout(timer); } else { start(); } return () => { setResult = void 0; if (subscription) { subscription.unsubscribe(); subscription = void 0; } }; }; return [resultAtom, observable, makePending, start, isNotMounted]; }); const observableAtom = atom( (get) => { const [resultAtom] = get(observableResultAtom); const result = get(resultAtom); if (result instanceof Promise) { return result.then(returnResultData); } return returnResultData(result); }, (get, set, data) => { const [resultAtom, observable, makePending, start, isNotMounted] = get(observableResultAtom); if ("next" in observable) { if (isNotMounted()) { set(resultAtom, makePending()); start(); } observable.next(data); } else { throw new Error("observable is not subject"); } } ); return observableAtom; } const cache1$1 = /* @__PURE__ */ new WeakMap(); const memo1$1 = (create, dep1) => (cache1$1.has(dep1) ? cache1$1 : cache1$1.set(dep1, create())).get(dep1); const LOADING = { state: "loading" }; function loadable(anAtom) { return memo1$1(() => { const loadableCache = /* @__PURE__ */ new WeakMap(); const refreshAtom = atom(0); const derivedAtom = atom( (get, { setSelf }) => { get(refreshAtom); const promise = get(anAtom); if (!(promise instanceof Promise)) { return { state: "hasData", data: promise }; } const cached = loadableCache.get(promise); if (cached) { return cached; } loadableCache.set(promise, LOADING); promise.then( (data) => { loadableCache.set(promise, { state: "hasData", data }); }, (error) => { loadableCache.set(promise, { state: "hasError", error }); } ).finally(setSelf); return LOADING; }, (_get, set) => { set(refreshAtom, (c) => c + 1); } ); return atom((get) => get(derivedAtom)); }, anAtom); } const cache1 = /* @__PURE__ */ new WeakMap(); const memo1 = (create, dep1) => (cache1.has(dep1) ? cache1 : cache1.set(dep1, create())).get(dep1); function unwrap(anAtom, defaultValue) { return memo1(() => { const refAtom = atom( () => ({}) ); const refreshAtom = atom(0); const derivedAtom = atom( (get, { setSelf }) => { get(refreshAtom); const ref = get(refAtom); const promise = get(anAtom); if (ref.p !== promise) { promise.then( (v) => ref.v = v, (e) => ref.e = e ).finally(setSelf); ref.p = promise; } if ("e" in ref) { throw ref.e; } if ("v" in ref) { return ref.v; } return defaultValue; }, (_get, set) => { set(refreshAtom, (c) => c + 1); } ); return atom((get) => get(derivedAtom)); }, anAtom); } }) }; }));