UNPKG

atomic-state

Version:

Atomic State is a state management library for React

1,140 lines 59.3 kB
'use client'; "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.session = exports.storage = exports.stateProvider = exports.useAtomActions = exports.useAtomDispatch = exports.useAtomValue = exports.atomicHook = exports.store = exports.selector = exports.createAtom = exports.AtomicState = void 0; exports.createObserver = createObserver; exports.createPersistence = createPersistence; exports.takeSnapshot = takeSnapshot; exports.setAtom = setAtom; exports.getActions = getActions; exports.atom = atom; exports.filter = filter; exports.useFilter = useFilter; exports.useAtom = useAtom; exports.createAtomicHook = createAtomicHook; exports.createStore = createStore; exports.create = create; exports.useValue = useValue; exports.useDispatch = useDispatch; exports.useActions = useActions; exports.useValueAndActions = useValueAndActions; exports.atomProvider = atomProvider; exports.useStorage = useStorage; exports.useStorageItem = useStorageItem; const jsx_runtime_1 = require("react/jsx-runtime"); /** @license Atomic State * Copyright (c) Dany Beltran * * This source code is licensed under the MIT license found in the * LICENSE file in the roo&t directory of this source tree. */ const react_1 = require("react"); const store_1 = require("./store"); const utils_1 = require("./utils"); function newObservable() { let subscribers = {}; const observer = { addListener(event, listener) { if (!subscribers[event]) { subscribers[event] = []; } subscribers[event].push(listener); }, removeListener(event, listener) { if (!subscribers[event]) { subscribers[event] = []; } subscribers[event] = subscribers[event].filter((l) => l !== listener); }, emit(event, payload) { if (subscribers[event]) { subscribers[event].forEach((listener) => { listener(payload); }); } } }; return observer; } function createObserver() { const observer = newObservable(); function notify(storeName, hookCall, payload) { observer.emit(storeName, { storeName, hookCall, payload }); } return { observer: observer, notify }; } const atomObservables = {}; const defaultPersistenceProvider = typeof localStorage !== 'undefined' ? localStorage : { getItem() { }, setItem() { }, removeItem() { } }; function createPersistence(persistenceProvider = defaultPersistenceProvider) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; const setItem = (_c = (_b = (_a = persistenceProvider.setItem) !== null && _a !== void 0 ? _a : persistenceProvider.set) !== null && _b !== void 0 ? _b : persistenceProvider.setItemAsync) !== null && _c !== void 0 ? _c : (() => { }); const getItem = (_f = (_e = (_d = persistenceProvider.getItem) !== null && _d !== void 0 ? _d : persistenceProvider.get) !== null && _e !== void 0 ? _e : persistenceProvider.getItemAsync) !== null && _f !== void 0 ? _f : (() => { }); const removeItem = (_m = (_l = (_k = (_j = (_h = (_g = persistenceProvider.removeItem) !== null && _g !== void 0 ? _g : persistenceProvider.remove) !== null && _h !== void 0 ? _h : persistenceProvider.removeItemAsync) !== null && _j !== void 0 ? _j : persistenceProvider.delete) !== null && _k !== void 0 ? _k : persistenceProvider.deleteItem) !== null && _l !== void 0 ? _l : persistenceProvider.deleteItemAsync) !== null && _m !== void 0 ? _m : (() => { }); persistenceProvider.setItem = setItem; persistenceProvider.getItem = getItem; persistenceProvider.removeItem = removeItem; return persistenceProvider; } const atomicStateContext = (0, react_1.createContext)({ storeName: false, persistenceProvider: defaultPersistenceProvider }); function AtomInitialize({ atm }) { useAtom(atm); return null; } const AtomicState = ({ children, default: def, value, storeName = false, clientOnly, persistenceProvider = defaultPersistenceProvider }) => { var _a, _b, _c, _d; if (def) { for (let atomKey in def) { /** * * When promises are passed in nextjs, they are sent as chunks, so here * we try to parse their values */ let parsedChunk; const dataChunk = (_a = def[atomKey]) !== null && _a !== void 0 ? _a : def[atomKey]; if (dataChunk instanceof Promise) { try { const parsedChunkValue = JSON.parse(dataChunk.value); parsedChunk = (_b = parsedChunkValue === null || parsedChunkValue === void 0 ? void 0 : parsedChunkValue.data) !== null && _b !== void 0 ? _b : parsedChunkValue; } catch (_e) { parsedChunk = dataChunk; } } else { parsedChunk = dataChunk; } const defaultsKey = storeName === false ? atomKey : `${storeName}-${atomKey}`; store_1.defaultAtomsValues.set(defaultsKey, parsedChunk); store_1.defaultAtomsInAtomic.set(defaultsKey, true); } } if (value) { for (let atomKey in value) { /** * * When promises are passed in nextjs, they are sent as chunks, so here * we try to parse their values */ let parsedChunk; const dataChunk = (_c = value[atomKey]) !== null && _c !== void 0 ? _c : value[atomKey]; if (dataChunk instanceof Promise) { try { const parsedChunkValue = JSON.parse(dataChunk.value); parsedChunk = (_d = parsedChunkValue === null || parsedChunkValue === void 0 ? void 0 : parsedChunkValue.data) !== null && _d !== void 0 ? _d : parsedChunkValue; } catch (_f) { parsedChunk = dataChunk; } } else { parsedChunk = dataChunk; } const defaultsKey = storeName === false ? atomKey : `${storeName}-${atomKey}`; store_1.defaultAtomsValues.set(defaultsKey, parsedChunk); store_1.defaultAtomsInAtomic.set(defaultsKey, true); } } const createdAtoms = Array.from(store_1.atomsInitializeObjects.values()); const thisId = (0, react_1.useMemo)(() => Math.random(), []).toString(); const initialized = (0, react_1.useMemo)(() => createdAtoms.map((atm) => { return ((0, jsx_runtime_1.jsx)(react_1.StrictMode, { children: (0, jsx_runtime_1.jsx)(AtomInitialize, { atm: atm }) }, (atm === null || atm === void 0 ? void 0 : atm.name) + storeName + thisId)); }), [createdAtoms]); return ((0, jsx_runtime_1.jsxs)(atomicStateContext.Provider, { value: { storeName: storeName === '' ? false : storeName, persistenceProvider }, children: [(0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: initialized }), children] })); }; exports.AtomicState = AtomicState; const resolvedAtoms = {}; const persistenceLoaded = {}; /** * Take a snapshot of all atoms' and filters' values. * You can pass a string with the `prefix` you used in the `AtomicState` root component * if you want only atoms and filters using that prefix. */ function takeSnapshot(storeName = 'default') { let stores = {}; for (let atomKey of store_1.defaultAtomsValues.keys()) { const [prefixName, atomName] = atomKey.split('-'); const storeExists = atomKey.includes('-'); // This means an atom does not belong to a specific store // so it will be added to the `default` store if (!atomName) { if (!stores.default) { stores.default = {}; } } else { if (!(0, utils_1._isDefined)(stores[prefixName])) { stores[prefixName] = {}; } } if (storeExists) { stores[prefixName][atomName] = store_1.defaultAtomsValues.get(atomKey); } else { stores['default'][prefixName] = store_1.defaultAtomsValues.get(atomKey); } } for (let filterKey of store_1.defaultFiltersValues.keys()) { const [prefixName, filterName] = filterKey.split('-'); const storeExists = filterKey.includes('-'); if (!storeExists) { if (!stores.default) { stores.default = {}; } } else { if (!(0, utils_1._isDefined)(stores[prefixName])) { stores[prefixName] = {}; } } if (storeExists) { stores[prefixName][filterName] = store_1.defaultFiltersValues.get(filterKey); } else { stores['default'][prefixName] = store_1.defaultFiltersValues.get(filterKey); } } return !(0, utils_1._isDefined)(storeName) ? stores : stores[storeName] || {}; } function setAtom($atom, v, prefix) { var _a; const init = $atom['init-object']; const { key, effects = [] } = init; const $atomKey = (prefix ? `${prefix}-${key}` : key); const observable = atomObservables[$atomKey]; const newValue = typeof v === 'function' ? v(store_1.defaultAtomsValues.get($atomKey)) : v; let willCancel = false; function cancel() { willCancel = true; } for (let cleanupFunction of (_a = store_1.atomsEffectsCleanupFunctons.get($atomKey)) !== null && _a !== void 0 ? _a : []) { cleanupFunction(); } for (let effect of effects) { const currentState = store_1.defaultAtomsValues.get($atomKey); const effectResult = effect({ previous: currentState, state: newValue, cancel, dispatch: undefined }); if (typeof effectResult === 'boolean') { if (effectResult === false) { willCancel = true; } } } if (!willCancel) { if (store_1.defaultAtomsValues.get($atomKey) !== newValue) { store_1.defaultAtomsValues.set($atomKey, newValue); if (observable) { observable.notify($atomKey, Math.random().toFixed(2), store_1.defaultAtomsValues.get($atomKey)); } } } } function getActions($atom) { const init = $atom['init-object']; let _actions = {}; for (let action in init.actions) { _actions[action] = (args) => init.actions[action]({ state: store_1.defaultAtomsValues.get(init.key), args, dispatch: (v) => setAtom($atom, v), get: store_1.getAtom, set: setAtom }); } return _actions; } function useAtomCreate(init) { const { storeName, persistenceProvider } = (0, react_1.useContext)(atomicStateContext); const { effects = [], persist, sync = true, onSync = () => { }, persistenceProvider: $localStorage = persistenceProvider } = init; const persistence = persist; const $persistence = createPersistence($localStorage); if (!init.name) { init.name = init.key; } const $atomKey = storeName === false ? init.name : storeName + '-' + init.name; const [isLSReady, setIsLSReady] = (0, react_1.useState)(false); const hookCall = (0, react_1.useMemo)(() => `${Math.random()}`.split('.')[1], []); if (!store_1.atomsEffectsCleanupFunctons.has($atomKey)) { store_1.atomsEffectsCleanupFunctons.set($atomKey, []); } const isDefined = (0, utils_1._isDefined)(init.default); const initDef = (0, utils_1._isDefined)(store_1.defaultAtomsValues.get($atomKey)) ? store_1.defaultAtomsValues.get($atomKey) : init.default; const initialValue = (function getInitialValue() { const isFunction = !(0, utils_1._isDefined)(store_1.defaultAtomsValues.get($atomKey)) && (0, utils_1._isFunction)(init.default); const initialIfFnOrPromise = isFunction ? init.default() : (0, utils_1._isPromise)(init.default) ? init.default : undefined; const isPromiseValue = (0, utils_1._isPromise)(initialIfFnOrPromise); let initVal = isDefined ? !(0, utils_1._isDefined)(store_1.defaultAtomsValues.get($atomKey)) ? !isPromiseValue ? (0, utils_1._isDefined)(initialIfFnOrPromise) ? initialIfFnOrPromise : initDef : init.default : initDef : initDef; try { if (persistence) { if (typeof localStorage !== 'undefined') { if (!(0, utils_1._isDefined)(store_1.defaultAtomsValues.get($atomKey)) || store_1.defaultAtomsInAtomic.get($atomKey)) { store_1.defaultAtomsInAtomic.set($atomKey, false); store_1.defaultAtomsValues.set($atomKey, isPromiseValue ? undefined : initVal); } } } else { if (!store_1.defaultAtomsValues.has($atomKey)) { store_1.defaultAtomsValues.set($atomKey, initVal); } } return initVal; } catch (err) { return initVal; } })(); const [vIfPersistence, setVIfPersistence] = (0, react_1.useState)(() => { if (persist) { if (typeof window !== 'undefined') { try { return (() => __awaiter(this, void 0, void 0, function* () { try { const storageItem = typeof $persistence === 'undefined' ? init.default : yield $persistence.getItem($atomKey); return typeof $persistence === 'undefined' ? init.default : JSON.parse(storageItem) || initDef; } catch (_a) { return undefined; } }))(); } catch (err) { return initialValue; } } } else return undefined; }); const [state, setState] = (0, react_1.useState)(((0, utils_1._isPromise)(initialValue) || (0, utils_1._isFunction)(initialValue)) && !(0, utils_1._isDefined)(store_1.defaultAtomsValues.get($atomKey)) ? undefined : (() => { store_1.defaultAtomsValues.set($atomKey, initialValue); return initialValue; })()); if (!store_1.pendingAtoms.get($atomKey)) { store_1.pendingAtoms.set($atomKey, 0); } if (!atomObservables[$atomKey]) { atomObservables[$atomKey] = createObserver(); } const { observer, notify } = atomObservables[$atomKey]; const [runEffects, setRunEffects] = (0, react_1.useState)(false); const hydrated = (0, react_1.useRef)(false); const updateState = (0, react_1.useCallback)((v) => { let willCancel = false; let newValue; let hasChanded; function cancelUpdate() { willCancel = true; } newValue = (0, utils_1._isFunction)(v) ? v(store_1.defaultAtomsValues.get($atomKey)) : v; hasChanded = (() => { try { return !(0, utils_1.jsonEquality)(newValue, store_1.defaultAtomsValues.get($atomKey)); } catch (err) { return false; } })(); const notifyIfValueIsDefault = (() => { try { if ((0, utils_1._isFunction)(store_1.defaultAtomsValues.get($atomKey))) { return true; } if ((0, utils_1.jsonEquality)(newValue, initDef) && !resolvedAtoms[$atomKey]) { resolvedAtoms[$atomKey] = true; return true; } else { return false; } } catch (err) { return true; } })(); const shouldNotifyOtherSubscribers = (0, utils_1._isFunction)(store_1.defaultAtomsValues.get($atomKey)) || hasChanded || notifyIfValueIsDefault; // We first run every cleanup functions returned in atom effects try { for (let cleanupFunction of store_1.atomsEffectsCleanupFunctons.get($atomKey)) { cleanupFunction(); } } catch (err) { } finally { // We reset all atom cleanup functions store_1.atomsEffectsCleanupFunctons.set($atomKey, []); try { for (let effect of effects) { const cancelStateUpdate = effect({ previous: state, state: newValue, dispatch: updateState, cancel: cancelUpdate }); if ((0, utils_1._isPromise)(cancelStateUpdate)) { ; cancelStateUpdate.then((r) => { if ((0, utils_1._isDefined)(r) && !r) { willCancel = true; } else { if ((0, utils_1._isFunction)(r)) { store_1.atomsEffectsCleanupFunctons.get($atomKey).push(r); } } }); } else if ((0, utils_1._isDefined)(cancelStateUpdate) && !cancelStateUpdate) { willCancel = true; } else { if ((0, utils_1._isFunction)(cancelStateUpdate)) { store_1.atomsEffectsCleanupFunctons .get($atomKey) .push(cancelStateUpdate); } } } } catch (err) { setRunEffects(true); } finally { if (!willCancel) { if ((0, utils_1._isDefined)(newValue)) { if (store_1.defaultAtomsValues.get($atomKey) !== newValue) { store_1.defaultAtomsValues.set($atomKey, newValue); if (persistence) { $persistence.setItem($atomKey, JSON.stringify(newValue)); } } } try { if (shouldNotifyOtherSubscribers) { if ((0, utils_1._isDefined)(newValue)) { notify($atomKey, hookCall, newValue); } } } finally { // Finally update state if ((0, utils_1._isDefined)(newValue)) { setState(newValue); } } } } } }, [ hookCall, notify, runEffects, $atomKey, persistence, hydrated, state, init.name ]); (0, react_1.useEffect)(() => { function storageListener() { return __awaiter(this, void 0, void 0, function* () { if (typeof localStorage !== 'undefined') { if ((0, utils_1._isDefined)(localStorage[$atomKey])) { try { const newState = JSON.parse(localStorage[$atomKey]); /** * We compare our atom saved in the storage with the current * atom value and only update our state if they are different * **/ if (!(0, utils_1.jsonEquality)(newState, store_1.defaultAtomsValues.get($atomKey))) { updateState(newState); yield onSync(newState); } } catch (err) { } } } }); } if (persistence) { if (typeof window !== 'undefined') { if (typeof localStorage !== 'undefined') { if ($persistence === localStorage) { const canListen = (0, utils_1._isDefined)(window.addEventListener); if (canListen) { if (sync) { window.addEventListener('storage', storageListener); return () => { window.removeEventListener('storage', storageListener); }; } } } } } } return () => { }; }, [init.name, persistence, $persistence]); (0, react_1.useEffect)(() => { function loadPersistence() { return __awaiter(this, void 0, void 0, function* () { persistenceLoaded[$atomKey] = true; if ((0, utils_1._isDefined)(vIfPersistence)) { if (!hydrated.current) { const tm1 = setTimeout(() => __awaiter(this, void 0, void 0, function* () { if (persistence) { const storageItem = yield vIfPersistence; if (!(0, utils_1.jsonEquality)(storageItem, store_1.defaultAtomsValues.get($atomKey))) { if (!(0, utils_1._isDefined)(resolvedAtoms[$atomKey])) { updateState(storageItem); } } setIsLSReady(true); } }), 0); const tm2 = setTimeout(() => { setVIfPersistence(undefined); hydrated.current = true; }, 0); return () => { clearTimeout(tm1); clearTimeout(tm2); }; } } return () => { }; }); } if (!persistenceLoaded[$atomKey]) { loadPersistence(); } }, [vIfPersistence, updateState, hydrated, $atomKey]); (0, react_1.useEffect)(() => { function getPromiseInitialValue() { return __awaiter(this, void 0, void 0, function* () { var _a; // Only resolve promise if default or resolved value are not present if (!(0, utils_1._isDefined)(store_1.defaultAtomsValues.get($atomKey))) { if ((0, utils_1._isFunction)(init.default)) { if (store_1.pendingAtoms.get($atomKey) === 0) { store_1.pendingAtoms.set($atomKey, store_1.pendingAtoms.get($atomKey) + 1); let v = (0, utils_1._isDefined)(init.default) ? (() => __awaiter(this, void 0, void 0, function* () { return (0, utils_1._isFunction)(init.default) ? init.default() : init.default; }))() : undefined; if ((0, utils_1._isDefined)(v)) { ; v.then((val) => { if (store_1.defaultAtomsValues.get($atomKey) !== val) { store_1.defaultAtomsValues.set($atomKey, val); notify($atomKey, hookCall, store_1.defaultAtomsValues.get($atomKey)); updateState(val); } }); } } else { store_1.pendingAtoms.set($atomKey, store_1.pendingAtoms.get($atomKey) + 1); if (state || store_1.defaultAtomsValues.get($atomKey)) { (_a = atomObservables[$atomKey]) === null || _a === void 0 ? void 0 : _a.notify($atomKey, hookCall, (0, utils_1._isDefined)(state) ? state : store_1.defaultAtomsValues.get($atomKey)); } } } } }); } getPromiseInitialValue(); }, [state, initDef, updateState, init.name, hookCall]); (0, react_1.useEffect)(() => { return () => { store_1.pendingAtoms.set($atomKey, 0); }; }, [init.name]); (0, react_1.useEffect)(() => { const handler = (e) => __awaiter(this, void 0, void 0, function* () { if (e.hookCall !== hookCall) { if ((0, utils_1._isDefined)(e.payload)) { setState(e.payload); } } }); observer.addListener($atomKey, handler); return () => { observer.removeListener($atomKey, handler); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [runEffects]); (0, react_1.useEffect)(() => { function updateStorage() { return __awaiter(this, void 0, void 0, function* () { if (typeof localStorage !== 'undefined') { const storageItem = yield $persistence.getItem($atomKey); if ((0, utils_1._isDefined)(storageItem) || storageItem === null) { // Only remove from localStorage if persistence is false if (!persistence) { $persistence.removeItem($atomKey); } else { if ((0, utils_1._isDefined)(state)) { $persistence.setItem($atomKey, JSON.stringify(state)); } } } } }); } updateStorage(); }, [init.name, persistence, state]); // eslint-disable-next-line react-hooks/exhaustive-deps const actions = (0, react_1.useMemo)(() => init.actions || {}, [init.actions]); const __actions = (0, react_1.useMemo)(() => Object.fromEntries(Object.keys(actions).map(key => [ key, (args) => actions[key]({ args, state, dispatch: updateState, get: store_1.getValue }) ])), // eslint-disable-next-line react-hooks/exhaustive-deps [state]); return [ state, updateState, __actions ]; } /** * Creates an atom containing state */ function atom($init) { if ('get' in $init) { return filter($init); } else { const init = $init; if (!init.name) { init.name = init.key; } store_1.usedKeys.set(init.name, true); if (!store_1.atomsInitializeObjects.has(init.name)) { store_1.atomsInitializeObjects.set(init === null || init === void 0 ? void 0 : init.name, init); } const useCreate = () => useAtomCreate(init); useCreate['atom-name'] = init.name; useCreate['init-object'] = init; useCreate.key = init.name; return useCreate; } } exports.createAtom = atom; const objectFilters = {}; const resolvedFilters = {}; const filterObservables = {}; const subscribedFilters = {}; const cachedDeps = new Map(); const cachedDepsValues = new Map(); const cached$resolving = new Map(); const cachedReadFilters = new Map(); const cachedReadFiltersValues = new Map(); function filter(init) { if (!init.name) { init.name = init.key; } if (!(0, utils_1._isDefined)(store_1.filtersInitializeObjects.get(init === null || init === void 0 ? void 0 : init.name)) || store_1.filtersInitializeObjects.get(init.name) !== init) { store_1.filtersInitializeObjects.set(init === null || init === void 0 ? void 0 : init.name, init); } const { name = '' } = store_1.filtersInitializeObjects.get(init === null || init === void 0 ? void 0 : init.name); if (!cachedDeps.has(name)) { cachedDeps.set(name, {}); } let filterDeps = cachedDeps.get(name); if (!cachedDepsValues.has(name)) { cachedDepsValues.set(name, {}); } const depsValues = cachedDepsValues.get(name); if (!cached$resolving.has(name)) { cached$resolving.set(name, {}); } let $resolving = cached$resolving.get(name); if (!cachedReadFilters.has(name)) { cachedReadFilters.set(name, {}); } let readFilters = cachedReadFilters.get(name); if (!cachedReadFiltersValues.has(name)) { cachedReadFiltersValues.set(name, {}); } let readFiltersValues = cachedReadFilters.get(name); const useFilterGet = () => { const hookCall = (0, react_1.useMemo)(() => Math.random(), []); const { storeName } = (0, react_1.useContext)(atomicStateContext); const $prefix = storeName === false ? '' : storeName; if (!($prefix in filterDeps)) { filterDeps[$prefix] = {}; } const $filterKey = storeName === false ? name : storeName + '-' + name; if (!filterObservables[$filterKey]) { filterObservables[$filterKey] = createObserver(); } const filterObserver = filterObservables[$filterKey]; const notifyOtherFilters = (0, react_1.useCallback)(function notifyOtherFilters(hookCall, payload) { filterObserver.notify($filterKey, hookCall, payload); }, [storeName, hookCall, $filterKey]); for (let dep in filterDeps[$prefix]) { if (depsValues[dep] !== store_1.defaultAtomsValues.get(dep)) { resolvedFilters[$filterKey] = false; } } for (let dep in readFilters) { if (readFiltersValues[dep] !== store_1.defaultFiltersValues.get(dep)) { resolvedFilters[$filterKey] = false; } } const $$filterGet = ($atom) => { var _a, _b; subscribedFilters[$filterKey] = true; if (!(0, utils_1._isFunction)($atom)) { const depsKey = storeName === false ? $atom.name : [storeName, $atom.name].join('-'); filterDeps[$prefix][depsKey] = true; depsValues[depsKey] = store_1.defaultAtomsValues.get(depsKey); } else { const depsKey = storeName === false ? (_a = $atom === null || $atom === void 0 ? void 0 : $atom['init-object']) === null || _a === void 0 ? void 0 : _a.name : [storeName, (_b = $atom === null || $atom === void 0 ? void 0 : $atom['init-object']) === null || _b === void 0 ? void 0 : _b.name].join('-'); filterDeps[$prefix][depsKey] = true; depsValues[depsKey] = store_1.defaultAtomsValues.get(depsKey); } const __valuesKey = storeName === false ? atom.name : [storeName, atom.name].join('-'); const __valuesKeyNames = storeName === false ? $atom['atom-name'] : [storeName, $atom['atom-name']].join('-'); return !(0, utils_1._isFunction)($atom) ? !(0, utils_1._isDefined)(store_1.defaultAtomsValues.get(__valuesKey)) ? $atom.default : store_1.defaultAtomsValues.get(__valuesKey) : !(0, utils_1._isDefined)(store_1.defaultAtomsValues.get(__valuesKeyNames)) ? $atom['init-object'].default : store_1.defaultAtomsValues.get(__valuesKeyNames); }; const $$filterRead = ($filter) => { var _a; subscribedFilters[$filterKey] = true; const __filtersKey = !(0, utils_1._isFunction)($filter) ? storeName === false ? $filter.name : [storeName, $filter.name].join('-') : storeName === false ? $filter['filter-name'] : [storeName, $filter['filter-name']].join('-'); if (!(0, utils_1._isFunction)($filter)) { readFilters[__filtersKey] = true; readFiltersValues[__filtersKey] = store_1.defaultFiltersValues.get(__filtersKey); } else { // We want any re-renders from filters used to trigger a re-render of the current filter readFilters[__filtersKey] = true; readFiltersValues[__filtersKey] = store_1.defaultFiltersValues.get(__filtersKey); } return !(0, utils_1._isFunction)($filter) ? !(0, utils_1._isDefined)(store_1.defaultFiltersValues.get(__filtersKey)) ? $filter.default : store_1.defaultFiltersValues.get(__filtersKey) : !(0, utils_1._isDefined)(store_1.defaultFiltersValues.get(__filtersKey)) ? (_a = $filter['init-object']) === null || _a === void 0 ? void 0 : _a.default : store_1.defaultFiltersValues.get(__filtersKey); }; const getObject = (0, react_1.useMemo)(() => ({ get: ($atom) => { const isFilter = typeof ($atom === null || $atom === void 0 ? void 0 : $atom['init-object'].get) === 'function'; return isFilter ? $$filterRead($atom) : $$filterGet($atom); }, read: ($filter) => { return $$filterRead($filter); } }), [storeName]); function getInitialValue() { try { let firstResolved = undefined; return !resolvedFilters[$filterKey] ? (() => { var _a; resolvedFilters[$filterKey] = true; store_1.defaultFiltersValues.set($filterKey, init.default); try { $resolving[$filterKey] = true; firstResolved = (_a = store_1.filtersInitializeObjects .get(name)) === null || _a === void 0 ? void 0 : _a.get(getObject); if (!(0, utils_1._isDefined)(firstResolved)) { return init.default; } else { ; (() => __awaiter(this, void 0, void 0, function* () { firstResolved = yield firstResolved; store_1.defaultFiltersValues.set($filterKey, firstResolved); // This hook will notify itself if any deps have changed if ((0, utils_1._isDefined)(firstResolved)) { notifyOtherFilters('', firstResolved); } }))(); return firstResolved; } } catch (err) { } finally { if ((0, utils_1._isDefined)(firstResolved)) { notifyOtherFilters('', firstResolved); } queueMicrotask(() => { $resolving[$filterKey] = false; }); return firstResolved; } })() : (() => { return store_1.defaultFiltersValues.get($filterKey); })(); } catch (err) { return init.default; } } let defValue = store_1.defaultFiltersValues.get($filterKey); const initialValue = getInitialValue(); resolvedFilters[$filterKey] = true; if ((0, utils_1._isPromise)(initialValue)) { store_1.defaultFiltersValues.set($filterKey, initialValue); setTimeout(() => __awaiter(this, void 0, void 0, function* () { store_1.defaultFiltersValues.set($filterKey, yield initialValue); notifyOtherFilters(hookCall, yield store_1.defaultFiltersValues.get($filterKey)); }), 0); } if ((0, utils_1._isDefined)(initialValue)) { if ((0, utils_1._isPromise)(initialValue)) { initialValue.then((e) => { defValue = e; store_1.defaultFiltersValues.set($filterKey, e); filterObserver.notify($filterKey, '', e); }); } else { defValue = initialValue; store_1.defaultFiltersValues.set($filterKey, initialValue); } } else { if (!(0, utils_1._isDefined)(defValue)) { defValue = init.default; } } const [filterValue, setFilterValue] = (0, react_1.useState)(() => (0, utils_1._isDefined)(defValue) ? (0, utils_1._isPromise)(defValue) ? (0, utils_1._isPromise)(initialValue) ? init.default : initialValue : defValue : (() => { return defValue; })()); (0, react_1.useEffect)(() => { var _a; (_a = atomObservables[$filterKey]) === null || _a === void 0 ? void 0 : _a.notify($filterKey, '', filterValue); }, [filterValue]); (0, react_1.useEffect)(() => { if (!resolvedFilters[$filterKey]) { if ((0, utils_1._isDefined)(filterValue)) { notifyOtherFilters(hookCall, filterValue); } } }, [filterValue, hookCall, $filterKey, resolvedFilters[$filterKey]]); (0, react_1.useEffect)(() => { // Render the first time if initialValue is a promise if ((0, utils_1._isPromise)(initialValue)) { initialValue.then((initial) => { if ((0, utils_1._isDefined)(initial)) { store_1.defaultFiltersValues.set($filterKey, initial); setFilterValue(initial); } }); } }, [initialValue]); function renderValue(e) { return __awaiter(this, void 0, void 0, function* () { var _a; const isFilterUpdate = e.storeName in readFilters; if ((0, utils_1._isFunction)(e.payload) ? true : isFilterUpdate ? !(0, utils_1.jsonEquality)(store_1.defaultFiltersValues.get(e.storeName), readFiltersValues[e.storeName]) : !(0, utils_1.jsonEquality)(e.payload, depsValues[e.storeName])) { if (e.storeName in (isFilterUpdate ? readFilters : filterDeps[$prefix])) { if ((0, utils_1._isDefined)(e.payload)) { if (isFilterUpdate) { readFiltersValues[e.storeName] = e.payload; } else { depsValues[e.storeName] = e.payload; } } } if (!$resolving[$filterKey]) { $resolving[$filterKey] = true; try { const newValue = e.storeName in filterDeps[$prefix] || e.storeName in readFilters ? (_a = store_1.filtersInitializeObjects.get(name)) === null || _a === void 0 ? void 0 : _a.get(getObject) : store_1.defaultFiltersValues.get($filterKey); store_1.defaultFiltersValues.set($filterKey, newValue); (() => __awaiter(this, void 0, void 0, function* () { if ((0, utils_1._isFunction)(newValue)) { notifyOtherFilters(hookCall, newValue); setFilterValue(() => newValue); } else { if ((0, utils_1._isDefined)(newValue)) { if ((0, utils_1._isPromise)(newValue)) { const newV = yield newValue; setFilterValue(newV); notifyOtherFilters(hookCall, newV); } else { setFilterValue(newValue); notifyOtherFilters(hookCall, newValue); } } } }))(); } catch (err) { } finally { queueMicrotask(() => { $resolving[$filterKey] = false; }); } } } }); } (0, react_1.useEffect)(() => { // Whenever the filter object / function changes, add atoms deps again var _a, _b; for (let dep in filterDeps[$prefix]) { (_a = atomObservables[dep]) === null || _a === void 0 ? void 0 : _a.observer.addListener(dep, renderValue); } // We subscribe to any re-renders of filters that our current filter is using for (let readFilter in readFilters) { (_b = filterObservables[readFilter]) === null || _b === void 0 ? void 0 : _b.observer.addListener(readFilter, renderValue); } return () => { var _a, _b; for (let dep in filterDeps[$prefix]) { (_a = atomObservables[dep]) === null || _a === void 0 ? void 0 : _a.observer.removeListener(dep, renderValue); } for (let readFilter in readFilters) { (_b = filterObservables[readFilter]) === null || _b === void 0 ? void 0 : _b.observer.removeListener(readFilter, renderValue); } }; }, []); function updateValueFromObservableChange(e) { return __awaiter(this, void 0, void 0, function* () { const { payload } = e; if (hookCall !== e.hookCall) { const $payload = yield payload; if ((0, utils_1._isFunction)($payload)) { setFilterValue(() => $payload); } else { if ((0, utils_1._isDefined)($payload)) { setFilterValue($payload); } } } }); } (0, react_1.useEffect)(() => { var _a; (_a = filterObserver.observer) === null || _a === void 0 ? void 0 : _a.addListener($filterKey, updateValueFromObservableChange); return () => { var _a; (_a = filterObserver === null || filterObserver === void 0 ? void 0 : filterObserver.observer) === null || _a === void 0 ? void 0 : _a.removeListener($filterKey, updateValueFromObservableChange); }; }, [$filterKey]); return filterValue; }; useFilterGet['filter-name'] = name; useFilterGet['init-object'] = init; return useFilterGet; } exports.selector = filter; function useFilter(f) { var _a; const { storeName } = (0, react_1.useContext)(atomicStateContext); if ((0, utils_1._isFunction)(f)) { const $f = f['init-object']; if ($f !== store_1.filtersInitializeObjects.get($f === null || $f === void 0 ? void 0 : $f.name)) { if ((0, utils_1._isDefined)($f)) { ; (store_1.filtersInitializeObjects.get($f === null || $f === void 0 ? void 0 : $f.name) || {}).get = $f === null || $f === void 0 ? void 0 : $f.get; } } } else { if (!f.name) { // @ts-ignore f.name = f.key; } if (store_1.filtersInitializeObjects.get(f.name) !== f) { ; (store_1.filtersInitializeObjects.get(f === null || f === void 0 ? void 0 : f.name) || {}).get = f === null || f === void 0 ? void 0 : f.get; } } const renderdFilter = !(0, utils_1._isFunction)(f) ? (() => { if (!f.name) { // @ts-ignore f.name = f.key; } const __filterSKey = storeName === false ? f.name : [storeName, f.name].join('-'); if (!(0, utils_1._isDefined)(objectFilters[__filterSKey])) { objectFilters[__filterSKey] = filter(store_1.filtersInitializeObjects.get(f.name)); } else { if (objectFilters[__filterSKey]['init-object'] !== f) { objectFilters[__filterSKey] = filter(f); } } return objectFilters[__filterSKey](); })() : f(); // @ts-ignore return (renderdFilter !== null && renderdFilter !== void 0 ? renderdFilter : (_a = f['init-object']) === null || _a === void 0 ? void 0 : _a.default); } const objectAtoms = {}; /** * Get an atom's value and state setter */ function useAtom(atom) { var _a; if (!(0, utils_1._isFunction)(atom)) { if (!atom.name) { atom.name = atom.key; } if (!(0, utils_1._isDefined)(objectAtoms[atom.name])) { objectAtoms[atom.name] = (0, exports.createAtom)(atom); } else { if (objectAtoms[atom.name]['init-object'] !== atom) { objectAtoms[atom.name] = (0, exports.createAtom)(atom); } } } if (!(0, utils_1._isFunction)(atom)) { if (!atom.name) { atom.name = atom.key; } } return (!(0, utils_1._isFunction)(atom) ? objectAtoms[((_a = atom.name) !== null && _a !== void 0 ? _a : atom.key)]() : atom()); } /** * Creates a store with the `setPartialvalue`, `setValue` and `reset` methods. * It returns a hook that returns an array with the value and the actions */ function createAtomicHook(config = {}) { const globalStoreState = atom(Object.assign(Object.assign({}, config), { actions: Object.assign({ /** * Should be used only with object values */ // @ts-ignore setPartialvalue({ dispatch, args }) { if (typeof args === 'function') { // @ts-ignore dispatch(prev => (Object.assign(Object.assign({}, prev), args(prev)))); // @ts-ignore } else dispatch(prev => (Object.assign(Object.assign({}, prev), args))); }, // @ts-ignore setPartial({ dispatch, args }) { if (typeof args === 'function') { // @ts-ignore dispatch(prev => (Object.assign(Object.assign({}, prev), args(prev)))); // @ts-ignore } else dispatch(prev => (Object.assign(Object.assign({}, prev), args))); }, // Can be used with non-object values // @ts-ignore setValue({ dispatch, args }) { // @ts-ignore dispatch(args); }, /** * Reset the store state to the original value (Taken from `default`) */ // @ts-ignore reset({ dispatch }