(function(root,factory){ const api=factory(); if(typeof module==='object'&&module.exports)module.exports=api; root.BendFrameScheduler=api; })(typeof globalThis!=='undefined'?globalThis:this,function(){ 'use strict'; const DEFAULT_INTERVAL=1000/60; function createFrameScheduler(options={}){ const requestFrame=options.requestFrame||globalThis.requestAnimationFrame?.bind(globalThis); const cancelFrame=options.cancelFrame||globalThis.cancelAnimationFrame?.bind(globalThis); const setDelay=options.setDelay||globalThis.setTimeout?.bind(globalThis); const clearDelay=options.clearDelay||globalThis.clearTimeout?.bind(globalThis); const now=options.now||(()=>globalThis.performance?.now?.()||Date.now()); const interval=Math.max(1,Number(options.interval)||DEFAULT_INTERVAL); const tolerance=Math.max(0,Number(options.tolerance)||0); const watchdogDelay=Math.max(interval,Number(options.watchdogDelay)||interval+2); const commit=options.commit; const validTiming=typeof requestFrame==='function'&&typeof cancelFrame==='function' &&typeof setDelay==='function'&&typeof clearDelay==='function'; if(!validTiming)throw new TypeError('Frame scheduler timing functions are required'); if(typeof commit!=='function')throw new TypeError('Frame scheduler commit callback is required'); let frame=0,timer=0,lastCommitAt=0,latest=null,revision=0,committedRevision=0,disposed=false; const clearArmed=()=>{ if(frame)cancelFrame(frame); if(timer)clearDelay(timer); frame=0;timer=0; }; const arm=()=>{ if(disposed||frame||timer||latest==null)return false; const step=timestamp=>{ if(disposed||latest==null){clearArmed();return false} const at=Number.isFinite(timestamp)?timestamp:now(); if(lastCommitAt&&at+tolerance{ timer=0; if(typeof options.onWatchdog==='function')options.onWatchdog(); step(now()); },watchdogDelay); return true; }; const push=value=>{ if(disposed)return false; latest=value;revision++;arm();return revision; }; const flush=()=>{ if(disposed||latest==null)return false; clearArmed(); const value=latest,currentRevision=revision,at=now(); latest=null;lastCommitAt=at;committedRevision=currentRevision; commit(value,at,currentRevision); if(latest!=null)arm(); return true; }; const cancel=({resetCadence=false}={})=>{ clearArmed();latest=null; if(resetCadence)lastCommitAt=0; }; const dispose=()=>{cancel({resetCadence:true});disposed=true}; const inspect=()=>Object.freeze({ armed:Boolean(frame||timer), pending:latest!=null, revision, committedRevision, lastCommitAt }); return Object.freeze({push,flush,cancel,dispose,inspect}); } return Object.freeze({DEFAULT_INTERVAL,createFrameScheduler}); });