jotai
Version:
👻 Primitive and flexible state management for React
166 lines (159 loc) • 5.75 kB
JavaScript
'use client';
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('jotai/vanilla'), require('jotai/vanilla/internals')) :
typeof define === 'function' && define.amd ? define(['exports', 'react', 'jotai/vanilla', 'jotai/vanilla/internals'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jotaiReact = {}, global.React, global.jotaiVanilla, global.jotaiVanillaInternals));
})(this, (function (exports, ReactExports, vanilla, internals) { 'use strict';
var StoreContext = ReactExports.createContext(undefined);
function useStore(options) {
var store = ReactExports.useContext(StoreContext);
return (options == null ? void 0 : options.store) || store || vanilla.getDefaultStore();
}
function Provider(_ref) {
var children = _ref.children,
store = _ref.store;
var storeRef = ReactExports.useRef(undefined);
if (!store && !storeRef.current) {
storeRef.current = vanilla.createStore();
}
return ReactExports.createElement(StoreContext.Provider, {
value: store || storeRef.current
}, children);
}
var isPromiseLike = function isPromiseLike(x) {
return typeof (x == null ? void 0 : x.then) === 'function';
};
var attachPromiseMeta = function attachPromiseMeta(promise) {
promise.status = 'pending';
promise.then(function (v) {
promise.status = 'fulfilled';
promise.value = v;
}, function (e) {
promise.status = 'rejected';
promise.reason = e;
});
};
var use = ReactExports.use || function (promise) {
if (promise.status === 'pending') {
throw promise;
} else if (promise.status === 'fulfilled') {
return promise.value;
} else if (promise.status === 'rejected') {
throw promise.reason;
} else {
attachPromiseMeta(promise);
throw promise;
}
};
var continuablePromiseMap = new WeakMap();
var createContinuablePromise = function createContinuablePromise(promise, getValue) {
var continuablePromise = continuablePromiseMap.get(promise);
if (!continuablePromise) {
continuablePromise = new Promise(function (resolve, reject) {
var curr = promise;
var onFulfilled = function onFulfilled(me) {
return function (v) {
if (curr === me) {
resolve(v);
}
};
};
var onRejected = function onRejected(me) {
return function (e) {
if (curr === me) {
reject(e);
}
};
};
var _onAbort = function onAbort() {
try {
var nextValue = getValue();
if (isPromiseLike(nextValue)) {
continuablePromiseMap.set(nextValue, continuablePromise);
curr = nextValue;
nextValue.then(onFulfilled(nextValue), onRejected(nextValue));
internals.INTERNAL_registerAbortHandler(nextValue, _onAbort);
} else {
resolve(nextValue);
}
} catch (e) {
reject(e);
}
};
promise.then(onFulfilled(promise), onRejected(promise));
internals.INTERNAL_registerAbortHandler(promise, _onAbort);
});
continuablePromiseMap.set(promise, continuablePromise);
}
return continuablePromise;
};
function useAtomValue(atom, options) {
var store = useStore(options);
var _useReducer = ReactExports.useReducer(function (prev) {
var nextValue = store.get(atom);
if (Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom) {
return prev;
}
return [nextValue, store, atom];
}, undefined, function () {
return [store.get(atom), store, atom];
}),
_useReducer$ = _useReducer[0],
valueFromReducer = _useReducer$[0],
storeFromReducer = _useReducer$[1],
atomFromReducer = _useReducer$[2],
rerender = _useReducer[1];
var value = valueFromReducer;
if (storeFromReducer !== store || atomFromReducer !== atom) {
rerender();
value = store.get(atom);
}
var delay = options == null ? void 0 : options.delay;
ReactExports.useEffect(function () {
var unsub = store.sub(atom, function () {
if (typeof delay === 'number') {
var _value = store.get(atom);
if (isPromiseLike(_value)) {
attachPromiseMeta(createContinuablePromise(_value, function () {
return store.get(atom);
}));
}
setTimeout(rerender, delay);
return;
}
rerender();
});
rerender();
return unsub;
}, [store, atom, delay]);
ReactExports.useDebugValue(value);
if (isPromiseLike(value)) {
var promise = createContinuablePromise(value, function () {
return store.get(atom);
});
return use(promise);
}
return value;
}
function useSetAtom(atom, options) {
var store = useStore(options);
var setAtom = ReactExports.useCallback(function () {
if (!('write' in atom)) {
throw new Error('not writable atom');
}
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return store.set.apply(store, [atom].concat(args));
}, [store, atom]);
return setAtom;
}
function useAtom(atom, options) {
return [useAtomValue(atom, options), useSetAtom(atom, options)];
}
exports.Provider = Provider;
exports.useAtom = useAtom;
exports.useAtomValue = useAtomValue;
exports.useSetAtom = useSetAtom;
exports.useStore = useStore;
}));