UNPKG

my-utils-kit

Version:

A lightweight and type-safe utility library for working with strings, objects, array Performance methods in TypeScript. Includes helpful methods for deep cloning, object transformations, safe access, query string handling, and more — designed for modern J

182 lines (181 loc) 5.54 kB
export function debounce(fn, delay, immediate = false) { let timeout; return function (...args) { const context = this; const callNow = immediate && !timeout; if (timeout) clearTimeout(timeout); timeout = setTimeout(() => { timeout = null; if (!immediate) fn.apply(context, args); }, delay); if (callNow) fn.apply(context, args); }; } export function throttle(fn, delay, immediate = false) { let timer = null; let lastArgs = null; return function (...args) { const context = this; if (!timer) { if (immediate) { fn.apply(context, args); } else { lastArgs = args; } timer = setTimeout(() => { if (!immediate && lastArgs) { fn.apply(context, lastArgs); lastArgs = null; } timer = null; }, delay); } }; } export function memoize(fn) { const cache = new Map(); return function (...args) { const key = JSON.stringify(args); if (cache.has(key)) { console.log("Returning from cache:", key); return cache.get(key); } const result = fn.apply(this, args); cache.set(key, result); console.log("Calculating new result:", key); return result; }; } export const asyncMemoize = async (fn) => { const cache = new Map(); return async function (...args) { const key = JSON.stringify(args); if (cache.has(key)) { return cache.get(key); } const result = await fn(...args); cache.set(key, result); return result; }; }; export class OperationBatcher { constructor() { this.operations = []; this.executing = false; } enqueueOperation(fn) { this.operations.push(fn); if (!this.executing) { this.execute(); } } async execute() { this.executing = true; while (this.operations.length > 0) { const operation = this.operations.shift(); if (operation) { try { await operation(); } catch (err) { console.error("Operation failed", err); } } } this.executing = false; } } export function runCallbackOnUserEvent(callback, options) { if (typeof callback !== "function") { throw new Error("Callback must be a function"); } const { events = ["mousemove", "scroll", "touchstart"], timeout } = options || {}; let executed = false; function runOnce() { if (executed) return; executed = true; for (const event of events) { document.removeEventListener(event, runOnce); } callback(); } for (const event of events) { document.addEventListener(event, runOnce, { once: true, passive: true }); } if (typeof timeout === "number" && timeout > 0) { setTimeout(runOnce, timeout); } } export function loadScriptOnUserEvent(src, options) { if (typeof src !== "string" || !src.trim()) { throw new Error("Script source must be a non-empty string"); } const { events = ["mousemove", "scroll", "touchstart"], timeout } = options || {}; let executed = false; function loadScript() { if (executed) return; executed = true; for (const event of events) { document.removeEventListener(event, loadScript); } const script = document.createElement("script"); script.src = src; script.async = true; document.head.appendChild(script); } for (const event of events) { document.addEventListener(event, loadScript, { once: true, passive: true }); } if (typeof timeout === "number" && timeout > 0) { setTimeout(loadScript, timeout); } } export function observeElementOnIntersect(selector, options, callback) { if (typeof selector !== "string") { throw new Error("Selector must be a string"); } const elements = document.querySelectorAll(selector); if (!elements.length) return; const observer = new IntersectionObserver((entries, obs) => { for (const entry of entries) { if (entry.isIntersecting) { callback(entry); obs.unobserve(entry.target); } } }, options); elements.forEach((el) => observer.observe(el)); } export function getScreenSize(ranges = { xs: { min: 0, max: 480 }, sm: { min: 481, max: 640 }, md: { min: 641, max: 768 }, lg: { min: 769, max: 1024 }, xl: { min: 1025, max: 1280 }, "2xl": { min: 1281, max: 1536 }, "3xl": { min: 1537, max: Infinity } }) { const width = window.innerWidth; for (const [label, { min, max }] of Object.entries(ranges)) { if (width >= min && width <= max) { return label; } } return undefined; // fallback } export function watchScreenSize(callback, ranges) { function handler() { const size = getScreenSize(ranges || undefined); callback(size); } window.addEventListener('resize', handler); handler(); // Call immediately on setup return () => window.removeEventListener('resize', handler); }