{"version":3,"file":"usePacedMutations.cjs","sources":["../../src/usePacedMutations.ts"],"sourcesContent":["import { useCallback, useMemo, useRef } from 'react'\nimport { createPacedMutations } from '@tanstack/db'\nimport type { PacedMutationsConfig, Transaction } from '@tanstack/db'\n\n/**\n * React hook for managing paced mutations with timing strategies.\n *\n * Provides optimistic mutations with pluggable strategies like debouncing,\n * queuing, or throttling. The optimistic updates are applied immediately via\n * `onMutate`, and the actual persistence is controlled by the strategy.\n *\n * @param config - Configuration including onMutate, mutationFn and strategy\n * @returns A mutate function that accepts variables and returns Transaction objects\n *\n * @example\n * ```tsx\n * // Debounced auto-save\n * function AutoSaveForm({ formId }: { formId: string }) {\n *   const mutate = usePacedMutations<string>({\n *     onMutate: (value) => {\n *       // Apply optimistic update immediately\n *       formCollection.update(formId, draft => {\n *         draft.content = value\n *       })\n *     },\n *     mutationFn: async ({ transaction }) => {\n *       await api.save(transaction.mutations)\n *     },\n *     strategy: debounceStrategy({ wait: 500 })\n *   })\n *\n *   const handleChange = async (value: string) => {\n *     const tx = mutate(value)\n *\n *     // Optional: await persistence or handle errors\n *     try {\n *       await tx.isPersisted.promise\n *       console.log('Saved!')\n *     } catch (error) {\n *       console.error('Save failed:', error)\n *     }\n *   }\n *\n *   return <textarea onChange={e => handleChange(e.target.value)} />\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Throttled slider updates\n * function VolumeSlider() {\n *   const mutate = usePacedMutations<number>({\n *     onMutate: (volume) => {\n *       settingsCollection.update('volume', draft => {\n *         draft.value = volume\n *       })\n *     },\n *     mutationFn: async ({ transaction }) => {\n *       await api.updateVolume(transaction.mutations)\n *     },\n *     strategy: throttleStrategy({ wait: 200 })\n *   })\n *\n *   return <input type=\"range\" onChange={e => mutate(+e.target.value)} />\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Debounce with leading/trailing for color picker (persist first + final only)\n * function ColorPicker() {\n *   const mutate = usePacedMutations<string>({\n *     onMutate: (color) => {\n *       themeCollection.update('primary', draft => {\n *         draft.color = color\n *       })\n *     },\n *     mutationFn: async ({ transaction }) => {\n *       await api.updateTheme(transaction.mutations)\n *     },\n *     strategy: debounceStrategy({ wait: 0, leading: true, trailing: true })\n *   })\n *\n *   return (\n *     <input\n *       type=\"color\"\n *       onChange={e => mutate(e.target.value)}\n *     />\n *   )\n * }\n * ```\n */\nexport function usePacedMutations<\n  TVariables = unknown,\n  T extends object = Record<string, unknown>,\n>(\n  config: PacedMutationsConfig<TVariables, T>,\n): (variables: TVariables) => Transaction<T> {\n  // Keep refs to the latest callbacks so we can call them without recreating the instance\n  const onMutateRef = useRef(config.onMutate)\n  onMutateRef.current = config.onMutate\n\n  const mutationFnRef = useRef(config.mutationFn)\n  mutationFnRef.current = config.mutationFn\n\n  // Create stable wrappers that always call the latest version\n  const stableOnMutate = useCallback<typeof config.onMutate>((variables) => {\n    return onMutateRef.current(variables)\n  }, [])\n\n  const stableMutationFn = useCallback<typeof config.mutationFn>((params) => {\n    return mutationFnRef.current(params)\n  }, [])\n\n  // Create paced mutations instance with proper dependency tracking\n  // Serialize strategy for stable comparison since strategy objects are recreated on each render\n  const mutate = useMemo(() => {\n    return createPacedMutations<TVariables, T>({\n      ...config,\n      onMutate: stableOnMutate,\n      mutationFn: stableMutationFn,\n    })\n  }, [\n    stableOnMutate,\n    stableMutationFn,\n    config.metadata,\n    // Serialize strategy to avoid recreating when object reference changes but values are same\n    JSON.stringify({\n      type: config.strategy._type,\n      options: config.strategy.options,\n    }),\n  ])\n\n  // Return stable mutate callback\n  const stableMutate = useCallback(mutate, [mutate])\n\n  return stableMutate\n}\n"],"names":["useRef","useCallback","useMemo","createPacedMutations"],"mappings":";;;;AA4FO,SAAS,kBAId,QAC2C;AAE3C,QAAM,cAAcA,MAAAA,OAAO,OAAO,QAAQ;AAC1C,cAAY,UAAU,OAAO;AAE7B,QAAM,gBAAgBA,MAAAA,OAAO,OAAO,UAAU;AAC9C,gBAAc,UAAU,OAAO;AAG/B,QAAM,iBAAiBC,kBAAoC,CAAC,cAAc;AACxE,WAAO,YAAY,QAAQ,SAAS;AAAA,EACtC,GAAG,CAAA,CAAE;AAEL,QAAM,mBAAmBA,kBAAsC,CAAC,WAAW;AACzE,WAAO,cAAc,QAAQ,MAAM;AAAA,EACrC,GAAG,CAAA,CAAE;AAIL,QAAM,SAASC,MAAAA,QAAQ,MAAM;AAC3B,WAAOC,wBAAoC;AAAA,MACzC,GAAG;AAAA,MACH,UAAU;AAAA,MACV,YAAY;AAAA,IAAA,CACb;AAAA,EACH,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA,OAAO;AAAA;AAAA,IAEP,KAAK,UAAU;AAAA,MACb,MAAM,OAAO,SAAS;AAAA,MACtB,SAAS,OAAO,SAAS;AAAA,IAAA,CAC1B;AAAA,EAAA,CACF;AAGD,QAAM,eAAeF,MAAAA,YAAY,QAAQ,CAAC,MAAM,CAAC;AAEjD,SAAO;AACT;;"}