atomic-state
Version:
Atomic State is a state management library for React
1,140 lines • 59.3 kB
JavaScript
'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 }