{"version":3,"file":"useQueuer.cjs","names":["useDefaultPacerOptions","Queuer","shallow"],"sources":["../../src/queuer/useQueuer.ts"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { Queuer } from '@tanstack/pacer/queuer'\nimport { shallow, useSelector } from '@tanstack/react-store'\nimport { useDefaultPacerOptions } from '../provider/PacerProvider'\nimport type { Store } from '@tanstack/react-store'\nimport type { QueuerOptions, QueuerState } from '@tanstack/pacer/queuer'\nimport type { FunctionComponent, ReactNode } from 'react'\n\nexport interface ReactQueuerOptions<\n  TValue,\n  TSelected = {},\n> extends QueuerOptions<TValue> {\n  /**\n   * Optional callback invoked when the component unmounts. Receives the queuer instance.\n   * When provided, replaces the default cleanup (stop); use it to call flush(), flushAsBatch(), stop(), add logging, etc.\n   */\n  onUnmount?: (queuer: ReactQueuer<TValue, TSelected>) => void\n}\n\nexport interface ReactQueuer<TValue, TSelected = {}> extends Omit<\n  Queuer<TValue>,\n  'store'\n> {\n  /**\n   * A React HOC (Higher Order Component) that allows you to subscribe to the queuer state.\n   *\n   * This is useful for opting into state re-renders for specific parts of the queuer state\n   * deep in your component tree without needing to pass a selector to the hook.\n   *\n   * @example\n   * <queuer.Subscribe selector={(state) => ({ size: state.size, isRunning: state.isRunning })}>\n   *   {({ size, isRunning }) => (\n   *     <div>Queue: {size} items, {isRunning ? 'Processing' : 'Idle'}</div>\n   *   )}\n   * </queuer.Subscribe>\n   */\n  Subscribe: <TSelected>(props: {\n    selector: (state: QueuerState<TValue>) => TSelected\n    children: ((state: TSelected) => ReactNode) | ReactNode\n  }) => ReturnType<FunctionComponent>\n  /**\n   * Reactive state that will be updated and re-rendered when the queuer state changes\n   *\n   * Use this instead of `queuer.store.state`\n   */\n  readonly state: Readonly<TSelected>\n  /**\n   * @deprecated Use `queuer.state` instead of `queuer.store.state` if you want to read reactive state.\n   * The state on the store object is not reactive, as it has not been wrapped in a `useSelector` hook internally.\n   * Although, you can make the state reactive by using the `useSelector` in your own usage.\n   */\n  readonly store: Store<Readonly<QueuerState<TValue>>>\n}\n\n/**\n * A React hook that creates and manages a Queuer instance.\n *\n * This is a lower-level hook that provides direct access to the Queuer's functionality without\n * any built-in state management. This allows you to integrate it with any state management solution\n * you prefer (useState, Redux, Zustand, etc.) by utilizing the onItemsChange callback.\n *\n * For a hook with built-in state management, see useQueuedState.\n *\n * The Queuer extends the base Queue to add processing capabilities. Items are processed\n * synchronously in order, with optional delays between processing each item. The queuer includes\n * an internal tick mechanism that can be started and stopped, making it useful as a scheduler.\n * When started, it will process one item per tick, with an optional wait time between ticks.\n *\n * By default uses FIFO (First In First Out) behavior, but can be configured for LIFO\n * (Last In First Out) by specifying 'front' position when adding items.\n *\n * ## State Management and Selector\n *\n * The hook uses TanStack Store for reactive state management. You can subscribe to state changes\n * in two ways:\n *\n * **1. Using `queuer.Subscribe` HOC (Recommended for component tree subscriptions)**\n *\n * Use the `Subscribe` HOC to subscribe to state changes deep in your component tree without\n * needing to pass a selector to the hook. This is ideal when you want to subscribe to state\n * in child components.\n *\n * **2. Using the `selector` parameter (For hook-level subscriptions)**\n *\n * The `selector` parameter allows you to specify which state changes will trigger a re-render\n * at the hook level, optimizing performance by preventing unnecessary re-renders when irrelevant\n * 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 or using the `Subscribe` HOC. This prevents unnecessary\n * re-renders and gives you full control over when your component updates.\n *\n * Available state properties:\n * - `executionCount`: Number of items that have been processed by the queuer\n * - `expirationCount`: Number of items that have been removed due to expiration\n * - `isEmpty`: Whether the queuer has no items to process\n * - `isFull`: Whether the queuer has reached its maximum capacity\n * - `isIdle`: Whether the queuer is not currently processing any items\n * - `isRunning`: Whether the queuer is active and will process items automatically\n * - `items`: Array of items currently waiting to be processed\n * - `itemTimestamps`: Timestamps when items were added for expiration tracking\n * - `pendingTick`: Whether the queuer has a pending timeout for processing the next item\n * - `rejectionCount`: Number of items that have been rejected from being added\n * - `size`: Number of items currently in the queue\n * - `status`: Current processing status ('idle' | 'running' | 'stopped')\n *\n * ## Unmount behavior\n *\n * By default, the hook stops the queuer when the component unmounts.\n * Use the `onUnmount` option to customize this. For example, to flush pending items instead:\n *\n * ```tsx\n * const queue = useQueuer(fn, {\n *   started: true,\n *   wait: 1000,\n *   onUnmount: (q) => q.flush()\n * });\n * ```\n *\n * @example\n * ```tsx\n * // Default behavior - no reactive state subscriptions\n * const queue = useQueuer(\n *   (item) => console.log('Processing:', item),\n *   { started: true, wait: 1000 }\n * );\n *\n * // Subscribe to state changes deep in component tree using Subscribe HOC\n * <queue.Subscribe selector={(state) => ({ size: state.size, isRunning: state.isRunning })}>\n *   {({ size, isRunning }) => (\n *     <div>Queue: {size} items, {isRunning ? 'Processing' : 'Idle'}</div>\n *   )}\n * </queue.Subscribe>\n *\n * // Opt-in to re-render when queue size changes at hook level (optimized for displaying queue length)\n * const queue = useQueuer(\n *   (item) => console.log('Processing:', item),\n *   { started: true, wait: 1000 },\n *   (state) => ({\n *     size: state.size,\n *     isEmpty: state.isEmpty,\n *     isFull: state.isFull\n *   })\n * );\n *\n * // Opt-in to re-render when processing state changes (optimized for loading indicators)\n * const queue = useQueuer(\n *   (item) => console.log('Processing:', item),\n *   { started: true, wait: 1000 },\n *   (state) => ({\n *     isRunning: state.isRunning,\n *     isIdle: state.isIdle,\n *     status: state.status,\n *     pendingTick: state.pendingTick\n *   })\n * );\n *\n * // Opt-in to re-render when execution metrics change (optimized for stats display)\n * const queue = useQueuer(\n *   (item) => console.log('Processing:', item),\n *   { started: true, wait: 1000 },\n *   (state) => ({\n *     executionCount: state.executionCount,\n *     expirationCount: state.expirationCount,\n *     rejectionCount: state.rejectionCount\n *   })\n * );\n *\n * // Example with custom state management and scheduling\n * const [items, setItems] = useState([]);\n *\n * const queue = useQueuer(\n *   (item) => console.log('Processing:', item),\n *   {\n *     started: true, // Start processing immediately\n *     wait: 1000,    // Process one item every second\n *     onItemsChange: (queue) => setItems(queue.peekAllItems()),\n *     getPriority: (item) => item.priority // Process higher priority items first\n *   }\n * );\n *\n * // Add items to process - they'll be handled automatically\n * queue.addItem('task1');\n * queue.addItem('task2');\n *\n * // Control the scheduler\n * queue.stop();  // Pause processing\n * queue.start(); // Resume processing\n *\n * // Access the selected state (will be empty object {} unless selector provided)\n * const { size, isRunning, executionCount } = queue.state;\n * ```\n */\nexport function useQueuer<TValue, TSelected = {}>(\n  fn: (item: TValue) => void,\n  options: ReactQueuerOptions<TValue, TSelected> = {},\n  selector: (state: QueuerState<TValue>) => TSelected = () => ({}) as TSelected,\n): ReactQueuer<TValue, TSelected> {\n  const mergedOptions = {\n    ...useDefaultPacerOptions().queuer,\n    ...options,\n  } as ReactQueuerOptions<TValue, TSelected>\n  const [queuer] = useState(() => {\n    const queuerInstance = new Queuer<TValue>(\n      fn,\n      mergedOptions,\n    ) as unknown as ReactQueuer<TValue, TSelected>\n\n    /* eslint-disable-next-line @eslint-react/component-hook-factories -- Subscribe attached once in useState lazy init; stable per instance */\n    queuerInstance.Subscribe = function Subscribe<TSelected>(props: {\n      selector: (state: QueuerState<TValue>) => TSelected\n      children: ((state: TSelected) => ReactNode) | ReactNode\n    }) {\n      const selected = useSelector(queuerInstance.store, props.selector, {\n        compare: shallow,\n      })\n\n      return typeof props.children === 'function'\n        ? props.children(selected)\n        : props.children\n    }\n\n    return queuerInstance\n  })\n\n  queuer.fn = fn\n  queuer.setOptions(mergedOptions)\n\n  /* eslint-disable react-hooks/exhaustive-deps, @eslint-react/exhaustive-deps, react-compiler/react-compiler -- unmount cleanup only; empty deps keep teardown stable */\n  useEffect(() => {\n    return () => {\n      if (mergedOptions.onUnmount) {\n        mergedOptions.onUnmount(queuer)\n      } else {\n        queuer.stop()\n      }\n    }\n  }, [])\n  /* eslint-enable react-hooks/exhaustive-deps, @eslint-react/exhaustive-deps, react-compiler/react-compiler */\n\n  const state = useSelector(queuer.store, selector, { compare: shallow })\n\n  return useMemo(\n    () =>\n      ({\n        ...queuer,\n        state,\n      }) as ReactQueuer<TValue, TSelected>, // omit `store` in favor of `state`\n    [queuer, state],\n  )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiMA,SAAgB,UACd,IACA,UAAiD,EAAE,EACnD,kBAA6D,EAAE,GAC/B;CAChC,MAAM,gBAAgB;EACpB,GAAGA,8CAAwB,CAAC;EAC5B,GAAG;EACJ;CACD,MAAM,CAAC,oCAAyB;EAC9B,MAAM,iBAAiB,IAAIC,8BACzB,IACA,cACD;AAGD,iBAAe,YAAY,SAAS,UAAqB,OAGtD;GACD,MAAM,kDAAuB,eAAe,OAAO,MAAM,UAAU,EACjE,SAASC,+BACV,CAAC;AAEF,UAAO,OAAO,MAAM,aAAa,aAC7B,MAAM,SAAS,SAAS,GACxB,MAAM;;AAGZ,SAAO;GACP;AAEF,QAAO,KAAK;AACZ,QAAO,WAAW,cAAc;AAGhC,4BAAgB;AACd,eAAa;AACX,OAAI,cAAc,UAChB,eAAc,UAAU,OAAO;OAE/B,QAAO,MAAM;;IAGhB,EAAE,CAAC;CAGN,MAAM,+CAAoB,OAAO,OAAO,UAAU,EAAE,SAASA,+BAAS,CAAC;AAEvE,kCAEK;EACC,GAAG;EACH;EACD,GACH,CAAC,QAAQ,MAAM,CAChB"}