{"version":3,"file":"useRateLimitedValue.cjs","names":["useRateLimitedState"],"sources":["../../src/rate-limiter/useRateLimitedValue.ts"],"sourcesContent":["import { useEffect } from 'react'\nimport { useRateLimitedState } from './useRateLimitedState'\nimport type {\n  ReactRateLimiter,\n  ReactRateLimiterOptions,\n} from './useRateLimiter'\nimport type { RateLimiterState } from '@tanstack/pacer/rate-limiter'\n\n/**\n * A high-level React hook that creates a rate-limited version of a value that updates at most a certain number of times within a time window.\n * This hook uses React's useState internally to manage the rate-limited state.\n *\n * Rate limiting is a simple \"hard limit\" approach - it allows all updates until the limit is reached, then blocks\n * subsequent updates until the window resets. Unlike throttling or debouncing, it does not attempt to space out\n * or intelligently collapse updates. This can lead to bursts of rapid updates followed by periods of no updates.\n *\n * The rate limiter supports two types of windows:\n * - 'fixed': A strict window that resets after the window period. All updates within the window count\n *   towards the limit, and the window resets completely after the period.\n * - 'sliding': A rolling window that allows updates as old ones expire. This provides a more\n *   consistent rate of updates over time.\n *\n * For smoother update patterns, consider:\n * - useThrottledValue: When you want consistent spacing between updates (e.g. UI changes)\n * - useDebouncedValue: When you want to collapse rapid updates into a single update (e.g. search input)\n *\n * Rate limiting should primarily be used when you need to enforce strict limits, like API rate limits.\n *\n * The hook returns a tuple containing:\n * - The rate-limited value that updates according to the configured rate limit\n * - The rate limiter instance with control methods\n *\n * For more direct control over rate limiting behavior without React state management,\n * consider using the lower-level useRateLimiter hook instead.\n *\n * ## State Management and Selector\n *\n * The hook uses TanStack Store for reactive state management via the underlying rate limiter instance.\n * The `selector` parameter allows you to specify which rate limiter state changes will trigger a re-render,\n * optimizing performance by preventing unnecessary re-renders when irrelevant state changes occur.\n *\n * **By default, there will be no reactive state subscriptions** and you must opt-in to state\n * tracking by providing a selector function. This prevents unnecessary re-renders and gives you\n * full control over when your component updates. Only when you provide a selector will the\n * component re-render when the selected state values change.\n *\n * Available rate limiter state properties:\n * - `executionCount`: Number of function executions that have been completed\n * - `executionTimes`: Array of timestamps when executions occurred for rate limiting calculations\n * - `rejectionCount`: Number of function executions that have been rejected due to rate limiting\n *\n * @example\n * ```tsx\n * // Default behavior - no reactive state subscriptions\n * const [rateLimitedValue, rateLimiter] = useRateLimitedValue(rawValue, {\n *   limit: 5,\n *   window: 60000,\n *   windowType: 'sliding'\n * });\n *\n * // Opt-in to re-render when execution count changes (optimized for tracking successful updates)\n * const [rateLimitedValue, rateLimiter] = useRateLimitedValue(\n *   rawValue,\n *   { limit: 5, window: 60000, windowType: 'sliding' },\n *   (state) => ({ executionCount: state.executionCount })\n * );\n *\n * // Opt-in to re-render when rejection count changes (optimized for tracking rate limit violations)\n * const [rateLimitedValue, rateLimiter] = useRateLimitedValue(\n *   rawValue,\n *   { limit: 5, window: 60000, windowType: 'sliding' },\n *   (state) => ({ rejectionCount: state.rejectionCount })\n * );\n *\n * // Opt-in to re-render when execution times change (optimized for window calculations)\n * const [rateLimitedValue, rateLimiter] = useRateLimitedValue(\n *   rawValue,\n *   { limit: 5, window: 60000, windowType: 'sliding' },\n *   (state) => ({ executionTimes: state.executionTimes })\n * );\n *\n * // With rejection callback and fixed window\n * const [rateLimitedValue, rateLimiter] = useRateLimitedValue(rawValue, {\n *   limit: 3,\n *   window: 5000,\n *   windowType: 'fixed',\n *   onReject: (rateLimiter) => {\n *     console.log(`Update rejected. Try again in ${rateLimiter.getMsUntilNextWindow()}ms`);\n *   }\n * });\n *\n * // Access the selected rate limiter state (will be empty object {} unless selector provided)\n * const { executionCount, rejectionCount } = rateLimiter.state;\n * ```\n */\nexport function useRateLimitedValue<TValue, TSelected = RateLimiterState>(\n  value: TValue,\n  options: ReactRateLimiterOptions<\n    React.Dispatch<React.SetStateAction<TValue>>,\n    TSelected\n  >,\n  selector?: (state: RateLimiterState) => TSelected,\n): [\n  TValue,\n  ReactRateLimiter<React.Dispatch<React.SetStateAction<TValue>>, TSelected>,\n] {\n  const [rateLimitedValue, setRateLimitedValue, rateLimiter] =\n    useRateLimitedState(value, options, selector)\n\n  useEffect(() => {\n    setRateLimitedValue(value)\n  }, [value, setRateLimitedValue])\n\n  return [rateLimitedValue, rateLimiter]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+FA,SAAgB,oBACd,OACA,SAIA,UAIA;CACA,MAAM,CAAC,kBAAkB,qBAAqB,eAC5CA,gDAAoB,OAAO,SAAS,SAAS;AAE/C,4BAAgB;AACd,sBAAoB,MAAM;IACzB,CAAC,OAAO,oBAAoB,CAAC;AAEhC,QAAO,CAAC,kBAAkB,YAAY"}