UNPKG

jotai

Version:

👻 Primitive and flexible state management for React

877 lines (859 loc) • 27.5 kB
'use strict'; var vanilla = require('jotai/vanilla'); var RESET = Symbol(process.env.NODE_ENV !== 'production' ? 'RESET' : ''); function atomWithReset(initialValue) { var anAtom = vanilla.atom(initialValue, function (get, set, update) { var nextValue = typeof update === 'function' ? update(get(anAtom)) : update; set(anAtom, nextValue === RESET ? initialValue : nextValue); }); return anAtom; } function atomWithReducer(initialValue, reducer) { return vanilla.atom(initialValue, function (get, set, action) { set(this, reducer(get(this), action)); }); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: true } : { done: false, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function atomFamily(initializeAtom, areEqual) { var shouldRemove = null; var atoms = new Map(); var listeners = new Set(); var _createAtom = function createAtom(param) { var item; if (areEqual === undefined) { item = atoms.get(param); } else { for (var _iterator = _createForOfIteratorHelperLoose(atoms), _step; !(_step = _iterator()).done;) { var _step$value = _step.value, key = _step$value[0], value = _step$value[1]; if (areEqual(key, param)) { item = value; break; } } } if (item !== undefined) { if (shouldRemove != null && shouldRemove(item[1], param)) { _createAtom.remove(param); } else { return item[0]; } } var newAtom = initializeAtom(param); atoms.set(param, [newAtom, Date.now()]); notifyListeners('CREATE', param, newAtom); return newAtom; }; var notifyListeners = function notifyListeners(type, param, atom) { for (var _iterator2 = _createForOfIteratorHelperLoose(listeners), _step2; !(_step2 = _iterator2()).done;) { var listener = _step2.value; listener({ type: type, param: param, atom: atom }); } }; _createAtom.unstable_listen = function (callback) { listeners.add(callback); return function () { listeners.delete(callback); }; }; _createAtom.getParams = function () { return atoms.keys(); }; _createAtom.remove = function (param) { if (areEqual === undefined) { if (!atoms.has(param)) return; var _ref = atoms.get(param), atom = _ref[0]; atoms.delete(param); notifyListeners('REMOVE', param, atom); } else { for (var _iterator3 = _createForOfIteratorHelperLoose(atoms), _step3; !(_step3 = _iterator3()).done;) { var _step3$value = _step3.value, key = _step3$value[0], _step3$value$ = _step3$value[1], _atom = _step3$value$[0]; if (areEqual(key, param)) { atoms.delete(key); notifyListeners('REMOVE', key, _atom); break; } } } }; _createAtom.setShouldRemove = function (fn) { shouldRemove = fn; if (!shouldRemove) return; for (var _iterator4 = _createForOfIteratorHelperLoose(atoms), _step4; !(_step4 = _iterator4()).done;) { var _step4$value = _step4.value, key = _step4$value[0], _step4$value$ = _step4$value[1], atom = _step4$value$[0], _createdAt = _step4$value$[1]; if (shouldRemove(_createdAt, key)) { atoms.delete(key); notifyListeners('REMOVE', key, atom); } } }; return _createAtom; } var getCached$2 = function getCached(c, m, k) { return (m.has(k) ? m : m.set(k, c())).get(k); }; var cache1$3 = new WeakMap(); var memo3 = function memo3(create, dep1, dep2, dep3) { var cache2 = getCached$2(function () { return new WeakMap(); }, cache1$3, dep1); var cache3 = getCached$2(function () { return new WeakMap(); }, cache2, dep2); return getCached$2(create, cache3, dep3); }; function selectAtom(anAtom, selector, equalityFn) { if (equalityFn === void 0) { equalityFn = Object.is; } return memo3(function () { var EMPTY = Symbol(); var selectValue = function selectValue(_ref) { var value = _ref[0], prevSlice = _ref[1]; if (prevSlice === EMPTY) { return selector(value); } var slice = selector(value, prevSlice); return equalityFn(prevSlice, slice) ? prevSlice : slice; }; var derivedAtom = vanilla.atom(function (get) { var prev = get(derivedAtom); var value = get(anAtom); return selectValue([value, prev]); }); derivedAtom.init = EMPTY; return derivedAtom; }, anAtom, selector, equalityFn); } var frozenAtoms = new WeakSet(); var _deepFreeze = function deepFreeze(value) { if (typeof value !== 'object' || value === null) { return value; } Object.freeze(value); var propNames = Object.getOwnPropertyNames(value); for (var _iterator = _createForOfIteratorHelperLoose(propNames), _step; !(_step = _iterator()).done;) { var name = _step.value; _deepFreeze(value[name]); } return value; }; function freezeAtom(anAtom) { if (frozenAtoms.has(anAtom)) { return anAtom; } frozenAtoms.add(anAtom); var origRead = anAtom.read; anAtom.read = function (get, options) { return _deepFreeze(origRead.call(this, get, options)); }; if ('write' in anAtom) { var origWrite = anAtom.write; anAtom.write = function (get, set) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } return origWrite.call.apply(origWrite, [this, get, function () { for (var _len2 = arguments.length, setArgs = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { setArgs[_key2] = arguments[_key2]; } if (setArgs[0] === anAtom) { setArgs[1] = _deepFreeze(setArgs[1]); } return set.apply(void 0, setArgs); }].concat(args)); }; } return anAtom; } function freezeAtomCreator(createAtom) { if (process.env.NODE_ENV !== 'production') { console.warn('[DEPRECATED] freezeAtomCreator is deprecated, define it on users end'); } return function () { return freezeAtom(createAtom.apply(void 0, arguments)); }; } var getCached$1 = function getCached(c, m, k) { return (m.has(k) ? m : m.set(k, c())).get(k); }; var cache1$2 = new WeakMap(); var memo2$1 = function memo2(create, dep1, dep2) { var cache2 = getCached$1(function () { return new WeakMap(); }, cache1$2, dep1); return getCached$1(create, cache2, dep2); }; var cacheKeyForEmptyKeyExtractor = {}; var isWritable = function isWritable(atom) { return !!atom.write; }; var isFunction = function isFunction(x) { return typeof x === 'function'; }; function splitAtom(arrAtom, keyExtractor) { return memo2$1(function () { var mappingCache = new WeakMap(); var _getMapping = function getMapping(arr, prev) { var mapping = mappingCache.get(arr); if (mapping) { return mapping; } var prevMapping = prev && mappingCache.get(prev); var atomList = []; var keyList = []; arr.forEach(function (item, index) { var key = keyExtractor ? keyExtractor(item) : index; keyList[index] = key; var cachedAtom = prevMapping && prevMapping.atomList[prevMapping.keyList.indexOf(key)]; if (cachedAtom) { atomList[index] = cachedAtom; return; } var read = function read(get) { var prev = get(mappingAtom); var currArr = get(arrAtom); var mapping = _getMapping(currArr, prev == null ? void 0 : prev.arr); var index = mapping.keyList.indexOf(key); if (index < 0 || index >= currArr.length) { var prevItem = arr[_getMapping(arr).keyList.indexOf(key)]; if (prevItem) { return prevItem; } throw new Error('splitAtom: index out of bounds for read'); } return currArr[index]; }; var write = function write(get, set, update) { var prev = get(mappingAtom); var arr = get(arrAtom); var mapping = _getMapping(arr, prev == null ? void 0 : prev.arr); var index = mapping.keyList.indexOf(key); if (index < 0 || index >= arr.length) { throw new Error('splitAtom: index out of bounds for write'); } var nextItem = isFunction(update) ? update(arr[index]) : update; if (!Object.is(arr[index], nextItem)) { set(arrAtom, [].concat(arr.slice(0, index), [nextItem], arr.slice(index + 1))); } }; atomList[index] = isWritable(arrAtom) ? vanilla.atom(read, write) : vanilla.atom(read); }); if (prevMapping && prevMapping.keyList.length === keyList.length && prevMapping.keyList.every(function (x, i) { return x === keyList[i]; })) { mapping = prevMapping; } else { mapping = { arr: arr, atomList: atomList, keyList: keyList }; } mappingCache.set(arr, mapping); return mapping; }; var mappingAtom = vanilla.atom(function (get) { var prev = get(mappingAtom); var arr = get(arrAtom); var mapping = _getMapping(arr, prev == null ? void 0 : prev.arr); return mapping; }); if (process.env.NODE_ENV !== 'production') { mappingAtom.debugPrivate = true; } mappingAtom.init = undefined; var splittedAtom = isWritable(arrAtom) ? vanilla.atom(function (get) { return get(mappingAtom).atomList; }, function (get, set, action) { switch (action.type) { case 'remove': { var index = get(splittedAtom).indexOf(action.atom); if (index >= 0) { var arr = get(arrAtom); set(arrAtom, [].concat(arr.slice(0, index), arr.slice(index + 1))); } break; } case 'insert': { var _index = action.before ? get(splittedAtom).indexOf(action.before) : get(splittedAtom).length; if (_index >= 0) { var _arr = get(arrAtom); set(arrAtom, [].concat(_arr.slice(0, _index), [action.value], _arr.slice(_index))); } break; } case 'move': { var index1 = get(splittedAtom).indexOf(action.atom); var index2 = action.before ? get(splittedAtom).indexOf(action.before) : get(splittedAtom).length; if (index1 >= 0 && index2 >= 0) { var _arr2 = get(arrAtom); if (index1 < index2) { set(arrAtom, [].concat(_arr2.slice(0, index1), _arr2.slice(index1 + 1, index2), [_arr2[index1]], _arr2.slice(index2))); } else { set(arrAtom, [].concat(_arr2.slice(0, index2), [_arr2[index1]], _arr2.slice(index2, index1), _arr2.slice(index1 + 1))); } } break; } } }) : vanilla.atom(function (get) { return get(mappingAtom).atomList; }); return splittedAtom; }, arrAtom, keyExtractor || cacheKeyForEmptyKeyExtractor); } function atomWithDefault(getDefault) { var EMPTY = Symbol(); var overwrittenAtom = vanilla.atom(EMPTY); if (process.env.NODE_ENV !== 'production') { overwrittenAtom.debugPrivate = true; } var anAtom = vanilla.atom(function (get, options) { var overwritten = get(overwrittenAtom); if (overwritten !== EMPTY) { return overwritten; } return getDefault(get, options); }, function (get, set, update) { if (update === RESET) { set(overwrittenAtom, EMPTY); } else if (typeof update === 'function') { var prevValue = get(anAtom); set(overwrittenAtom, update(prevValue)); } else { set(overwrittenAtom, update); } }); return anAtom; } var isPromiseLike = function isPromiseLike(x) { return typeof (x == null ? void 0 : x.then) === 'function'; }; function withStorageValidator(validator) { return function (unknownStorage) { var storage = _extends({}, unknownStorage, { getItem: function getItem(key, initialValue) { var validate = function validate(value) { if (!validator(value)) { return initialValue; } return value; }; var value = unknownStorage.getItem(key, initialValue); if (isPromiseLike(value)) { return value.then(validate); } return validate(value); } }); return storage; }; } function createJSONStorage(getStringStorage, options) { if (getStringStorage === void 0) { getStringStorage = function getStringStorage() { try { return window.localStorage; } catch (e) { if (process.env.NODE_ENV !== 'production') { if (typeof window !== 'undefined') { console.warn(e); } } return undefined; } }; } var lastStr; var lastValue; var storage = { getItem: function getItem(key, initialValue) { var _getStringStorage$get, _getStringStorage; var parse = function parse(str) { str = str || ''; if (lastStr !== str) { try { lastValue = JSON.parse(str, options == null ? void 0 : options.reviver); } catch (_unused) { return initialValue; } lastStr = str; } return lastValue; }; var str = (_getStringStorage$get = (_getStringStorage = getStringStorage()) == null ? void 0 : _getStringStorage.getItem(key)) != null ? _getStringStorage$get : null; if (isPromiseLike(str)) { return str.then(parse); } return parse(str); }, setItem: function setItem(key, newValue) { var _getStringStorage2; return (_getStringStorage2 = getStringStorage()) == null ? void 0 : _getStringStorage2.setItem(key, JSON.stringify(newValue, options == null ? void 0 : options.replacer)); }, removeItem: function removeItem(key) { var _getStringStorage3; return (_getStringStorage3 = getStringStorage()) == null ? void 0 : _getStringStorage3.removeItem(key); } }; var createHandleSubscribe = function createHandleSubscribe(subscriber) { return function (key, callback, initialValue) { return subscriber(key, function (v) { var newValue; try { newValue = JSON.parse(v || ''); } catch (_unused2) { newValue = initialValue; } callback(newValue); }); }; }; var subscriber; try { var _getStringStorage4; subscriber = (_getStringStorage4 = getStringStorage()) == null ? void 0 : _getStringStorage4.subscribe; } catch (_unused3) {} if (!subscriber && typeof window !== 'undefined' && typeof window.addEventListener === 'function' && window.Storage) { subscriber = function subscriber(key, callback) { if (!(getStringStorage() instanceof window.Storage)) { return function () {}; } var storageEventCallback = function storageEventCallback(e) { if (e.storageArea === getStringStorage() && e.key === key) { callback(e.newValue); } }; window.addEventListener('storage', storageEventCallback); return function () { window.removeEventListener('storage', storageEventCallback); }; }; } if (subscriber) { storage.subscribe = createHandleSubscribe(subscriber); } return storage; } var defaultStorage = createJSONStorage(); function atomWithStorage(key, initialValue, storage, options) { if (storage === void 0) { storage = defaultStorage; } var getOnInit = options == null ? void 0 : options.getOnInit; var baseAtom = vanilla.atom(getOnInit ? storage.getItem(key, initialValue) : initialValue); if (process.env.NODE_ENV !== 'production') { baseAtom.debugPrivate = true; } baseAtom.onMount = function (setAtom) { setAtom(storage.getItem(key, initialValue)); var unsub; if (storage.subscribe) { unsub = storage.subscribe(key, setAtom, initialValue); } return unsub; }; var anAtom = vanilla.atom(function (get) { return get(baseAtom); }, function (get, set, update) { var nextValue = typeof update === 'function' ? update(get(baseAtom)) : update; if (nextValue === RESET) { set(baseAtom, initialValue); return storage.removeItem(key); } if (nextValue instanceof Promise) { return nextValue.then(function (resolvedValue) { set(baseAtom, resolvedValue); return storage.setItem(key, resolvedValue); }); } set(baseAtom, nextValue); return storage.setItem(key, nextValue); }); return anAtom; } function atomWithObservable(getObservable, options) { var returnResultData = function returnResultData(result) { if ('e' in result) { throw result.e; } return result.d; }; var observableResultAtom = vanilla.atom(function (get) { var _observable$Symbol$ob, _observable; var observable = getObservable(get); var itself = (_observable$Symbol$ob = (_observable = observable)[Symbol.observable]) == null ? void 0 : _observable$Symbol$ob.call(_observable); if (itself) { observable = itself; } var resolve; var makePending = function makePending() { return new Promise(function (r) { resolve = r; }); }; var initialResult = options && 'initialValue' in options ? { d: typeof options.initialValue === 'function' ? options.initialValue() : options.initialValue } : makePending(); var setResult; var lastResult; var listener = function listener(result) { lastResult = result; resolve == null || resolve(result); setResult == null || setResult(result); }; var subscription; var timer; var isNotMounted = function isNotMounted() { return !setResult; }; var unsubscribe = function unsubscribe() { if (subscription) { subscription.unsubscribe(); subscription = undefined; } }; var start = function start() { if (subscription) { clearTimeout(timer); subscription.unsubscribe(); } subscription = observable.subscribe({ next: function next(d) { return listener({ d: d }); }, error: function error(e) { return listener({ e: e }); }, complete: function complete() {} }); if (isNotMounted() && options != null && options.unstable_timeout) { timer = setTimeout(unsubscribe, options.unstable_timeout); } }; start(); var resultAtom = vanilla.atom(lastResult || initialResult); if (process.env.NODE_ENV !== 'production') { resultAtom.debugPrivate = true; } resultAtom.onMount = function (update) { setResult = update; if (lastResult) { update(lastResult); } if (subscription) { clearTimeout(timer); } else { start(); } return function () { setResult = undefined; if (options != null && options.unstable_timeout) { timer = setTimeout(unsubscribe, options.unstable_timeout); } else { unsubscribe(); } }; }; return [resultAtom, observable, makePending, start, isNotMounted]; }); if (process.env.NODE_ENV !== 'production') { observableResultAtom.debugPrivate = true; } var observableAtom = vanilla.atom(function (get) { var _get = get(observableResultAtom), resultAtom = _get[0]; var result = get(resultAtom); if (result instanceof Promise) { return result.then(returnResultData); } return returnResultData(result); }, function (get, set, data) { var _get2 = get(observableResultAtom), resultAtom = _get2[0], observable = _get2[1], makePending = _get2[2], start = _get2[3], isNotMounted = _get2[4]; if ('next' in observable) { if (isNotMounted()) { set(resultAtom, makePending()); start(); } observable.next(data); } else { throw new Error('observable is not subject'); } }); return observableAtom; } var cache1$1 = new WeakMap(); var memo1 = function memo1(create, dep1) { return (cache1$1.has(dep1) ? cache1$1 : cache1$1.set(dep1, create())).get(dep1); }; var isPromise$1 = function isPromise(x) { return x instanceof Promise; }; var LOADING = { state: 'loading' }; function loadable(anAtom) { return memo1(function () { var loadableCache = new WeakMap(); var refreshAtom = vanilla.atom(0); if (process.env.NODE_ENV !== 'production') { refreshAtom.debugPrivate = true; } var derivedAtom = vanilla.atom(function (get, _ref) { var setSelf = _ref.setSelf; get(refreshAtom); var value; try { value = get(anAtom); } catch (error) { return { state: 'hasError', error: error }; } if (!isPromise$1(value)) { return { state: 'hasData', data: value }; } var promise = value; var cached1 = loadableCache.get(promise); if (cached1) { return cached1; } promise.then(function (data) { loadableCache.set(promise, { state: 'hasData', data: data }); setSelf(); }, function (error) { loadableCache.set(promise, { state: 'hasError', error: error }); setSelf(); }); var cached2 = loadableCache.get(promise); if (cached2) { return cached2; } loadableCache.set(promise, LOADING); return LOADING; }, function (_get, set) { set(refreshAtom, function (c) { return c + 1; }); }); if (process.env.NODE_ENV !== 'production') { derivedAtom.debugPrivate = true; } return vanilla.atom(function (get) { return get(derivedAtom); }); }, anAtom); } var getCached = function getCached(c, m, k) { return (m.has(k) ? m : m.set(k, c())).get(k); }; var cache1 = new WeakMap(); var memo2 = function memo2(create, dep1, dep2) { var cache2 = getCached(function () { return new WeakMap(); }, cache1, dep1); return getCached(create, cache2, dep2); }; var isPromise = function isPromise(x) { return x instanceof Promise; }; var defaultFallback = function defaultFallback() { return undefined; }; function unwrap(anAtom, fallback) { if (fallback === void 0) { fallback = defaultFallback; } return memo2(function () { var promiseErrorCache = new WeakMap(); var promiseResultCache = new WeakMap(); var refreshAtom = vanilla.atom(0); if (process.env.NODE_ENV !== 'production') { refreshAtom.debugPrivate = true; } var promiseAndValueAtom = vanilla.atom(function (get, _ref) { var setSelf = _ref.setSelf; get(refreshAtom); var prev = get(promiseAndValueAtom); var promise = get(anAtom); if (!isPromise(promise)) { return { v: promise }; } if (promise !== (prev == null ? void 0 : prev.p)) { promise.then(function (v) { promiseResultCache.set(promise, v); setSelf(); }, function (e) { promiseErrorCache.set(promise, e); setSelf(); }); } if (promiseErrorCache.has(promise)) { throw promiseErrorCache.get(promise); } if (promiseResultCache.has(promise)) { return { p: promise, v: promiseResultCache.get(promise) }; } if (prev && 'v' in prev) { return { p: promise, f: fallback(prev.v), v: prev.v }; } return { p: promise, f: fallback() }; }, function (_get, set) { set(refreshAtom, function (c) { return c + 1; }); }); promiseAndValueAtom.init = undefined; if (process.env.NODE_ENV !== 'production') { promiseAndValueAtom.debugPrivate = true; } return vanilla.atom(function (get) { var state = get(promiseAndValueAtom); if ('f' in state) { return state.f; } return state.v; }, function (_get, set) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } return set.apply(void 0, [anAtom].concat(args)); }); }, anAtom, fallback); } function atomWithRefresh(read, write) { var refreshAtom = vanilla.atom(0); if (process.env.NODE_ENV !== 'production') { refreshAtom.debugPrivate = true; } return vanilla.atom(function (get, options) { get(refreshAtom); return read(get, options); }, function (get, set) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } if (args.length === 0) { set(refreshAtom, function (c) { return c + 1; }); } else if (write) { return write.apply(void 0, [get, set].concat(args)); } else if (process.env.NODE_ENV !== 'production') { throw new Error('refresh must be called without arguments'); } }); } function atomWithLazy(makeInitial) { var a = vanilla.atom(undefined); delete a.init; Object.defineProperty(a, 'init', { get: function get() { return makeInitial(); } }); return a; } exports.RESET = RESET; exports.atomFamily = atomFamily; exports.atomWithDefault = atomWithDefault; exports.atomWithLazy = atomWithLazy; exports.atomWithObservable = atomWithObservable; exports.atomWithReducer = atomWithReducer; exports.atomWithRefresh = atomWithRefresh; exports.atomWithReset = atomWithReset; exports.atomWithStorage = atomWithStorage; exports.createJSONStorage = createJSONStorage; exports.freezeAtom = freezeAtom; exports.freezeAtomCreator = freezeAtomCreator; exports.loadable = loadable; exports.selectAtom = selectAtom; exports.splitAtom = splitAtom; exports.unstable_withStorageValidator = withStorageValidator; exports.unwrap = unwrap;