UNPKG

jotai-x

Version:

Jotai store factory for a best-in-class developer experience.

433 lines (428 loc) 15 kB
var __defProp = Object.defineProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; // src/atomWithFn.ts import { atom } from "jotai"; var wrapFn = (fnOrValue) => typeof fnOrValue === "function" ? { __fn: fnOrValue } : fnOrValue; var unwrapFn = (wrappedFnOrValue) => wrappedFnOrValue && typeof wrappedFnOrValue === "object" && "__fn" in wrappedFnOrValue ? wrappedFnOrValue.__fn : wrappedFnOrValue; var atomWithFn = (initialValue) => { const baseAtom = atom(wrapFn(initialValue)); return atom( (get) => unwrapFn(get(baseAtom)), (_get, set, value) => set(baseAtom, wrapFn(value)) ); }; // src/createAtomProvider.tsx import React2 from "react"; import { createStore } from "jotai/vanilla"; // src/useHydrateStore.ts import React from "react"; import { atom as atom2, useSetAtom } from "jotai"; import { useHydrateAtoms } from "jotai/utils"; var useHydrateStore = (atoms, initialValues, options = {}) => { const values = React.useMemo(() => { const nextValues = []; for (const key of Object.keys(atoms)) { const initialValue = initialValues[key]; if (initialValue !== void 0) { nextValues.push([atoms[key], initialValue]); } } return nextValues; }, [atoms, initialValues]); useHydrateAtoms(values, options); }; var useSyncStore = (atoms, values, { skipInitialValues, store: storeOption } = {}) => { const atomEntries = React.useMemo( () => Object.entries(atoms), [atoms] ); const syncAtom = React.useMemo( () => atom2( null, (_get, set, nextValues) => { const previousValues = nextValues.previousValues; for (const [key, writableAtom] of atomEntries) { const value = nextValues.values[key]; if (value === void 0 || value === null) continue; if (previousValues && Object.is(previousValues[key], value)) { continue; } set(writableAtom, value); } } ), [atomEntries] ); const syncValues = useSetAtom(syncAtom, { store: storeOption }); const previousValuesRef = React.useRef(skipInitialValues); React.useEffect(() => { syncValues({ previousValues: previousValuesRef.current, values }); previousValuesRef.current = values; }, [syncValues, values]); }; // src/createAtomProvider.tsx var getFullyQualifiedScope = (storeName, scope) => { return `${storeName}:${scope}`; }; var PROVIDER_SCOPE = "provider"; var AtomStoreContext = React2.createContext( /* @__PURE__ */ new Map() ); var useAtomStore = (storeName, scope = PROVIDER_SCOPE, warnIfUndefined = true) => { var _a; const storeContext = React2.useContext(AtomStoreContext); const store = (_a = storeContext.get(getFullyQualifiedScope(storeName, scope))) != null ? _a : storeContext.get(getFullyQualifiedScope(storeName, PROVIDER_SCOPE)); if (!store && warnIfUndefined) { console.warn( `Tried to access jotai store '${storeName}' outside of a matching provider.` ); } return store; }; var HydrateAtoms = (_a) => { var _b = _a, { initialValues, children, store, atoms } = _b, props = __objRest(_b, [ "initialValues", "children", "store", "atoms" ]); const hydratedValues = __spreadValues(__spreadValues({}, initialValues), props); useHydrateStore(atoms, hydratedValues, { store }); useSyncStore(atoms, props, { store, skipInitialValues: props }); return /* @__PURE__ */ React2.createElement(React2.Fragment, null, children); }; var createAtomProvider = (storeScope, atoms, options = {}) => { const Effect = options.effect; return (_a) => { var _b = _a, { store, scope, children, resetKey } = _b, props = __objRest(_b, ["store", "scope", "children", "resetKey"]); const [storeState, setStoreState] = React2.useState( () => store != null ? store : createStore() ); const resolvedStore = store != null ? store : storeState; React2.useEffect(() => { if (!store && resetKey) { setStoreState(createStore()); } }, [resetKey, store]); const previousStoreContext = React2.useContext(AtomStoreContext); const storeContext = React2.useMemo(() => { const newStoreContext = new Map(previousStoreContext); if (scope) { newStoreContext.set( getFullyQualifiedScope(storeScope, scope), resolvedStore ); } newStoreContext.set( getFullyQualifiedScope(storeScope, PROVIDER_SCOPE), resolvedStore ); return newStoreContext; }, [previousStoreContext, resolvedStore, scope]); return /* @__PURE__ */ React2.createElement(AtomStoreContext.Provider, { value: storeContext }, /* @__PURE__ */ React2.createElement(HydrateAtoms, __spreadValues({ store: resolvedStore, atoms }, props), !!Effect && /* @__PURE__ */ React2.createElement(Effect, null), children)); }; }; // src/createAtomStore.ts import React3, { useMemo } from "react"; import { getDefaultStore, useAtom, useAtomValue, useSetAtom as useSetAtom2 } from "jotai"; import { selectAtom } from "jotai/utils"; var capitalizeFirstLetter = (str = "") => str.length > 0 ? str[0].toUpperCase() + str.slice(1) : ""; var isAtom = (possibleAtom) => !!possibleAtom && typeof possibleAtom === "object" && "read" in possibleAtom && typeof possibleAtom.read === "function"; var convertScopeShorthand = (optionsOrScope = {}) => typeof optionsOrScope === "string" ? { scope: optionsOrScope } : optionsOrScope; var identity = (x) => x; var createAtomStore = (initialState, { name, delay: delayRoot, effect, extend, suppressWarnings }) => { const atomsWithoutExtend = {}; const writableAtomsWithoutExtend = {}; const atomIsWritable = {}; function UseStoreApiFactory(options, store) { this.options = options; this.store = store; } for (const [key, atomOrValue] of Object.entries(initialState)) { const atomConfig = isAtom(atomOrValue) ? atomOrValue : atomWithFn(atomOrValue); atomsWithoutExtend[key] = atomConfig; const writable = "write" in atomConfig; atomIsWritable[key] = writable; if (writable) { writableAtomsWithoutExtend[key] = atomConfig; } } const atoms = __spreadValues({}, atomsWithoutExtend); if (extend) { const extendedAtoms = extend(atomsWithoutExtend); for (const [key, atomConfig] of Object.entries(extendedAtoms)) { atoms[key] = atomConfig; atomIsWritable[key] = "write" in atomConfig; } } const useStore = (optionsOrScope = {}) => { const { scope, store, warnIfNoStore = !suppressWarnings } = convertScopeShorthand(optionsOrScope); const contextStore = useAtomStore(name, scope, !store && warnIfNoStore); return store != null ? store : contextStore; }; const useAtomValueWithStore = (atomConfig, store, optionsOrScope, selector = identity, equalityFnOrDeps, deps) => { var _a, _b; const options = convertScopeShorthand(optionsOrScope); const equalityFn = typeof equalityFnOrDeps === "function" ? equalityFnOrDeps : void 0; deps = (_a = typeof equalityFnOrDeps === "function" ? deps : equalityFnOrDeps) != null ? _a : [selector, equalityFn]; const [memoizedSelector, memoizedEqualityFn] = React3.useMemo( () => [selector, equalityFn], // eslint-disable-next-line react-compiler/react-compiler deps ); const selectorAtom = React3.useMemo( () => memoizedSelector === identity && !memoizedEqualityFn ? atomConfig : selectAtom( atomConfig, memoizedSelector, memoizedEqualityFn ), [atomConfig, memoizedSelector, memoizedEqualityFn] ); return useAtomValue(selectorAtom, { store, delay: (_b = options.delay) != null ? _b : delayRoot }); }; const getAtomWithStore = (atomConfig, store, _optionsOrScope) => { return (store != null ? store : getDefaultStore()).get(atomConfig); }; const useSetAtomWithStore = (atomConfig, store, _optionsOrScope) => { return useSetAtom2(atomConfig, { store }); }; const setAtomWithStore = (atomConfig, store, _optionsOrScope) => { return (...args) => (store != null ? store : getDefaultStore()).set( atomConfig, ...args ); }; const useAtomStateWithStore = (atomConfig, store, optionsOrScope) => { const { delay = delayRoot } = convertScopeShorthand(optionsOrScope); return useAtom(atomConfig, { store, delay }); }; const subscribeAtomWithStore = (atomConfig, store, _optionsOrScope) => { return (callback) => { store != null ? store : store = getDefaultStore(); const unsubscribe = store.sub(atomConfig, () => { callback(store.get(atomConfig)); }); return () => unsubscribe(); }; }; for (const key of Object.keys(atoms)) { const atomConfig = atoms[key]; const isWritable = atomIsWritable[key]; const capitalizedKey = capitalizeFirstLetter(key); UseStoreApiFactory.prototype[`use${capitalizedKey}Value`] = function(selector, equalityFnOrDeps, deps) { return useAtomValueWithStore( atomConfig, this.store, this.options, selector, equalityFnOrDeps, deps ); }; UseStoreApiFactory.prototype[`get${capitalizedKey}`] = function() { return getAtomWithStore(atomConfig, this.store, this.options); }; UseStoreApiFactory.prototype[`subscribe${capitalizedKey}`] = function(callback) { return subscribeAtomWithStore( atomConfig, this.store, this.options )(callback); }; if (isWritable) { UseStoreApiFactory.prototype[`useSet${capitalizedKey}`] = function() { return useSetAtomWithStore(atomConfig, this.store, this.options); }; UseStoreApiFactory.prototype[`set${capitalizedKey}`] = function(...args) { return setAtomWithStore( atomConfig, this.store, this.options )(...args); }; UseStoreApiFactory.prototype[`use${capitalizedKey}State`] = function() { return useAtomStateWithStore( atomConfig, this.store, this.options ); }; } } const defineUseStoreApiMethod = (methodNameWithKey, methodNameWithAtomConfig, fnWithKey, fnWithAtomConfig = fnWithKey) => { UseStoreApiFactory.prototype[methodNameWithKey] = function(key, ...args) { const atomConfig = atoms[key]; return fnWithKey(atomConfig, this.store, this.options, ...args); }; UseStoreApiFactory.prototype[methodNameWithAtomConfig] = function(atomConfig, ...args) { return fnWithAtomConfig(atomConfig, this.store, this.options, ...args); }; }; defineUseStoreApiMethod("useValue", "useAtomValue", useAtomValueWithStore); defineUseStoreApiMethod("get", "getAtom", getAtomWithStore); defineUseStoreApiMethod("useSet", "useSetAtom", useSetAtomWithStore); defineUseStoreApiMethod( "set", "setAtom", (atomConfig, store, options, ...args) => setAtomWithStore(atomConfig, store, options)(...args), setAtomWithStore ); defineUseStoreApiMethod("useState", "useAtomState", useAtomStateWithStore); defineUseStoreApiMethod( "subscribe", "subscribeAtom", (atomConfig, store, options, callback) => subscribeAtomWithStore(atomConfig, store, options)(callback), subscribeAtomWithStore ); const Provider = createAtomProvider(name, writableAtomsWithoutExtend, { effect }); const storeApi = { atom: atoms, name }; const useStoreApi = (options = {}) => { const convertedOptions = convertScopeShorthand(options); const store = useStore(convertedOptions); return useMemo( () => new UseStoreApiFactory(convertedOptions, store), [ store, convertedOptions.delay, convertedOptions.scope, convertedOptions.store, convertedOptions.warnIfNoStore ] ); }; const useNameState = (key, options) => { var _a; const store = (_a = useStore(options)) != null ? _a : getDefaultStore(); return useAtomStateWithStore(atoms[key], store, options); }; const useNameValue = (key, _a = {}, deps) => { var _b = _a, { equalityFn, selector } = _b, options = __objRest(_b, [ "equalityFn", "selector" ]); var _a2; const store = (_a2 = useStore(options)) != null ? _a2 : getDefaultStore(); return useAtomValueWithStore( atoms[key], store, options, selector, equalityFn != null ? equalityFn : deps, equalityFn && deps ); }; const useNameSet = (key, options) => { var _a; const store = (_a = useStore(options)) != null ? _a : getDefaultStore(); return useSetAtomWithStore(atoms[key], store, options); }; const capitalizedName = capitalizeFirstLetter(name); const storeApiIndex = name.length === 0 ? "store" : `${name}Store`; return { [`${capitalizedName}Provider`]: Provider, [storeApiIndex]: storeApi, [`use${capitalizedName}Store`]: useStoreApi, [`use${capitalizedName}State`]: useNameState, [`use${capitalizedName}Value`]: useNameValue, [`use${capitalizedName}Set`]: useNameSet, name }; }; function useAtomStoreValue(store, key, selector, equalityFnOrDeps, deps) { return store.useValue(key, selector, equalityFnOrDeps, deps); } function useAtomStoreSet(store, key) { return store.useSet(key); } function useAtomStoreState(store, key) { return store.useState(key); } function useStoreAtomValue(store, atom3, selector, equalityFnOrDeps, deps) { return store.useAtomValue(atom3, selector, equalityFnOrDeps, deps); } function useStoreSetAtom(store, atom3) { return store.useSetAtom(atom3); } function useStoreAtomState(store, atom3) { return store.useAtomState(atom3); } export { HydrateAtoms, atomWithFn, createAtomProvider, createAtomStore, useAtomStore, useAtomStoreSet, useAtomStoreState, useAtomStoreValue, useHydrateStore, useStoreAtomState, useStoreAtomValue, useStoreSetAtom, useSyncStore }; //# sourceMappingURL=index.mjs.map