import type { Loadable } from "atom.io" import type { Canonical } from "atom.io/foundations/canonical" import type { ConstructorOf, Ctor, Store, Transceiver } from "atom.io/internal" import { createMutableAtom, createMutableAtomFamily, createRegularAtom, createRegularAtomFamily, IMPLICIT, } from "atom.io/internal" import type { StateUpdate } from "./events.ts" import type { AtomToken, MutableAtomFamilyToken, MutableAtomToken, RegularAtomFamilyToken, RegularAtomToken, } from "./tokens.ts" export type RegularAtomOptions = { /** The unique identifier of the atom */ key: string /** The starting value of the atom */ default: T | (() => T) /** Hooks used to run side effects when the atom is set */ effects?: readonly AtomEffect[] /** The classes of errors that might be thrown when deriving the atom's default value */ catch?: readonly Ctor[] } /** * Create a regular atom, a global reactive variable in the implicit store * @param options - {@link RegularAtomOptions}. * @returns * A reference to the atom created: a {@link RegularAtomToken} */ export function atom( options: RegularAtomOptions, ): RegularAtomToken { return createRegularAtom(IMPLICIT.STORE, options, undefined) } export type MutableAtomOptions> = { /** The unique identifier of the atom */ key: string /** A constructor for the atom's value */ class: ConstructorOf /** Hooks used to run side effects when the atom is set */ effects?: readonly AtomEffect[] } /** * Create a mutable atom, a global reactive variable in the implicit store * * The value of a mutable atom must be some kind of {@link Transceiver}. * * @param options - {@link MutableAtomOptions}. * @returns * A reference to the atom created: a {@link MutableAtomToken} */ export function mutableAtom>( options: MutableAtomOptions, ): MutableAtomToken { return createMutableAtom(IMPLICIT.STORE, options, undefined) } /** * A function that runs side effects when the atom is set * @param tools - {@link Effectors} that can be used to run side effects * @returns * Optionally, a cleanup function that will be called when the atom is disposed */ export type AtomEffect = ( tools: Effectors, ) => Loadable<(() => void) | void> export type Effectors = { /** * Reset the value of the atom to its default */ resetSelf: () => void /** * Set the value of the atom * @param next - The new value of the atom, or a setter function */ setSelf: (next: New | ((old: T) => New)) => void /** Subscribe to changes to the atom */ onSet: (callback: (options: StateUpdate) => void) => void /** The token of the atom */ token: T extends Transceiver ? MutableAtomToken : AtomToken /** The store in which the atom exists */ store: Store } export type RegularAtomFamilyOptions = { /** The unique identifier of the atom family */ key: string /** The starting value of the atom family */ default: T | ((key: K) => T) /** Hooks used to run side effects when an atom in the family is set */ effects?: (key: K) => AtomEffect[] /** The classes of errors that might be thrown when deriving the atom's default value */ catch?: readonly Ctor[] } /** * Create a family of regular atoms, allowing for the dynamic creation and disposal of atoms. * @param options - {@link RegularAtomFamilyOptions} * @returns * A reference to the atom family created: a {@link RegularAtomFamilyToken} */ export function atomFamily( options: RegularAtomFamilyOptions, ): RegularAtomFamilyToken { return createRegularAtomFamily(IMPLICIT.STORE, options) } export type MutableAtomFamilyOptions< T extends Transceiver, K extends Canonical, > = { /** The unique identifier of the atom family */ key: string /** The class of the transceiver to be created */ class: ConstructorOf /** Hooks used to run side effects when an atom in the family is set */ effects?: (key: K) => AtomEffect[] } /** * Create a family of mutable atoms, allowing for the dynamic creation and disposal of atoms. * * The value of a mutable atom must be some kind of {@link Transceiver}. * * @param options - {@link MutableAtomFamilyOptions} * @returns * A reference to the atom family created: a {@link MutableAtomFamilyToken} */ export function mutableAtomFamily< T extends Transceiver, K extends Canonical, >(options: MutableAtomFamilyOptions): MutableAtomFamilyToken { return createMutableAtomFamily(IMPLICIT.STORE, options) }