{"version":3,"sources":["../src/index.ts","../src/rv.ts","../src/use-rv.ts"],"sourcesContent":["// Copyright (c) rasulomaroff. All rights reserved. Licensed under the MIT license.\n\nexport { rv } from './rv'\nexport { useRv } from './use-rv'\n\nexport type * from './types'\n","import type { CleanupFn, EqualFn, Listener, Rv, RvInitOptions, RvOptions } from './types'\n\nconst defaultEq = <T>(oldValue: T, newValue: T): boolean => oldValue === newValue\n\n/**\n * Creates a reactive variable (RV), allowing value retrieval, updates, and subscriptions.\n *\n * @template T The type of the stored value.\n *\n * @param val The initial value of the reactive variable.\n * @param options Optional configuration for the reactive variable.\n *\n * @returns A reactive variable function that allows getting, setting, and listening for updates.\n *\n * @example\n * ```ts\n * // initialize a state variable with initial value set to 0\n * const positiveVar = rv(0, {\n *     // all options are optional\n *\n *     // define custom `eq` function that will be run on every value set to determine\n *     // whether or not value is going to be updated\n *     eq: (oldValue, newValue) => newValue > oldValue && newValue >= 0,\n *\n *     // define callback that's going to be run on every change\n *     on: (newValue, oldValue) => {}\n * })\n *\n * // alternatively, there's a handy function initializer\n * // all options are identical\n * const positiveVar = rv.fn(() => 0)\n *\n * // call variable function with no arguments to get its current value\n * const currentValue = positiveVar()\n *\n * // call variable function passing an argument in order to set it\n * // Won't trigger an update because the values are \"equal\" under this custom rule.\n * positiveVar(-3, {\n *     // override the initial `eq` function for this update call.\n *     eq: (oldValue, newValue) => newValue > oldValue\n *     // additionally, you can disable initial `eq` function by passing `false` here\n *     // it will use a default `eq` function which is just a strict check: `===`\n *     eq: false // in this case, update WILL happen\n * })\n *\n * // you can also subscribe to value without using any hooks\n * const unsubscribe = positiveVar.on((newValue, oldValue) => console.log(newValue, oldValue))\n *\n * positiveVar(4) // logs: 4\n *\n * unsubscribe()\n *\n * positiveVar(5) // there will be no logs\n * ```\n */\nexport function rv<T>(val: T, options?: RvInitOptions<T>): Rv<T> {\n    const { eq = defaultEq, on } = options ?? <RvInitOptions<T>>{}\n\n    const listeners = new Set<Listener<T>>()\n\n    if (on) listeners.add(on)\n\n    const fn: Rv<T> = (...args: [] | [newValue: T, options?: RvOptions<T>]): T => {\n        if (args.length === 0) return val\n\n        const [newValue, options] = args\n\n        let eqfn: EqualFn<T> = eq\n\n        if (typeof options?.eq !== 'undefined') {\n            eqfn = options.eq === false ? defaultEq : options.eq\n        }\n\n        if (eqfn(val, newValue)) return val\n\n        const oldValue = val\n        val = newValue\n\n        listeners.forEach(cb => cb(newValue, oldValue))\n\n        return val\n    }\n\n    fn.on = (listener): CleanupFn => {\n        listeners.add(listener)\n\n        return () => {\n            listeners.delete(listener)\n        }\n    }\n\n    return fn\n}\n\n/**\n * Creates a reactive variable from an initializer function.\n * The function is immediately executed to determine the initial value.\n *\n * @template T The type of the stored value.\n * @param init A function that returns the initial value.\n * @param options Optional configuration for equality comparison and event listeners.\n *\n * @returns A reactive variable function.\n */\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nrv.fn = <T>(init: () => T, options?: RvInitOptions<T>) => rv(init(), options)\n","// using this package to support all react versions starting from 16.8 where hooks were just introduced\nimport { useSyncExternalStore } from 'use-sync-external-store/shim'\n\nimport type { Rv } from './types'\n\n/**\n * Subscribes to a reactive variable and provides its current value,\n * updating the state when the variable is updated.\n *\n * @template T The type of the reactive variable's value.\n * @param rv The reactive variable to subscribe to.\n *\n * @returns The current value of the reactive variable.\n *\n * @example\n * ```tsx\n * import React from 'react'\n * import { rv, useRv } from 'react-rv'\n *\n * const counter = rv(0)\n *\n * const Counter = () => {\n *     const value = useRv(counter)\n *     return (\n *         <div>\n *             <p>Count: {value}</p>\n *             <button onClick={() => counter(value + 1)}>Increment</button>\n *         </div>\n *     )\n * }\n * ```\n */\nexport const useRv = <T>(rv: Rv<T>): T => useSyncExternalStore(rv.on, rv, rv)\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,QAAAE,EAAA,UAAAC,IAAA,eAAAC,EAAAJ,GCEA,IAAMK,EAAY,CAAIC,EAAaC,IAAyBD,IAAaC,EAqDlE,SAASC,EAAMC,EAAQC,EAAmC,CAC7D,GAAM,CAAE,GAAAC,EAAKN,EAAW,GAAAO,CAAG,EAAIF,GAA6B,CAAC,EAEvDG,EAAY,IAAI,IAElBD,GAAIC,EAAU,IAAID,CAAE,EAExB,IAAME,EAAY,IAAIC,IAAwD,CAC1E,GAAIA,EAAK,SAAW,EAAG,OAAON,EAE9B,GAAM,CAACF,EAAUG,CAAO,EAAIK,EAExBC,EAAmBL,EAMvB,GAJI,OAAOD,GAAS,GAAO,MACvBM,EAAON,EAAQ,KAAO,GAAQL,EAAYK,EAAQ,IAGlDM,EAAKP,EAAKF,CAAQ,EAAG,OAAOE,EAEhC,IAAMH,EAAWG,EACjB,OAAAA,EAAMF,EAENM,EAAU,QAAQI,GAAMA,EAAGV,EAAUD,CAAQ,CAAC,EAEvCG,CACX,EAEA,OAAAK,EAAG,GAAMI,IACLL,EAAU,IAAIK,CAAQ,EAEf,IAAM,CACTL,EAAU,OAAOK,CAAQ,CAC7B,GAGGJ,CACX,CAaAN,EAAG,GAAK,CAAIW,EAAeT,IAA+BF,EAAGW,EAAK,EAAGT,CAAO,ECxG5E,IAAAU,EAAqC,wCA+BxBC,EAAYC,MAAiB,wBAAqBA,EAAG,GAAIA,EAAIA,CAAE","names":["index_exports","__export","rv","useRv","__toCommonJS","defaultEq","oldValue","newValue","rv","val","options","eq","on","listeners","fn","args","eqfn","cb","listener","init","import_shim","useRv","rv"]}