{"version":3,"file":"functions.cjs","names":[],"sources":["../../src/utils/functions.ts"],"sourcesContent":["/**\n * Create a trailing-edge debounced version of `fn`.\n *\n * The wrapped function delays invoking `fn` until `wait` milliseconds have\n * elapsed since the last time it was called. Only the latest arguments are\n * used. Call `.cancel()` to clear any pending invocation.\n *\n * @example\n * const save = debounce((q: string) => search(q), 300);\n * save(\"a\"); save(\"ab\"); save(\"abc\"); // only \"abc\" runs after 300ms\n * save.cancel();                       // nothing runs\n */\nexport function debounce<A extends unknown[]>(\n    fn: (...args: A) => void,\n    wait: number,\n): ((...args: A) => void) & { cancel: () => void } {\n    let timer: ReturnType<typeof setTimeout> | undefined;\n\n    const debounced = (...args: A): void => {\n        if (timer !== undefined) clearTimeout(timer);\n        timer = setTimeout(() => {\n            timer = undefined;\n            fn(...args);\n        }, wait);\n    };\n\n    debounced.cancel = (): void => {\n        if (timer !== undefined) {\n            clearTimeout(timer);\n            timer = undefined;\n        }\n    };\n\n    return debounced;\n}\n\n/**\n * Create a throttled version of `fn` with leading and trailing edges.\n *\n * `fn` runs immediately on the first call (leading edge), then at most once\n * per `wait` milliseconds. If calls happen during the wait window, the last\n * one fires on the trailing edge. Call `.cancel()` to drop any pending\n * trailing call and reset the window.\n *\n * @example\n * const onScroll = throttle(() => render(), 200);\n * window.addEventListener(\"scroll\", onScroll);\n * onScroll.cancel();\n */\nexport function throttle<A extends unknown[]>(\n    fn: (...args: A) => void,\n    wait: number,\n): ((...args: A) => void) & { cancel: () => void } {\n    let timer: ReturnType<typeof setTimeout> | undefined;\n    let lastArgs: A | undefined;\n    let lastInvoke = 0;\n\n    const invoke = (args: A): void => {\n        lastInvoke = Date.now();\n        fn(...args);\n    };\n\n    const throttled = (...args: A): void => {\n        const now = Date.now();\n        const remaining = wait - (now - lastInvoke);\n\n        if (remaining <= 0) {\n            if (timer !== undefined) {\n                clearTimeout(timer);\n                timer = undefined;\n            }\n            invoke(args);\n        } else {\n            lastArgs = args;\n            if (timer === undefined) {\n                timer = setTimeout(() => {\n                    timer = undefined;\n                    if (lastArgs !== undefined) {\n                        const pending = lastArgs;\n                        lastArgs = undefined;\n                        invoke(pending);\n                    }\n                }, remaining);\n            }\n        }\n    };\n\n    throttled.cancel = (): void => {\n        if (timer !== undefined) {\n            clearTimeout(timer);\n            timer = undefined;\n        }\n        lastArgs = undefined;\n        lastInvoke = 0;\n    };\n\n    return throttled;\n}\n\n/**\n * Wrap `fn` so it runs at most once; subsequent calls return the cached result.\n *\n * @example\n * const init = once(() => expensiveSetup());\n * init(); // runs expensiveSetup()\n * init(); // returns the same cached result, no re-run\n */\nexport function once<A extends unknown[], R>(fn: (...args: A) => R): (...args: A) => R {\n    let called = false;\n    let result: R;\n\n    return (...args: A): R => {\n        if (!called) {\n            called = true;\n            result = fn(...args);\n        }\n        return result;\n    };\n}\n\n/**\n * Memoize only the most recent call of `fn`, keyed by shallow-equal arguments.\n *\n * If the next call has the same arguments (compared with `Object.is` per\n * position and equal length), the cached result is returned without re-running\n * `fn`. Any different argument list recomputes and replaces the cache.\n *\n * @example\n * const select = memoizeOne((a: number, b: number) => a + b);\n * select(1, 2); // computes 3\n * select(1, 2); // cached 3\n * select(2, 2); // recomputes 4\n */\nexport function memoizeOne<A extends unknown[], R>(fn: (...args: A) => R): (...args: A) => R {\n    let hasCache = false;\n    let lastArgs: A;\n    let lastResult: R;\n\n    const sameArgs = (next: A): boolean => {\n        if (!hasCache || next.length !== lastArgs.length) return false;\n        for (let i = 0; i < next.length; i++) {\n            if (!Object.is(next[i], lastArgs[i])) return false;\n        }\n        return true;\n    };\n\n    return (...args: A): R => {\n        if (sameArgs(args)) return lastResult;\n        lastArgs = args;\n        lastResult = fn(...args);\n        hasCache = true;\n        return lastResult;\n    };\n}\n"],"mappings":"AAYA,SAAgB,EACZ,EACA,EAC+C,CAC/C,IAAI,EAEE,GAAa,GAAG,IAAkB,CAChC,IAAU,IAAA,IAAW,aAAa,CAAK,EAC3C,EAAQ,eAAiB,CACrB,EAAQ,IAAA,GACR,EAAG,GAAG,CAAI,CACd,EAAG,CAAI,CACX,EASA,MAPA,GAAU,WAAqB,CACvB,IAAU,IAAA,KACV,aAAa,CAAK,EAClB,EAAQ,IAAA,GAEhB,EAEO,CACX,CAeA,SAAgB,EACZ,EACA,EAC+C,CAC/C,IAAI,EACA,EACA,EAAa,EAEX,EAAU,GAAkB,CAC9B,EAAa,KAAK,IAAI,EACtB,EAAG,GAAG,CAAI,CACd,EAEM,GAAa,GAAG,IAAkB,CAEpC,IAAM,EAAY,GADN,KAAK,IACS,EAAM,GAE5B,GAAa,GACT,IAAU,IAAA,KACV,aAAa,CAAK,EAClB,EAAQ,IAAA,IAEZ,EAAO,CAAI,IAEX,EAAW,EACP,IAAU,IAAA,KACV,EAAQ,eAAiB,CAErB,GADA,EAAQ,IAAA,GACJ,IAAa,IAAA,GAAW,CACxB,IAAM,EAAU,EAChB,EAAW,IAAA,GACX,EAAO,CAAO,CAClB,CACJ,EAAG,CAAS,GAGxB,EAWA,MATA,GAAU,WAAqB,CACvB,IAAU,IAAA,KACV,aAAa,CAAK,EAClB,EAAQ,IAAA,IAEZ,EAAW,IAAA,GACX,EAAa,CACjB,EAEO,CACX,CAUA,SAAgB,EAA6B,EAA0C,CACnF,IAAI,EAAS,GACT,EAEJ,OAAQ,GAAG,KACF,IACD,EAAS,GACT,EAAS,EAAG,GAAG,CAAI,GAEhB,EAEf,CAeA,SAAgB,EAAmC,EAA0C,CACzF,IAAI,EAAW,GACX,EACA,EAEE,EAAY,GAAqB,CACnC,GAAI,CAAC,GAAY,EAAK,SAAW,EAAS,OAAQ,MAAO,GACzD,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAC7B,GAAI,CAAC,OAAO,GAAG,EAAK,GAAI,EAAS,EAAE,EAAG,MAAO,GAEjD,MAAO,EACX,EAEA,OAAQ,GAAG,IACH,EAAS,CAAI,EAAU,GAC3B,EAAW,EACX,EAAa,EAAG,GAAG,CAAI,EACvB,EAAW,GACJ,EAEf"}