{"version":3,"file":"index.mjs","sources":["../src/batch.ts","../src/store.ts","../src/ssr.ts","../src/hooks.ts"],"sourcesContent":["import * as ReactDOM from 'react-dom';\n\nexport const batch = (ReactDOM as any)['unstable_batchedUpdates'.toString()] || ((callback: () => void) => callback());\n","import type {\n  Atom,\n  AtomKey,\n  AtomStore,\n  AtomStoreUpdate,\n  AtomUpdater,\n  AtomValueUpdate,\n  DynamicAtomGetter,\n  DynamicAtomSetter\n} from './types.js';\n\nimport { default as mitt } from 'mitt';\nimport { batch } from './batch.js';\n\n// Unique id\nlet _id = 0;\nconst id = () => Symbol(_id++);\n\n/**\n * Special EventEmitter for state updates.\n *\n * @description Precoil is built around an idiomatic asynchronous event-driven\n * architecture in which setters emits atoms keys named events that cause\n * listeners to be called with a new state.\n *\n * @example\n *\n *   // Logs state on update atom.\n *   unsafe_updater.on(counterAtom.key, console.log);\n *\n * @example\n *\n *   // Logs state on update atom with `counter` key.\n *   unsafe_updater.on('counter', console.log);\n *\n * @see https://github.com/developit/mitt\n *\n * @nosideeffects\n */\nexport const unsafe_updater = /*@__PURE__*/mitt<AtomStoreUpdate>();\n\n/**\n * The source of truth for all created atoms.\n *\n * @description It is better to use the atom's method to get the current state.\n *\n * @example\n *\n *   console.log(store.get('counter')); // log: 0\n *\n * @nosideeffects\n */\nexport const unsafe_store: AtomStore = /*@__PURE__*/new Map();\n\n/**\n * An atom represents state in precoil.\n *\n * @description Atoms contain the source of truth for our application state.\n *\n * @template T Atom state type.\n *\n * @param defaultValue Initial atom state.\n *\n * @param key A unique value that allows you to identify the atom.\n *\n * @returns A new atom that lets you read and update its state.\n *\n * @example\n *\n *   const counterAtom = atom(0, 'counter');\n *\n *   console.log(counterAtom.get()); // log: 0\n *   console.log(counterAtom.set(1)); // log: 1\n *\n * @noinline\n */\nexport const atom = <Value>(defaultValue: Value, key: AtomKey = id()): Atom<Value> => {\n  unsafe_store.set(key, defaultValue);\n\n  const _get = () => unsafe_store.get(key) as Value;\n\n  const _set = (update: AtomValueUpdate<Value>) => {\n    const current = unsafe_store.get(key) as Value;\n    const next = typeof update === 'function' ? (update as AtomUpdater<Value>)(current) : update;\n\n    if (\n      (\n        /* eslint-disable no-self-compare */\n        current === current ||\n        next === next\n      ) &&\n      current !== next\n    ) {\n      unsafe_store.set(key, next);\n\n      // Sync update\n      batch(() => unsafe_updater.emit(key, next));\n    }\n\n    return next;\n  };\n\n  const _sub = (next: (value: Value) => void) => {\n    unsafe_updater.on(key, next);\n\n    return () => unsafe_updater.off(key, next);\n  };\n\n  return {\n    key,\n    def: defaultValue,\n    get: _get,\n    set: _set,\n    sub: _sub\n  };\n};\n\n/**\n * An dynamic atom represents state in precoil.\n *\n * @description Dynamic atoms depend on other atoms.\n *\n * @template T Dynamic atom state type.\n *\n * @param get Function to get states of other atoms.\n *\n * @param set Function to set new states to other atoms.\n *\n * @param key A unique value that allows you to identify the atom.\n *\n * @returns A new dynamic atom that lets you read and update dependent\n * atoms state.\n *\n * @example\n *\n *   const dynamicCounterAtom = dynamicAtom(\n *     (get) => get(counterAtom),\n *     (get, set, arg) => set(counterAtom, arg),\n *     'dynamicCount'\n *   );\n *\n *   console.log(dynamicCounterAtom.get()); // log: 0\n *   console.log(dynamicCounterAtom.set(1)); // log: 1\n *\n * @noinline\n */\nexport const dynamicAtom = <Value, Update = undefined>(\n  get: (\n    get: DynamicAtomGetter\n  ) => Value,\n  set: (\n    get: DynamicAtomGetter,\n    set: DynamicAtomSetter,\n    update: Update\n  ) => Value,\n  key: AtomKey = id()\n): Atom<Value, Update> => {\n  const _depend: AtomKey[] = [];\n\n  const _get = () => get((from) => {\n    const _key = from.key;\n\n    if (_key === key) {\n      return unsafe_store.get(_key);\n    }\n\n    if (!_depend.includes(_key)) {\n      _depend.push(_key);\n    }\n\n    return from.get();\n  });\n\n  const _set = (update: AtomValueUpdate<Value, Update>) => set(\n    (from) => from.get(),\n    (from, _update) => from.set(_update),\n    typeof update === 'function' ? (update as AtomUpdater<Value, Update>)(unsafe_store.get(key)) : update\n  );\n\n  const _dynamic = atom(_get(), key);\n  const _update = _dynamic.set;\n\n  _dynamic.set = (arg) => _update(_set(arg as any));\n\n  _depend.some((_key) => unsafe_updater.on(_key, () => _update(_get())));\n\n  return _dynamic as any;\n};\n","import type { Atom } from './types.js';\n\nimport { unsafe_store } from './store.js';\n\n/**\n * Sets the state of the passed atom.\n */\nexport const hydrateAtom = <T>(atom: Atom<T>, value: T) => {\n  unsafe_store.set(atom.key, value);\n};\n\n/**\n * Resets a state of passed atom.\n */\nexport const resetAtom = <T>(atom: Atom<T>) => {\n  unsafe_store.set(atom.key, atom.def);\n};\n\n/**\n * Resets states of passed atoms.\n */\nexport const resetAtoms = (atoms: ReadonlyArray<Atom<any>>) => {\n  atoms.some(resetAtom);\n};\n","import type { Atom, AtomSelector } from './types.js';\n\nimport * as React from 'react';\n\n/**\n * @description This is the recommended hook to use when a component intends to read computed state.\n * Using this hook in a React component will subscribe the component to re-render when the computed\n * state is updated.\n *\n * @returns The computed value of the given atom state.\n *\n * @example\n *\n *   // Somewhere outside the component, for example, next to the declaration of the atom:\n *   const selectPlus = (value) => value + 1;\n *\n *   // In the component:\n *   const plus = useAtomSelector(counterAtom, selectPlus);\n *\n * @noinline\n */\nexport const useAtomSelector = <T, S>(atom: Atom<T>, selector: AtomSelector<T, S>) => {\n  const reselect = React.useRef(() => selector(atom.get())).current;\n\n  return React.useSyncExternalStore(\n    atom.sub,\n    reselect,\n    reselect\n  );\n};\n\n/**\n * @description This is the recommended hook to use when a component intends to read state\n * without writing to it. Using this hook in a React component will subscribe the component\n * to re-render when the state is updated.\n *\n * @returns The value of the given atom state.\n *\n * @example\n *\n *   const counter = useAtomValue(counterAtom);\n *\n * @nosideeffects\n */\nexport const useAtomValue = <T>(atom: Atom<T>) => {\n  return React.useSyncExternalStore(\n    atom.sub,\n    atom.get,\n    atom.get\n  );\n};\n\n/**\n * @description This is the recommended hook to use when a component intends to write to\n * state without reading it. Allows a component to set the value without subscribing the\n * component to re-render when the value changes.\n *\n * @returns A setter function for updating the value of atom state.\n *\n * @example\n *\n *   const setCounter = useSetAtomState(counterAtom);\n *\n * @nosideeffects\n */\nexport const useSetAtomState = <T>(atom: Atom<T>) => {\n  return React.useRef(atom.set).current;\n};\n\n/**\n * @description This is the recommended hook to use when a component intends to read and\n * write state. Using this hook in a React component will subscribe the component\n * to re-render when the state is updated.\n *\n * @returns A tuple where the first element is the value of state and the second element\n * is a setter function that will update the value of the given state when called.\n *\n * @example\n *\n *   const [counter, setCounter] = useAtomState(counterAtom);\n *\n * @nosideeffects\n */\nexport const useAtomState = <T>(atom: Atom<T>) => {\n  const state = useAtomValue(atom);\n  const update = useSetAtomState(atom);\n\n  return [state, update] as const;\n};\n\n/**\n * @description Using this hook allows a component to reset the state to its default value without\n * subscribing the component to re-render whenever the state changes.\n *\n * @returns A function that will reset the value of the given state to its default value.\n *\n * @example\n *\n *   const resetCounter = useResetAtomState(counterAtom);\n *\n * @nosideeffects\n */\nexport const useResetAtomState = <T>(atom: Atom<T>) => {\n  return React.useRef(() => atom.set(atom.def)).current;\n};\n\n/**\n * @description This is the recommended hook to use when a component intends to read computed state\n * only on first render. Using this hook in a React component will **NOT** subscribe the component\n * to re-render when the state is updated.\n *\n * @returns The value of the given atom state.\n *\n * @example\n *\n *   const counter = useAtomConst(counterAtom);\n *\n * @nosideeffects\n */\nexport const useAtomConst = <T>(atom: Atom<T>) => {\n  return React.useMemo(atom.get, []);\n};\n\n/**\n * @description This is the recommended hook to use when a component intends to read state\n * only on first render. Using this hook in a React component will **NOT** subscribe the component\n * to re-render when the state is updated.\n *\n * @returns The computed value of the given atom state.\n *\n * @example\n *\n *   const plus = useAtomSelectorConst(counterAtom, (value) => value + 1);\n *\n * @nosideeffects\n */\nexport const useAtomSelectorConst = <T, S>(atom: Atom<T>, selector: AtomSelector<T, S>) => {\n  return React.useMemo(() => selector(atom.get()), []);\n};\n"],"names":["_update","atom"],"mappings":"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"}