@crup/react-timer-hook 0.0.1-alpha.14 → 0.0.1-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,11 +20,11 @@ Timers get messy when a product needs pause and resume, countdowns tied to serve
20
20
  `@crup/react-timer-hook` keeps the default import small and lets you add only the pieces your screen needs:
21
21
 
22
22
  - ⏱️ `useTimer()` from the root package for one lifecycle: stopwatch, countdown, clock, or custom flow.
23
- - 🔋 Add-ons are opt-in: schedules, timer groups, duration helpers, and diagnostics live in subpath imports.
23
+ - 🔋 Add schedules, timer groups, duration helpers, and diagnostics only when a screen needs them.
24
24
  - 🧭 `useTimerGroup()` from `/group` for many keyed lifecycles with one shared scheduler.
25
25
  - 📡 `useScheduledTimer()` from `/schedules` for polling and timing context.
26
26
  - 🧩 `durationParts()` from `/duration` for common display math.
27
- - 🧪 Tested for React Strict Mode, rerenders, async callbacks, cleanup, and multi-timer screens.
27
+ - 🧪 Covered for rerenders, React Strict Mode, async callbacks, cleanup, and multi-timer screens.
28
28
  - 🤖 AI-ready docs are available through hosted `llms.txt`, `llms-full.txt`, and an optional MCP docs helper.
29
29
 
30
30
  ## Install
@@ -51,6 +51,22 @@ Each recipe has a live playground and a focused code sample:
51
51
  - Intermediate: [once-only onEnd](https://crup.github.io/react-timer-hook/recipes/intermediate/once-only-on-end/), [polling schedule](https://crup.github.io/react-timer-hook/recipes/intermediate/polling-schedule/), [poll and cancel](https://crup.github.io/react-timer-hook/recipes/intermediate/poll-and-cancel/), [backend event stop](https://crup.github.io/react-timer-hook/recipes/intermediate/backend-event-stop/), [diagnostics](https://crup.github.io/react-timer-hook/recipes/intermediate/debug-logs/)
52
52
  - Advanced: [many display countdowns](https://crup.github.io/react-timer-hook/recipes/advanced/many-display-countdowns/), [timer group](https://crup.github.io/react-timer-hook/recipes/advanced/timer-group/), [group controls](https://crup.github.io/react-timer-hook/recipes/advanced/group-controls/), [per-item polling](https://crup.github.io/react-timer-hook/recipes/advanced/per-item-polling/), [dynamic items](https://crup.github.io/react-timer-hook/recipes/advanced/dynamic-items/)
53
53
 
54
+ ## Use cases
55
+
56
+ | Product case | Use | Import | Recipe |
57
+ | --- | --- | --- | --- |
58
+ | Stopwatch, call timer, workout timer | Core | `@crup/react-timer-hook` | [Stopwatch](https://crup.github.io/react-timer-hook/recipes/basic/stopwatch/) |
59
+ | Wall clock or "last updated" display | Core | `@crup/react-timer-hook` | [Wall clock](https://crup.github.io/react-timer-hook/recipes/basic/wall-clock/) |
60
+ | Auction, reservation, or job deadline | Core | `@crup/react-timer-hook` | [Absolute countdown](https://crup.github.io/react-timer-hook/recipes/basic/absolute-countdown/) |
61
+ | Focus timer or checkout hold that pauses | Core + duration | `@crup/react-timer-hook` + `/duration` | [Pausable countdown](https://crup.github.io/react-timer-hook/recipes/basic/pausable-countdown/) |
62
+ | Backend status polling | Schedules | `@crup/react-timer-hook/schedules` | [Polling schedule](https://crup.github.io/react-timer-hook/recipes/intermediate/polling-schedule/) |
63
+ | Polling that can close early | Schedules | `@crup/react-timer-hook/schedules` | [Poll and cancel](https://crup.github.io/react-timer-hook/recipes/intermediate/poll-and-cancel/) |
64
+ | Auction list with independent row controls | Timer group | `@crup/react-timer-hook/group` | [Timer group](https://crup.github.io/react-timer-hook/recipes/advanced/timer-group/) |
65
+ | Upload/job dashboard with per-row polling | Timer group + schedules | `@crup/react-timer-hook/group` | [Per-item polling](https://crup.github.io/react-timer-hook/recipes/advanced/per-item-polling/) |
66
+ | Toast expiry or runtime item timers | Timer group | `@crup/react-timer-hook/group` | [Dynamic items](https://crup.github.io/react-timer-hook/recipes/advanced/dynamic-items/) |
67
+
68
+ See the full use-case guide: https://crup.github.io/react-timer-hook/use-cases/
69
+
54
70
  ## Quick examples
55
71
 
56
72
  ### Stopwatch
@@ -152,6 +168,7 @@ const timers = useTimerGroup({
152
168
  | `updateIntervalMs` | `number` | No | Render/update cadence in milliseconds. Defaults to `1000`. This does not define elapsed time; elapsed time is calculated from timestamps. Use a smaller value like `100` or `20` when the UI needs finer updates. |
153
169
  | `endWhen` | `(snapshot) => boolean` | No | Ends the lifecycle when it returns `true`. Use this for countdowns, timeouts, and custom stop conditions. |
154
170
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per generation when `endWhen` ends the lifecycle. `restart()` creates a new generation. |
171
+ | `onError` | `(error, snapshot, controls) => void` | No | Handles sync throws and async rejections from `onEnd`. |
155
172
 
156
173
  ### `useScheduledTimer()` settings
157
174
 
@@ -163,6 +180,7 @@ Import from `@crup/react-timer-hook/schedules` when you need polling or schedule
163
180
  | `updateIntervalMs` | `number` | No | Render/update cadence in milliseconds. Defaults to `1000`. Scheduled callbacks can run on their own cadence. |
164
181
  | `endWhen` | `(snapshot) => boolean` | No | Ends the lifecycle when it returns `true`. |
165
182
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per generation when `endWhen` ends the lifecycle. |
183
+ | `onError` | `(error, snapshot, controls) => void` | No | Handles sync throws and async rejections from `onEnd`. |
166
184
  | `schedules` | `TimerSchedule[]` | No | Scheduled side effects that run while the timer is active. Async overlap defaults to `skip`. |
167
185
  | `diagnostics` | `TimerDiagnostics` | No | Optional lifecycle and schedule events. No logs are emitted unless you pass a logger. |
168
186
 
@@ -194,6 +212,7 @@ Import from `@crup/react-timer-hook/group` when many keyed items need independen
194
212
  | `autoStart` | `boolean` | No | Starts the item automatically when it is added or synced. Defaults to `false`. |
195
213
  | `endWhen` | `(snapshot) => boolean` | No | Ends that item when it returns `true`. |
196
214
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per item generation when that item ends naturally. |
215
+ | `onError` | `(error, snapshot, controls) => void` | No | Handles sync throws and async rejections from that item's `onEnd`. |
197
216
  | `schedules` | `TimerSchedule[]` | No | Per-item schedules with the same contract as `useScheduledTimer()`. |
198
217
 
199
218
  ### Values and controls
@@ -227,9 +246,9 @@ The default import stays small. Add the other pieces only when that screen needs
227
246
 
228
247
  | Piece | Import | Best for | Raw | Gzip | Brotli |
229
248
  | --- | --- | --- | ---: | ---: | ---: |
230
- | ⏱️ Core | `@crup/react-timer-hook` | Stopwatch, countdown, clock, custom lifecycle | 3.82 kB | 1.31 kB | 1.21 kB |
231
- | 🧭 Timer group | `@crup/react-timer-hook/group` | Many independent row/item timers | 9.75 kB | 3.42 kB | 3.13 kB |
232
- | 📡 Schedules | `@crup/react-timer-hook/schedules` | Polling, cadence callbacks, overdue timing context | 7.41 kB | 2.57 kB | 2.36 kB |
249
+ | ⏱️ Core | `@crup/react-timer-hook` | Stopwatch, countdown, clock, custom lifecycle | 3.96 kB | 1.37 kB | 1.25 kB |
250
+ | 🧭 Timer group | `@crup/react-timer-hook/group` | Many independent row/item timers | 9.91 kB | 3.51 kB | 3.20 kB |
251
+ | 📡 Schedules | `@crup/react-timer-hook/schedules` | Polling, cadence callbacks, overdue timing context | 7.62 kB | 2.67 kB | 2.46 kB |
233
252
  | 🧩 Duration | `@crup/react-timer-hook/duration` | `days`, `hours`, `minutes`, `seconds`, `milliseconds` | 318 B | 224 B | 192 B |
234
253
  | 🔎 Diagnostics | `@crup/react-timer-hook/diagnostics` | Optional lifecycle and schedule event logging | 105 B | 115 B | 90 B |
235
254
 
@@ -0,0 +1 @@
1
+ import{c as p,d as c,k as f}from"./chunk-I3PNNG3I.js";function y(e){return e?typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger}:{enabled:!1,includeTicks:!1}}function v(e,n){let t=y(e);!t.enabled||!t.logger||n.type==="timer:tick"&&!t.includeTicks||t.logger({...n,label:n.label??t.label})}function k(e,n){return{generation:n,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function b(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null}}function E({schedules:e=[],states:n,snapshot:t,generation:o,controls:r,activation:i=!1,isLive:l,onEvent:d}){let u=new Set;e.forEach((s,C)=>{let m=s.id??String(C);u.add(m);let a=n.get(m);if(a||(a=b(),n.set(m,a)),i&&s.leading&&a.leadingGeneration!==o){a.leadingGeneration=o,g(s,m,a,t,o,r,S(s,m,t.now,t.now,0),l,d);return}a.lastRunAt===null&&(a.lastRunAt=t.now);let T=Math.floor((t.now-a.lastRunAt)/s.everyMs);if(T>=1){let h=a.lastRunAt+T*s.everyMs;g(s,m,a,t,o,r,S(s,m,h,t.now,T-1),l,d)}});for(let s of n.keys())u.has(s)||n.delete(s)}function I(e,n,t,o){let r=o;return e?.forEach((i,l)=>{let d=i.id??String(l),s=n.get(d)?.lastRunAt??t;r=Math.min(r,Math.max(1,s+i.everyMs-t))}),r}function M(e,n,t,o){let r=new Set;e?.forEach((i,l)=>{let d=i.id??String(l);r.add(d),n.has(d)||n.set(d,{lastRunAt:o?t:null,pendingCount:0,leadingGeneration:null})});for(let i of n.keys())r.has(i)||n.delete(i)}function R(e){return(e??[]).map((n,t)=>`${n.id??t}:${n.everyMs}:${n.leading??!1}:${n.overlap??"skip"}`).join(",")}function S(e,n,t,o,r){return{scheduleId:e.id??n,scheduledAt:t,firedAt:o,nextRunAt:t+e.everyMs,overdueCount:r,effectiveEveryMs:e.everyMs}}function g(e,n,t,o,r,i,l,d,u){if(t.pendingCount>0&&(e.overlap??"skip")==="skip"){t.lastRunAt=l.scheduledAt,u?.({type:"schedule:skip",context:l,reason:"overlap"});return}t.lastRunAt=l.scheduledAt,t.pendingCount+=1,u?.({type:"schedule:start",context:l}),Promise.resolve().then(()=>e.callback(o,i,l)).then(()=>u?.({type:"schedule:end",context:l}),s=>u?.({type:"schedule:error",context:l,error:s})).finally(()=>{d(r)&&(t.pendingCount=Math.max(0,t.pendingCount-1))})}function G(e,n){return{state:p(n),definition:e,endCalledGeneration:null}}function P(e){e.endCalledGeneration=null}function O(e,n){return c(e.state,n)}function $(e,n,t,o){let r=c(e.state,n);if(!e.definition.endWhen?.(r)||!f(e.state,n))return null;let i=c(e.state,n);return x(e,i,t,o),i}function x(e,n,t,o){let r=e.state.generation;if(e.endCalledGeneration!==r){e.endCalledGeneration=r;try{let i=e.definition.onEnd?.(n,t);i&&o&&Promise.resolve(i).catch(l=>o?.(l,n,r))}catch(i){if(o){o(i,n,r);return}throw i}}}export{v as a,k as b,E as c,I as d,M as e,R as f,G as g,P as h,O as i,$ as j};
@@ -1,5 +1,5 @@
1
- import { i as TimerDiagnostics } from './types-DK7omKO-.cjs';
2
- export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types-DK7omKO-.cjs';
1
+ import { i as TimerDiagnostics } from './types--o_xW2FP.cjs';
2
+ export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types--o_xW2FP.cjs';
3
3
 
4
4
  declare function consoleTimerDiagnostics(options?: {
5
5
  includeTicks?: boolean;
@@ -1,5 +1,5 @@
1
- import { i as TimerDiagnostics } from './types-DK7omKO-.js';
2
- export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types-DK7omKO-.js';
1
+ import { i as TimerDiagnostics } from './types--o_xW2FP.js';
2
+ export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types--o_xW2FP.js';
3
3
 
4
4
  declare function consoleTimerDiagnostics(options?: {
5
5
  includeTicks?: boolean;
@@ -1,4 +1,4 @@
1
- import { D as DurationParts } from './types-DK7omKO-.cjs';
1
+ import { D as DurationParts } from './types--o_xW2FP.cjs';
2
2
 
3
3
  declare function durationParts(milliseconds: number): DurationParts;
4
4
 
@@ -1,4 +1,4 @@
1
- import { D as DurationParts } from './types-DK7omKO-.js';
1
+ import { D as DurationParts } from './types--o_xW2FP.js';
2
2
 
3
3
  declare function durationParts(milliseconds: number): DurationParts;
4
4
 
package/dist/group.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var F=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var ge=Object.prototype.hasOwnProperty;var he=(e,t)=>{for(var i in t)F(e,i,{get:t[i],enumerable:!0})},ye=(e,t,i,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Se(t))!ge.call(e,a)&&a!==i&&F(e,a,{get:()=>t[a],enumerable:!(s=Te(t,a))||s.enumerable});return e};var we=e=>ye(F({},"__esModule",{value:!0}),e);var ke={};he(ke,{useTimerGroup:()=>ae});module.exports=we(ke);var I=require("react");function p(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function H(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function be(e){return e?typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger}:{enabled:!1,includeTicks:!1}}function A(e,t){let i=be(e);!i.enabled||!i.logger||t.type==="timer:tick"&&!i.includeTicks||i.logger({...t,label:t.label??i.label})}function x(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function Ce(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null}}function V({schedules:e=[],states:t,snapshot:i,generation:s,controls:a,activation:u=!1,isLive:c,onEvent:T}){let d=new Set;e.forEach((m,g)=>{let b=m.id??String(g);d.add(b);let S=t.get(b);if(S||(S=Ce(),t.set(b,S)),u&&m.leading&&S.leadingGeneration!==s){S.leadingGeneration=s,Q(m,b,S,i,s,a,J(m,b,i.now,i.now,0),c,T);return}S.lastRunAt===null&&(S.lastRunAt=i.now);let v=Math.floor((i.now-S.lastRunAt)/m.everyMs);if(v>=1){let h=S.lastRunAt+v*m.everyMs;Q(m,b,S,i,s,a,J(m,b,h,i.now,v-1),c,T)}});for(let m of t.keys())d.has(m)||t.delete(m)}function X(e,t,i,s){let a=s;return e?.forEach((u,c)=>{let T=u.id??String(c),m=t.get(T)?.lastRunAt??i;a=Math.min(a,Math.max(1,m+u.everyMs-i))}),a}function Y(e,t,i,s){let a=new Set;e?.forEach((u,c)=>{let T=u.id??String(c);a.add(T),t.has(T)||t.set(T,{lastRunAt:s?i:null,pendingCount:0,leadingGeneration:null})});for(let u of t.keys())a.has(u)||t.delete(u)}function J(e,t,i,s,a){return{scheduleId:e.id??t,scheduledAt:i,firedAt:s,nextRunAt:i+e.everyMs,overdueCount:a,effectiveEveryMs:e.everyMs}}function Q(e,t,i,s,a,u,c,T,d){if(i.pendingCount>0&&(e.overlap??"skip")==="skip"){i.lastRunAt=c.scheduledAt,d?.({type:"schedule:skip",context:c,reason:"overlap"});return}i.lastRunAt=c.scheduledAt,i.pendingCount+=1,d?.({type:"schedule:start",context:c}),Promise.resolve().then(()=>e.callback(s,u,c)).then(()=>d?.({type:"schedule:end",context:c}),m=>d?.({type:"schedule:error",context:c,error:m})).finally(()=>{T(a)&&(i.pendingCount=Math.max(0,i.pendingCount-1))})}function Z(e){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:e.wallNow}}function G(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function E(e,t){let i=G(e,t);return{status:e.status,now:t.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:i,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function M(e,t){return e.status!=="idle"?!1:(e.status="running",e.startedAt=t.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function _(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=G(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function ee(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function L(e,t,i={}){return e.generation+=1,e.tick=0,e.status=i.autoStart?"running":"idle",e.startedAt=i.autoStart?t.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=i.autoStart?t.monotonicNow:null,e.now=t.wallNow,!0}function te(e,t){return L(e,t,{autoStart:!0})}function ne(e,t,i){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=G(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=i??null,e.now=t.wallNow,!0)}function re(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=G(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function oe(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function ie(e,t){return{state:Z(t),definition:e,endCalledGeneration:null}}function j(e){e.endCalledGeneration=null}function w(e,t){return E(e.state,t)}function se(e,t,i,s){let a=E(e.state,t);if(!e.definition.endWhen?.(a)||!re(e.state,t))return null;let u=E(e.state,t);return Ie(e,u,i,s),u}function Ie(e,t,i,s){let a=e.state.generation;if(e.endCalledGeneration!==a){e.endCalledGeneration=a;try{let u=e.definition.onEnd?.(t,i);u&&s&&Promise.resolve(u).catch(c=>s?.(c,t,a))}catch(u){if(s){s(u,t,a);return}throw u}}}function ae(e={}){let t=(0,I.useRef)(null);return t.current===null&&(t.current=ve(e)),t.current.setOptions(e),(0,I.useEffect)(()=>{let s=t.current;return()=>s.destroy()},[]),(0,I.useEffect)(()=>{t.current.sync()},[e.diagnostics,e.items,e.updateIntervalMs]),{...(0,I.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getSnapshot),get:t.current.getTimer,...t.current.controls}}function ve(e){let t=e;K(t);let i=new Set,s=new Map,a=le(s,p().wallNow),u=null,c=R(t),T=!0,d=(n=p())=>{a=le(s,n.wallNow),i.forEach(r=>r())},m=()=>{u!==null&&(clearTimeout(u),u=null)},g=(n,r,o,l={})=>{A(t.diagnostics,{type:n,scope:"timer-group",timerId:r?.id,...x(o,r?.state.generation??0),...l})},b=n=>(r,o,l)=>{A(t.diagnostics,{type:"callback:error",scope:"timer-group",timerId:n.id,error:r,...x(o,l)})},S=(n,r,o)=>l=>{A(t.diagnostics,{type:l.type,scope:"timer-group",timerId:n.id,...l.context,..."reason"in l?{reason:l.reason}:{},..."error"in l?{error:l.error}:{},...x(r,o)})},v=n=>({start:()=>N(n),pause:()=>D(n),resume:()=>P(n),reset:r=>O(n,r),restart:()=>$(n),cancel:r=>U(n,r)}),h=(n,r=p(),o=!1)=>{if(n.state.status!=="running")return!1;let l=v(n.id),f=se(n,r,l,b(n));if(f)return g("timer:end",n,f),!0;let C=w(n,r);return V({schedules:n.definition.schedules,states:n.schedules,snapshot:C,generation:n.state.generation,controls:l,activation:o,isLive:z=>s.get(n.id)?.state.generation===z,onEvent:S(n,C,n.state.generation)}),!1},y=()=>{m();let n=Array.from(s.values()).filter(l=>l.state.status==="running");if(n.length===0)return;let r=p(),o=t.updateIntervalMs??1e3;for(let l of n)o=Math.min(o,X(l.definition.schedules,l.schedules,r.wallNow,o));g("scheduler:start",n[0],w(n[0],r)),u=setTimeout(()=>{let l=p();for(let f of s.values()){if(f.state.status!=="running")continue;oe(f.state,l);let C=w(f,l);g("timer:tick",f,C),h(f,l)}d(l),y()},o)},q=n=>{let r=s.get(n.id);if(r)return r.definition=n,k(r,p().wallNow),{item:r,added:!1};let o=p(),l={...ie(n,o),id:n.id,schedules:new Map};return s.set(n.id,l),k(l,o.wallNow),n.autoStart&&(M(l.state,o),h(l,o,!0)),{item:l,added:!0}},B=()=>{K(t);let n=T;T=!1;let r=new Set,o=!1,l=p();if(t.items){for(let f of t.items){r.add(f.id);let{item:C,added:z}=q(f);o=o||z,f.autoStart&&C.state.status==="idle"&&M(C.state,l)&&(o=!0,o=h(C,l,!0)||o),o=h(C,l)||o}for(let f of s.keys())r.has(f)||(s.delete(f),o=!0)}o&&d(l),(o||n)&&y()},ue=n=>{if(W([n]),s.has(n.id))throw new Error(`Timer item "${n.id}" already exists`);q(n),c=R(t),d(),y()},ce=(n,r)=>{let o=s.get(n);if(!o)return;let l={...o.definition,...r,id:n};W([l]),o.definition=l,k(o,p().wallNow),h(o),c=R(t),d(),y()},de=n=>{s.delete(n)&&(d(),y())},me=()=>{s.clear(),m(),d()},N=n=>{let r=s.get(n);if(!r)return;let o=p();M(r.state,o)&&(g("timer:start",r,w(r,o)),h(r,o,!0),d(o),y())},D=n=>{let r=s.get(n);if(!r)return;let o=p();_(r.state,o)&&(g("timer:pause",r,w(r,o)),d(o),y())},P=n=>{let r=s.get(n);if(!r)return;let o=p();ee(r.state,o)&&(g("timer:resume",r,w(r,o)),h(r,o,!0),d(o),y())},O=(n,r={})=>{let o=s.get(n);if(!o)return;let l=p();L(o.state,l,r),o.schedules.clear(),k(o,l.wallNow),j(o),g("timer:reset",o,w(o,l)),h(o,l,r.autoStart),d(l),y()},$=n=>{let r=s.get(n);if(!r)return;let o=p();te(r.state,o),r.schedules.clear(),k(r,o.wallNow),j(r),g("timer:restart",r,w(r,o)),h(r,o,!0),d(o),y()},U=(n,r)=>{let o=s.get(n);if(!o)return;let l=p();ne(o.state,l,r)&&(g("timer:cancel",o,w(o,l),{reason:r}),d(l),y())},pe=n=>{let r=s.get(n);return r?w(r,p()):void 0},fe={add:ue,update:ce,remove:de,clear:me,start:N,pause:D,resume:P,reset:O,restart:$,cancel:U,startAll:()=>Array.from(s.keys()).forEach(N),pauseAll:()=>Array.from(s.keys()).forEach(D),resumeAll:()=>Array.from(s.keys()).forEach(P),resetAll:n=>Array.from(s.keys()).forEach(r=>O(r,n)),restartAll:()=>Array.from(s.keys()).forEach($),cancelAll:n=>Array.from(s.keys()).forEach(r=>U(r,n))};return B(),{controls:fe,destroy:m,getSnapshot:()=>a,getTimer:pe,setOptions:n=>{K(n);let r=R(n);r!==c&&(c=r,T=!0),t=n},subscribe:n=>(i.add(n),()=>i.delete(n)),sync:B}}function le(e,t){return{now:t,size:e.size,ids:Array.from(e.keys())}}function k(e,t){Y(e.definition.schedules,e.schedules,t,e.state.status==="running")}function R(e){return[e.updateIntervalMs??1e3,...(e.items??[]).map(t=>{let i=t.schedules?.map((s,a)=>`${s.id??a}:${s.everyMs}:${s.leading??!1}:${s.overlap??"skip"}`).join(",");return`${t.id}:${t.autoStart??!1}:${i??""}`})].join("|")}function K(e){H(e.updateIntervalMs??1e3,"updateIntervalMs"),W(e.items)}function W(e){let t=new Set;e?.forEach(i=>{if(!i.id)throw new Error("Timer item id is required");if(t.has(i.id))throw new Error(`Duplicate timer item id "${i.id}"`);t.add(i.id),i.schedules?.forEach(s=>H(s.everyMs,"schedule.everyMs"))})}0&&(module.exports={useTimerGroup});
1
+ "use strict";var F=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var be=(e,t)=>{for(var i in t)F(e,i,{get:t[i],enumerable:!0})},Ce=(e,t,i,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of ye(t))!we.call(e,a)&&a!==i&&F(e,a,{get:()=>t[a],enumerable:!(s=he(t,a))||s.enumerable});return e};var Ie=e=>Ce(F({},"__esModule",{value:!0}),e);var Ge={};be(Ge,{useTimerGroup:()=>ce});module.exports=Ie(Ge);var v=require("react");function f(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function H(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function ve(e){return e?typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger}:{enabled:!1,includeTicks:!1}}function x(e,t){let i=ve(e);!i.enabled||!i.logger||t.type==="timer:tick"&&!i.includeTicks||i.logger({...t,label:t.label??i.label})}function G(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function ke(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null}}function Y({schedules:e=[],states:t,snapshot:i,generation:s,controls:a,activation:u=!1,isLive:m,onEvent:d}){let y=new Set;e.forEach((c,D)=>{let b=c.id??String(D);y.add(b);let S=t.get(b);if(S||(S=ke(),t.set(b,S)),u&&c.leading&&S.leadingGeneration!==s){S.leadingGeneration=s,X(c,b,S,i,s,a,V(c,b,i.now,i.now,0),m,d);return}S.lastRunAt===null&&(S.lastRunAt=i.now);let g=Math.floor((i.now-S.lastRunAt)/c.everyMs);if(g>=1){let h=S.lastRunAt+g*c.everyMs;X(c,b,S,i,s,a,V(c,b,h,i.now,g-1),m,d)}});for(let c of t.keys())y.has(c)||t.delete(c)}function Z(e,t,i,s){let a=s;return e?.forEach((u,m)=>{let d=u.id??String(m),c=t.get(d)?.lastRunAt??i;a=Math.min(a,Math.max(1,c+u.everyMs-i))}),a}function _(e,t,i,s){let a=new Set;e?.forEach((u,m)=>{let d=u.id??String(m);a.add(d),t.has(d)||t.set(d,{lastRunAt:s?i:null,pendingCount:0,leadingGeneration:null})});for(let u of t.keys())a.has(u)||t.delete(u)}function ee(e){return(e??[]).map((t,i)=>`${t.id??i}:${t.everyMs}:${t.leading??!1}:${t.overlap??"skip"}`).join(",")}function V(e,t,i,s,a){return{scheduleId:e.id??t,scheduledAt:i,firedAt:s,nextRunAt:i+e.everyMs,overdueCount:a,effectiveEveryMs:e.everyMs}}function X(e,t,i,s,a,u,m,d,y){if(i.pendingCount>0&&(e.overlap??"skip")==="skip"){i.lastRunAt=m.scheduledAt,y?.({type:"schedule:skip",context:m,reason:"overlap"});return}i.lastRunAt=m.scheduledAt,i.pendingCount+=1,y?.({type:"schedule:start",context:m}),Promise.resolve().then(()=>e.callback(s,u,m)).then(()=>y?.({type:"schedule:end",context:m}),c=>y?.({type:"schedule:error",context:m,error:c})).finally(()=>{d(a)&&(i.pendingCount=Math.max(0,i.pendingCount-1))})}function te(e){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:e.wallNow}}function E(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function R(e,t){let i=E(e,t);return{status:e.status,now:t.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:i,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function M(e,t){return e.status!=="idle"?!1:(e.status="running",e.startedAt=t.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function ne(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=E(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function re(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function j(e,t,i={}){return e.generation+=1,e.tick=0,e.status=i.autoStart?"running":"idle",e.startedAt=i.autoStart?t.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=i.autoStart?t.monotonicNow:null,e.now=t.wallNow,!0}function oe(e,t){return j(e,t,{autoStart:!0})}function ie(e,t,i){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=E(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=i??null,e.now=t.wallNow,!0)}function se(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=E(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function le(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function ae(e,t){return{state:te(t),definition:e,endCalledGeneration:null}}function K(e){e.endCalledGeneration=null}function w(e,t){return R(e.state,t)}function ue(e,t,i,s){let a=R(e.state,t);if(!e.definition.endWhen?.(a)||!se(e.state,t))return null;let u=R(e.state,t);return Ae(e,u,i,s),u}function Ae(e,t,i,s){let a=e.state.generation;if(e.endCalledGeneration!==a){e.endCalledGeneration=a;try{let u=e.definition.onEnd?.(t,i);u&&s&&Promise.resolve(u).catch(m=>s?.(m,t,a))}catch(u){if(s){s(u,t,a);return}throw u}}}function ce(e={}){let t=(0,v.useRef)(null);return t.current===null&&(t.current=xe(e)),t.current.setOptions(e),(0,v.useEffect)(()=>{let s=t.current;return()=>s.destroy()},[]),{...(0,v.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getSnapshot),get:t.current.getTimer,...t.current.controls}}function xe(e){let t=e;q(t);let i=new Set,s=new Map,a=W(s,f().wallNow),u=null,m=N(t),d=(n=f())=>{a=W(s,n.wallNow),i.forEach(r=>r())},y=()=>{u!==null&&(clearTimeout(u),u=null)},c=(n,r,o,l={})=>{x(t.diagnostics,{type:n,scope:"timer-group",timerId:r?.id,...G(o,r?.state.generation??0),...l})},D=n=>(r,o,l)=>{n.definition.onError?.(r,o,S(n.id)),x(t.diagnostics,{type:"callback:error",scope:"timer-group",timerId:n.id,error:r,...G(o,l)})},b=(n,r,o)=>l=>{x(t.diagnostics,{type:l.type,scope:"timer-group",timerId:n.id,...l.context,..."reason"in l?{reason:l.reason}:{},..."error"in l?{error:l.error}:{},...G(r,o)})},S=n=>({start:()=>P(n),pause:()=>O(n),resume:()=>$(n),reset:r=>U(n,r),restart:()=>z(n),cancel:r=>L(n,r)}),g=(n,r=f(),o=!1)=>{if(n.state.status!=="running")return!1;let l=S(n.id),T=ue(n,r,l,D(n));if(T)return c("timer:end",n,T),!0;let p=w(n,r);return Y({schedules:n.definition.schedules,states:n.schedules,snapshot:p,generation:n.state.generation,controls:l,activation:o,isLive:C=>s.get(n.id)?.state.generation===C,onEvent:b(n,p,n.state.generation)}),!1},h=(n=!0)=>{y();let r=Array.from(s.values()).filter(T=>T.state.status==="running");if(r.length===0)return;let o=f(),l=t.updateIntervalMs??1e3;for(let T of r)l=Math.min(l,Z(T.definition.schedules,T.schedules,o.wallNow,l));n&&c("scheduler:start",r[0],w(r[0],o)),u=setTimeout(()=>{let T=f();for(let p of s.values()){if(p.state.status!=="running")continue;le(p.state,T);let C=w(p,T);c("timer:tick",p,C),g(p,T)}d(T),h()},l)},J=n=>{let r=s.get(n.id);if(r)return r.definition=n,k(r,f().wallNow),{item:r,added:!1};let o=f(),l={...ae(n,o),id:n.id,schedules:new Map};return s.set(n.id,l),k(l,o.wallNow),{item:l,added:!0}},Q=(n={})=>{let r=n.notify??!0,o=n.process??!0,l=n.reschedule??!0;q(t);let T=new Set,p=!1,C=f();if(t.items){for(let I of t.items){T.add(I.id);let{item:A,added:ge}=J(I);p=p||ge,I.autoStart&&A.state.status==="idle"&&M(A.state,C)&&(p=!0,o&&(p=g(A,C,!0)||p)),o&&(p=g(A,C)||p)}for(let I of s.keys())T.has(I)||(s.delete(I),p=!0)}p&&(r?d(C):a=W(s,C.wallNow)),(p||l)&&h(r)},de=n=>{if(B([n]),s.has(n.id))throw new Error(`Timer item "${n.id}" already exists`);let{item:r}=J(n),o=f();n.autoStart&&M(r.state,o)&&g(r,o,!0),m=N(t),d(o),h()},me=(n,r)=>{let o=s.get(n);if(!o)return;let l={...o.definition,...r,id:n};B([l]),o.definition=l,k(o,f().wallNow),g(o),m=N(t),d(),h()},pe=n=>{s.delete(n)&&(d(),h())},fe=()=>{s.clear(),y(),d()},P=n=>{let r=s.get(n);if(!r)return;let o=f();M(r.state,o)&&(c("timer:start",r,w(r,o)),g(r,o,!0),d(o),h())},O=n=>{let r=s.get(n);if(!r)return;let o=f();ne(r.state,o)&&(c("timer:pause",r,w(r,o)),d(o),h())},$=n=>{let r=s.get(n);if(!r)return;let o=f();re(r.state,o)&&(c("timer:resume",r,w(r,o)),g(r,o,!0),d(o),h())},U=(n,r={})=>{let o=s.get(n);if(!o)return;let l=f();j(o.state,l,r),o.schedules.clear(),k(o,l.wallNow),K(o),c("timer:reset",o,w(o,l)),g(o,l,r.autoStart),d(l),h()},z=n=>{let r=s.get(n);if(!r)return;let o=f();oe(r.state,o),r.schedules.clear(),k(r,o.wallNow),K(r),c("timer:restart",r,w(r,o)),g(r,o,!0),d(o),h()},L=(n,r)=>{let o=s.get(n);if(!o)return;let l=f();ie(o.state,l,r)&&(c("timer:cancel",o,w(o,l),{reason:r}),d(l),h())},Te=n=>{let r=s.get(n);return r?w(r,f()):void 0},Se={add:de,update:me,remove:pe,clear:fe,start:P,pause:O,resume:$,reset:U,restart:z,cancel:L,startAll:()=>Array.from(s.keys()).forEach(P),pauseAll:()=>Array.from(s.keys()).forEach(O),resumeAll:()=>Array.from(s.keys()).forEach($),resetAll:n=>Array.from(s.keys()).forEach(r=>U(r,n)),restartAll:()=>Array.from(s.keys()).forEach(z),cancelAll:n=>Array.from(s.keys()).forEach(r=>L(r,n))};return Q(),{controls:Se,destroy:y,getSnapshot:()=>a,getTimer:Te,setOptions:n=>{q(n);let r=N(n),o=r!==m,l=n.items!==t.items||o;t=n,l&&(m=r,Q({notify:!1,process:!1,reschedule:o}))},subscribe:n=>(i.add(n),()=>i.delete(n))}}function W(e,t){return{now:t,size:e.size,ids:Array.from(e.keys())}}function k(e,t){_(e.definition.schedules,e.schedules,t,e.state.status==="running")}function N(e){return[e.updateIntervalMs??1e3,...(e.items??[]).map(t=>{let i=ee(t.schedules);return`${t.id}:${t.autoStart??!1}:${i??""}`})].join("|")}function q(e){H(e.updateIntervalMs??1e3,"updateIntervalMs"),B(e.items)}function B(e){let t=new Set;e?.forEach(i=>{if(!i.id)throw new Error("Timer item id is required");if(t.has(i.id))throw new Error(`Duplicate timer item id "${i.id}"`);t.add(i.id),i.schedules?.forEach(s=>H(s.everyMs,"schedule.everyMs"))})}0&&(module.exports={useTimerGroup});
package/dist/group.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-DK7omKO-.cjs';
2
- export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-DK7omKO-.cjs';
1
+ import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types--o_xW2FP.cjs';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types--o_xW2FP.cjs';
3
3
 
4
4
  declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
5
5
 
package/dist/group.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-DK7omKO-.js';
2
- export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-DK7omKO-.js';
1
+ import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types--o_xW2FP.js';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types--o_xW2FP.js';
3
3
 
4
4
  declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
5
5
 
package/dist/group.js CHANGED
@@ -1 +1 @@
1
- import{a as G,b as w,c as J,d as K,e as Q,f as V,g as C,h as d,i as W}from"./chunk-RT4C7DWO.js";import{a,b as x,e as I,f as j,g as q,h as F,i as L,j as B,l as H}from"./chunk-I3PNNG3I.js";import{useEffect as X,useRef as ae,useSyncExternalStore as ue}from"react";function ce(i={}){let o=ae(null);return o.current===null&&(o.current=le(i)),o.current.setOptions(i),X(()=>{let n=o.current;return()=>n.destroy()},[]),X(()=>{o.current.sync()},[i.diagnostics,i.items,i.updateIntervalMs]),{...ue(o.current.subscribe,o.current.getSnapshot,o.current.getSnapshot),get:o.current.getTimer,...o.current.controls}}function le(i){let o=i;P(o);let c=new Set,n=new Map,T=Y(n,a().wallNow),S=null,y=k(o),v=!0,l=(e=a())=>{T=Y(n,e.wallNow),c.forEach(t=>t())},E=()=>{S!==null&&(clearTimeout(S),S=null)},p=(e,t,r,s={})=>{G(o.diagnostics,{type:e,scope:"timer-group",timerId:t?.id,...w(r,t?.state.generation??0),...s})},Z=e=>(t,r,s)=>{G(o.diagnostics,{type:"callback:error",scope:"timer-group",timerId:e.id,error:t,...w(r,s)})},_=(e,t,r)=>s=>{G(o.diagnostics,{type:s.type,scope:"timer-group",timerId:e.id,...s.context,..."reason"in s?{reason:s.reason}:{},..."error"in s?{error:s.error}:{},...w(t,r)})},ee=e=>({start:()=>b(e),pause:()=>A(e),resume:()=>M(e),reset:t=>N(e,t),restart:()=>R(e),cancel:t=>O(e,t)}),f=(e,t=a(),r=!1)=>{if(e.state.status!=="running")return!1;let s=ee(e.id),u=W(e,t,s,Z(e));if(u)return p("timer:end",e,u),!0;let g=d(e,t);return J({schedules:e.definition.schedules,states:e.schedules,snapshot:g,generation:e.state.generation,controls:s,activation:r,isLive:$=>n.get(e.id)?.state.generation===$,onEvent:_(e,g,e.state.generation)}),!1},m=()=>{E();let e=Array.from(n.values()).filter(s=>s.state.status==="running");if(e.length===0)return;let t=a(),r=o.updateIntervalMs??1e3;for(let s of e)r=Math.min(r,K(s.definition.schedules,s.schedules,t.wallNow,r));p("scheduler:start",e[0],d(e[0],t)),S=setTimeout(()=>{let s=a();for(let u of n.values()){if(u.state.status!=="running")continue;H(u.state,s);let g=d(u,s);p("timer:tick",u,g),f(u,s)}l(s),m()},r)},D=e=>{let t=n.get(e.id);if(t)return t.definition=e,h(t,a().wallNow),{item:t,added:!1};let r=a(),s={...V(e,r),id:e.id,schedules:new Map};return n.set(e.id,s),h(s,r.wallNow),e.autoStart&&(I(s.state,r),f(s,r,!0)),{item:s,added:!0}},z=()=>{P(o);let e=v;v=!1;let t=new Set,r=!1,s=a();if(o.items){for(let u of o.items){t.add(u.id);let{item:g,added:$}=D(u);r=r||$,u.autoStart&&g.state.status==="idle"&&I(g.state,s)&&(r=!0,r=f(g,s,!0)||r),r=f(g,s)||r}for(let u of n.keys())t.has(u)||(n.delete(u),r=!0)}r&&l(s),(r||e)&&m()},te=e=>{if(U([e]),n.has(e.id))throw new Error(`Timer item "${e.id}" already exists`);D(e),y=k(o),l(),m()},re=(e,t)=>{let r=n.get(e);if(!r)return;let s={...r.definition,...t,id:e};U([s]),r.definition=s,h(r,a().wallNow),f(r),y=k(o),l(),m()},se=e=>{n.delete(e)&&(l(),m())},ne=()=>{n.clear(),E(),l()},b=e=>{let t=n.get(e);if(!t)return;let r=a();I(t.state,r)&&(p("timer:start",t,d(t,r)),f(t,r,!0),l(r),m())},A=e=>{let t=n.get(e);if(!t)return;let r=a();j(t.state,r)&&(p("timer:pause",t,d(t,r)),l(r),m())},M=e=>{let t=n.get(e);if(!t)return;let r=a();q(t.state,r)&&(p("timer:resume",t,d(t,r)),f(t,r,!0),l(r),m())},N=(e,t={})=>{let r=n.get(e);if(!r)return;let s=a();F(r.state,s,t),r.schedules.clear(),h(r,s.wallNow),C(r),p("timer:reset",r,d(r,s)),f(r,s,t.autoStart),l(s),m()},R=e=>{let t=n.get(e);if(!t)return;let r=a();L(t.state,r),t.schedules.clear(),h(t,r.wallNow),C(t),p("timer:restart",t,d(t,r)),f(t,r,!0),l(r),m()},O=(e,t)=>{let r=n.get(e);if(!r)return;let s=a();B(r.state,s,t)&&(p("timer:cancel",r,d(r,s),{reason:t}),l(s),m())},oe=e=>{let t=n.get(e);return t?d(t,a()):void 0},ie={add:te,update:re,remove:se,clear:ne,start:b,pause:A,resume:M,reset:N,restart:R,cancel:O,startAll:()=>Array.from(n.keys()).forEach(b),pauseAll:()=>Array.from(n.keys()).forEach(A),resumeAll:()=>Array.from(n.keys()).forEach(M),resetAll:e=>Array.from(n.keys()).forEach(t=>N(t,e)),restartAll:()=>Array.from(n.keys()).forEach(R),cancelAll:e=>Array.from(n.keys()).forEach(t=>O(t,e))};return z(),{controls:ie,destroy:E,getSnapshot:()=>T,getTimer:oe,setOptions:e=>{P(e);let t=k(e);t!==y&&(y=t,v=!0),o=e},subscribe:e=>(c.add(e),()=>c.delete(e)),sync:z}}function Y(i,o){return{now:o,size:i.size,ids:Array.from(i.keys())}}function h(i,o){Q(i.definition.schedules,i.schedules,o,i.state.status==="running")}function k(i){return[i.updateIntervalMs??1e3,...(i.items??[]).map(o=>{let c=o.schedules?.map((n,T)=>`${n.id??T}:${n.everyMs}:${n.leading??!1}:${n.overlap??"skip"}`).join(",");return`${o.id}:${o.autoStart??!1}:${c??""}`})].join("|")}function P(i){x(i.updateIntervalMs??1e3,"updateIntervalMs"),U(i.items)}function U(i){let o=new Set;i?.forEach(c=>{if(!c.id)throw new Error("Timer item id is required");if(o.has(c.id))throw new Error(`Duplicate timer item id "${c.id}"`);o.add(c.id),c.schedules?.forEach(n=>x(n.everyMs,"schedule.everyMs"))})}export{ce as useTimerGroup};
1
+ import{a as k,b as v,c as V,d as W,e as X,f as Y,g as Z,h as U,i as p,j as _}from"./chunk-N626U6HM.js";import{a,b as P,e as w,f as F,g as B,h as H,i as J,j as K,l as Q}from"./chunk-I3PNNG3I.js";import{useEffect as ce,useRef as le,useSyncExternalStore as me}from"react";function de(i={}){let o=le(null);return o.current===null&&(o.current=pe(i)),o.current.setOptions(i),ce(()=>{let n=o.current;return()=>n.destroy()},[]),{...me(o.current.subscribe,o.current.getSnapshot,o.current.getSnapshot),get:o.current.getTimer,...o.current.controls}}function pe(i){let o=i;z(o);let l=new Set,n=new Map,b=D(n,a().wallNow),y=null,I=E(o),m=(e=a())=>{b=D(n,e.wallNow),l.forEach(t=>t())},A=()=>{y!==null&&(clearTimeout(y),y=null)},f=(e,t,r,s={})=>{k(o.diagnostics,{type:e,scope:"timer-group",timerId:t?.id,...v(r,t?.state.generation??0),...s})},ee=e=>(t,r,s)=>{e.definition.onError?.(t,r,L(e.id)),k(o.diagnostics,{type:"callback:error",scope:"timer-group",timerId:e.id,error:t,...v(r,s)})},te=(e,t,r)=>s=>{k(o.diagnostics,{type:s.type,scope:"timer-group",timerId:e.id,...s.context,..."reason"in s?{reason:s.reason}:{},..."error"in s?{error:s.error}:{},...v(t,r)})},L=e=>({start:()=>N(e),pause:()=>R(e),resume:()=>M(e),reset:t=>x(e,t),restart:()=>C(e),cancel:t=>O(e,t)}),g=(e,t=a(),r=!1)=>{if(e.state.status!=="running")return!1;let s=L(e.id),c=_(e,t,s,ee(e));if(c)return f("timer:end",e,c),!0;let u=p(e,t);return V({schedules:e.definition.schedules,states:e.schedules,snapshot:u,generation:e.state.generation,controls:s,activation:r,isLive:h=>n.get(e.id)?.state.generation===h,onEvent:te(e,u,e.state.generation)}),!1},d=(e=!0)=>{A();let t=Array.from(n.values()).filter(c=>c.state.status==="running");if(t.length===0)return;let r=a(),s=o.updateIntervalMs??1e3;for(let c of t)s=Math.min(s,W(c.definition.schedules,c.schedules,r.wallNow,s));e&&f("scheduler:start",t[0],p(t[0],r)),y=setTimeout(()=>{let c=a();for(let u of n.values()){if(u.state.status!=="running")continue;Q(u.state,c);let h=p(u,c);f("timer:tick",u,h),g(u,c)}m(c),d()},s)},j=e=>{let t=n.get(e.id);if(t)return t.definition=e,S(t,a().wallNow),{item:t,added:!1};let r=a(),s={...Z(e,r),id:e.id,schedules:new Map};return n.set(e.id,s),S(s,r.wallNow),{item:s,added:!0}},q=(e={})=>{let t=e.notify??!0,r=e.process??!0,s=e.reschedule??!0;z(o);let c=new Set,u=!1,h=a();if(o.items){for(let T of o.items){c.add(T.id);let{item:G,added:ae}=j(T);u=u||ae,T.autoStart&&G.state.status==="idle"&&w(G.state,h)&&(u=!0,r&&(u=g(G,h,!0)||u)),r&&(u=g(G,h)||u)}for(let T of n.keys())c.has(T)||(n.delete(T),u=!0)}u&&(t?m(h):b=D(n,h.wallNow)),(u||s)&&d(t)},re=e=>{if($([e]),n.has(e.id))throw new Error(`Timer item "${e.id}" already exists`);let{item:t}=j(e),r=a();e.autoStart&&w(t.state,r)&&g(t,r,!0),I=E(o),m(r),d()},se=(e,t)=>{let r=n.get(e);if(!r)return;let s={...r.definition,...t,id:e};$([s]),r.definition=s,S(r,a().wallNow),g(r),I=E(o),m(),d()},oe=e=>{n.delete(e)&&(m(),d())},ne=()=>{n.clear(),A(),m()},N=e=>{let t=n.get(e);if(!t)return;let r=a();w(t.state,r)&&(f("timer:start",t,p(t,r)),g(t,r,!0),m(r),d())},R=e=>{let t=n.get(e);if(!t)return;let r=a();F(t.state,r)&&(f("timer:pause",t,p(t,r)),m(r),d())},M=e=>{let t=n.get(e);if(!t)return;let r=a();B(t.state,r)&&(f("timer:resume",t,p(t,r)),g(t,r,!0),m(r),d())},x=(e,t={})=>{let r=n.get(e);if(!r)return;let s=a();H(r.state,s,t),r.schedules.clear(),S(r,s.wallNow),U(r),f("timer:reset",r,p(r,s)),g(r,s,t.autoStart),m(s),d()},C=e=>{let t=n.get(e);if(!t)return;let r=a();J(t.state,r),t.schedules.clear(),S(t,r.wallNow),U(t),f("timer:restart",t,p(t,r)),g(t,r,!0),m(r),d()},O=(e,t)=>{let r=n.get(e);if(!r)return;let s=a();K(r.state,s,t)&&(f("timer:cancel",r,p(r,s),{reason:t}),m(s),d())},ie=e=>{let t=n.get(e);return t?p(t,a()):void 0},ue={add:re,update:se,remove:oe,clear:ne,start:N,pause:R,resume:M,reset:x,restart:C,cancel:O,startAll:()=>Array.from(n.keys()).forEach(N),pauseAll:()=>Array.from(n.keys()).forEach(R),resumeAll:()=>Array.from(n.keys()).forEach(M),resetAll:e=>Array.from(n.keys()).forEach(t=>x(t,e)),restartAll:()=>Array.from(n.keys()).forEach(C),cancelAll:e=>Array.from(n.keys()).forEach(t=>O(t,e))};return q(),{controls:ue,destroy:A,getSnapshot:()=>b,getTimer:ie,setOptions:e=>{z(e);let t=E(e),r=t!==I,s=e.items!==o.items||r;o=e,s&&(I=t,q({notify:!1,process:!1,reschedule:r}))},subscribe:e=>(l.add(e),()=>l.delete(e))}}function D(i,o){return{now:o,size:i.size,ids:Array.from(i.keys())}}function S(i,o){X(i.definition.schedules,i.schedules,o,i.state.status==="running")}function E(i){return[i.updateIntervalMs??1e3,...(i.items??[]).map(o=>{let l=Y(o.schedules);return`${o.id}:${o.autoStart??!1}:${l??""}`})].join("|")}function z(i){P(i.updateIntervalMs??1e3,"updateIntervalMs"),$(i.items)}function $(i){let o=new Set;i?.forEach(l=>{if(!l.id)throw new Error("Timer item id is required");if(o.has(l.id))throw new Error(`Duplicate timer item id "${l.id}"`);o.add(l.id),l.schedules?.forEach(n=>P(n.everyMs,"schedule.everyMs"))})}export{de as useTimerGroup};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var w=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var P=(e,t)=>{for(var o in t)w(e,o,{get:t[o],enumerable:!0})},F=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of O(t))!U.call(e,i)&&i!==o&&w(e,i,{get:()=>t[i],enumerable:!(r=E(t,i))||r.enumerable});return e};var D=e=>F(w({},"__esModule",{value:!0}),e);var W={};P(W,{useTimer:()=>x});module.exports=D(W);var d=require("react");function l(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function b(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function R(e){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:e.wallNow}}function T(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function p(e,t){let o=T(e,t);return{status:e.status,now:t.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:o,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function M(e,t){return e.status!=="idle"?!1:(e.status="running",e.startedAt=t.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function v(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=T(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function C(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function A(e,t,o={}){return e.generation+=1,e.tick=0,e.status=o.autoStart?"running":"idle",e.startedAt=o.autoStart?t.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=o.autoStart?t.monotonicNow:null,e.now=t.wallNow,!0}function N(e,t){return A(e,t,{autoStart:!0})}function h(e,t,o){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=T(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=o??null,e.now=t.wallNow,!0)}function y(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=T(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function I(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function x(e={}){let t=(0,d.useRef)(null);return t.current===null&&(t.current=G(e)),t.current.setOptions(e),(0,d.useEffect)(()=>{let r=t.current;return e.autoStart&&r.controls.start(),()=>r.destroy()},[]),{...(0,d.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getSnapshot),...t.current.controls}}function G(e){let t=e;b(t.updateIntervalMs??1e3,"updateIntervalMs");let o=new Set,r=R(l()),i=p(r,l()),S=null,f=null,u=(n=l())=>{i=p(r,n),o.forEach(a=>a())},s=()=>{S!==null&&(clearTimeout(S),S=null)},k=n=>{f!==r.generation&&(f=r.generation,t.onEnd?.(n,g))},m=n=>{let a=p(r,n);return!t.endWhen?.(a)||!y(r,n)?!1:(s(),u(n),k(p(r,n)),!0)},c=()=>{s(),r.status==="running"&&(S=setTimeout(()=>{if(r.status!=="running")return;let n=l();I(r,n),!m(n)&&(u(n),c())},t.updateIntervalMs??1e3))},g={start:()=>{let n=l();if(!M(r,n)){r.status==="running"&&c();return}u(n),m(n)||c()},pause:()=>{let n=l();v(r,n)&&(s(),u(n))},resume:()=>{let n=l();C(r,n)&&(u(n),m(n)||c())},reset:(n={})=>{let a=l();s(),A(r,a,n),f=null,u(a),n.autoStart&&!m(a)&&c()},restart:()=>{let n=l();s(),N(r,n),f=null,u(n),m(n)||c()},cancel:n=>{let a=l();h(r,a,n)&&(s(),u(a))}};return{controls:g,destroy:s,getSnapshot:()=>i,setOptions:n=>{b(n.updateIntervalMs??1e3,"updateIntervalMs"),t=n},subscribe:n=>(o.add(n),()=>o.delete(n))}}0&&(module.exports={useTimer});
1
+ "use strict";var A=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var F=(e,t)=>{for(var o in t)A(e,o,{get:t[o],enumerable:!0})},D=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of P(t))!U.call(e,i)&&i!==o&&A(e,i,{get:()=>t[i],enumerable:!(r=O(t,i))||r.enumerable});return e};var G=e=>D(A({},"__esModule",{value:!0}),e);var $={};F($,{useTimer:()=>k});module.exports=G($);var m=require("react");function a(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function g(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function M(e){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:e.wallNow}}function w(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function f(e,t){let o=w(e,t);return{status:e.status,now:t.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:o,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function h(e,t){return e.status!=="idle"?!1:(e.status="running",e.startedAt=t.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function v(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=w(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function C(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function R(e,t,o={}){return e.generation+=1,e.tick=0,e.status=o.autoStart?"running":"idle",e.startedAt=o.autoStart?t.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=o.autoStart?t.monotonicNow:null,e.now=t.wallNow,!0}function N(e,t){return R(e,t,{autoStart:!0})}function y(e,t,o){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=w(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=o??null,e.now=t.wallNow,!0)}function I(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=w(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function E(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function k(e={}){let t=(0,m.useRef)(null);return t.current===null&&(t.current=W(e)),t.current.setOptions(e),(0,m.useEffect)(()=>{let r=t.current;return e.autoStart&&r.controls.start(),()=>r.destroy()},[]),{...(0,m.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getSnapshot),...t.current.controls}}function W(e){let t=e;g(t.updateIntervalMs??1e3,"updateIntervalMs");let o=new Set,r=M(a()),i=f(r,a()),S=null,T=null,u=(n=a())=>{i=f(r,n),o.forEach(l=>l())},s=()=>{S!==null&&(clearTimeout(S),S=null)},x=n=>{if(T===r.generation)return;T=r.generation;let l=d=>{if(t.onError){t.onError(d,n,b);return}setTimeout(()=>{throw d},0)};try{Promise.resolve(t.onEnd?.(n,b)).catch(d=>{l(d)})}catch(d){l(d)}},p=n=>{let l=f(r,n);return!t.endWhen?.(l)||!I(r,n)?!1:(s(),u(n),x(f(r,n)),!0)},c=()=>{s(),r.status==="running"&&(S=setTimeout(()=>{if(r.status!=="running")return;let n=a();E(r,n),!p(n)&&(u(n),c())},t.updateIntervalMs??1e3))},b={start:()=>{let n=a();if(!h(r,n)){r.status==="running"&&c();return}u(n),p(n)||c()},pause:()=>{let n=a();v(r,n)&&(s(),u(n))},resume:()=>{let n=a();C(r,n)&&(u(n),p(n)||c())},reset:(n={})=>{let l=a();s(),R(r,l,n),T=null,u(l),n.autoStart&&!p(l)&&c()},restart:()=>{let n=a();s(),N(r,n),T=null,u(n),p(n)||c()},cancel:n=>{let l=a();y(r,l,n)&&(s(),u(l))}};return{controls:b,destroy:s,getSnapshot:()=>i,setOptions:n=>{g(n.updateIntervalMs??1e3,"updateIntervalMs"),t=n},subscribe:n=>(o.add(n),()=>o.delete(n))}}0&&(module.exports={useTimer});
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UseTimerOptions, T as TimerSnapshot, a as TimerControls } from './types-DK7omKO-.cjs';
2
- export { b as TimerEndPredicate, c as TimerStatus } from './types-DK7omKO-.cjs';
1
+ import { U as UseTimerOptions, T as TimerSnapshot, a as TimerControls } from './types--o_xW2FP.cjs';
2
+ export { b as TimerEndPredicate, c as TimerStatus } from './types--o_xW2FP.cjs';
3
3
 
4
4
  declare function useTimer(options?: UseTimerOptions): TimerSnapshot & TimerControls;
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UseTimerOptions, T as TimerSnapshot, a as TimerControls } from './types-DK7omKO-.js';
2
- export { b as TimerEndPredicate, c as TimerStatus } from './types-DK7omKO-.js';
1
+ import { U as UseTimerOptions, T as TimerSnapshot, a as TimerControls } from './types--o_xW2FP.js';
2
+ export { b as TimerEndPredicate, c as TimerStatus } from './types--o_xW2FP.js';
3
3
 
4
4
  declare function useTimer(options?: UseTimerOptions): TimerSnapshot & TimerControls;
5
5
 
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as n,b as f,c as h,d as l,e as y,f as v,g,h as b,i as C,j as I,k,l as O}from"./chunk-I3PNNG3I.js";import{useEffect as M,useRef as U,useSyncExternalStore as R}from"react";function x(u={}){let r=U(null);return r.current===null&&(r.current=P(u)),r.current.setOptions(u),M(()=>{let e=r.current;return u.autoStart&&e.controls.start(),()=>e.destroy()},[]),{...R(r.current.subscribe,r.current.getSnapshot,r.current.getSnapshot),...r.current.controls}}function P(u){let r=u;f(r.updateIntervalMs??1e3,"updateIntervalMs");let m=new Set,e=h(n()),S=l(e,n()),p=null,T=null,s=(t=n())=>{S=l(e,t),m.forEach(o=>o())},i=()=>{p!==null&&(clearTimeout(p),p=null)},E=t=>{T!==e.generation&&(T=e.generation,r.onEnd?.(t,d))},c=t=>{let o=l(e,t);return!r.endWhen?.(o)||!k(e,t)?!1:(i(),s(t),E(l(e,t)),!0)},a=()=>{i(),e.status==="running"&&(p=setTimeout(()=>{if(e.status!=="running")return;let t=n();O(e,t),!c(t)&&(s(t),a())},r.updateIntervalMs??1e3))},d={start:()=>{let t=n();if(!y(e,t)){e.status==="running"&&a();return}s(t),c(t)||a()},pause:()=>{let t=n();v(e,t)&&(i(),s(t))},resume:()=>{let t=n();g(e,t)&&(s(t),c(t)||a())},reset:(t={})=>{let o=n();i(),b(e,o,t),T=null,s(o),t.autoStart&&!c(o)&&a()},restart:()=>{let t=n();i(),C(e,t),T=null,s(t),c(t)||a()},cancel:t=>{let o=n();I(e,o,t)&&(i(),s(o))}};return{controls:d,destroy:i,getSnapshot:()=>S,setOptions:t=>{f(t.updateIntervalMs??1e3,"updateIntervalMs"),r=t},subscribe:t=>(m.add(t),()=>m.delete(t))}}export{x as useTimer};
1
+ import{a as o,b as d,c as y,d as m,e as v,f as g,g as E,h as b,i as k,j as C,k as I,l as O}from"./chunk-I3PNNG3I.js";import{useEffect as U,useRef as R,useSyncExternalStore as w}from"react";function x(c={}){let r=R(null);return r.current===null&&(r.current=P(c)),r.current.setOptions(c),U(()=>{let e=r.current;return c.autoStart&&e.controls.start(),()=>e.destroy()},[]),{...w(r.current.subscribe,r.current.getSnapshot,r.current.getSnapshot),...r.current.controls}}function P(c){let r=c;d(r.updateIntervalMs??1e3,"updateIntervalMs");let p=new Set,e=y(o()),h=m(e,o()),T=null,f=null,s=(t=o())=>{h=m(e,t),p.forEach(n=>n())},i=()=>{T!==null&&(clearTimeout(T),T=null)},M=t=>{if(f===e.generation)return;f=e.generation;let n=u=>{if(r.onError){r.onError(u,t,S);return}setTimeout(()=>{throw u},0)};try{Promise.resolve(r.onEnd?.(t,S)).catch(u=>{n(u)})}catch(u){n(u)}},l=t=>{let n=m(e,t);return!r.endWhen?.(n)||!I(e,t)?!1:(i(),s(t),M(m(e,t)),!0)},a=()=>{i(),e.status==="running"&&(T=setTimeout(()=>{if(e.status!=="running")return;let t=o();O(e,t),!l(t)&&(s(t),a())},r.updateIntervalMs??1e3))},S={start:()=>{let t=o();if(!v(e,t)){e.status==="running"&&a();return}s(t),l(t)||a()},pause:()=>{let t=o();g(e,t)&&(i(),s(t))},resume:()=>{let t=o();E(e,t)&&(s(t),l(t)||a())},reset:(t={})=>{let n=o();i(),b(e,n,t),f=null,s(n),t.autoStart&&!l(n)&&a()},restart:()=>{let t=o();i(),k(e,t),f=null,s(t),l(t)||a()},cancel:t=>{let n=o();C(e,n,t)&&(i(),s(n))}};return{controls:S,destroy:i,getSnapshot:()=>h,setOptions:t=>{d(t.updateIntervalMs??1e3,"updateIntervalMs"),r=t},subscribe:t=>(p.add(t),()=>p.delete(t))}}export{x as useTimer};
@@ -1 +1 @@
1
- "use strict";var A=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var Z=(e,t)=>{for(var r in t)A(e,r,{get:t[r],enumerable:!0})},_=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of X(t))!Y.call(e,i)&&i!==r&&A(e,i,{get:()=>t[i],enumerable:!(n=V(t,i))||n.enumerable});return e};var ee=e=>_(A({},"__esModule",{value:!0}),e);var ie={};Z(ie,{useScheduledTimer:()=>J});module.exports=ee(ie);var g=require("react");function T(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function k(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function te(e){return e?typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger}:{enabled:!1,includeTicks:!1}}function b(e,t){let r=te(e);!r.enabled||!r.logger||t.type==="timer:tick"&&!r.includeTicks||r.logger({...t,label:t.label??r.label})}function C(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function ne(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null}}function G({schedules:e=[],states:t,snapshot:r,generation:n,controls:i,activation:s=!1,isLive:u,onEvent:c}){let m=new Set;e.forEach((l,v)=>{let h=l.id??String(v);m.add(h);let d=t.get(h);if(d||(d=ne(),t.set(h,d)),s&&l.leading&&d.leadingGeneration!==n){d.leadingGeneration=n,N(l,h,d,r,n,i,D(l,h,r.now,r.now,0),u,c);return}d.lastRunAt===null&&(d.lastRunAt=r.now);let f=Math.floor((r.now-d.lastRunAt)/l.everyMs);if(f>=1){let I=d.lastRunAt+f*l.everyMs;N(l,h,d,r,n,i,D(l,h,I,r.now,f-1),u,c)}});for(let l of t.keys())m.has(l)||t.delete(l)}function O(e,t,r,n){let i=n;return e?.forEach((s,u)=>{let c=s.id??String(u),l=t.get(c)?.lastRunAt??r;i=Math.min(i,Math.max(1,l+s.everyMs-r))}),i}function P(e,t,r,n){let i=new Set;e?.forEach((s,u)=>{let c=s.id??String(u);i.add(c),t.has(c)||t.set(c,{lastRunAt:n?r:null,pendingCount:0,leadingGeneration:null})});for(let s of t.keys())i.has(s)||t.delete(s)}function D(e,t,r,n,i){return{scheduleId:e.id??t,scheduledAt:r,firedAt:n,nextRunAt:r+e.everyMs,overdueCount:i,effectiveEveryMs:e.everyMs}}function N(e,t,r,n,i,s,u,c,m){if(r.pendingCount>0&&(e.overlap??"skip")==="skip"){r.lastRunAt=u.scheduledAt,m?.({type:"schedule:skip",context:u,reason:"overlap"});return}r.lastRunAt=u.scheduledAt,r.pendingCount+=1,m?.({type:"schedule:start",context:u}),Promise.resolve().then(()=>e.callback(n,s,u)).then(()=>m?.({type:"schedule:end",context:u}),l=>m?.({type:"schedule:error",context:u,error:l})).finally(()=>{c(i)&&(r.pendingCount=Math.max(0,r.pendingCount-1))})}function U(e){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:e.wallNow}}function y(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function w(e,t){let r=y(e,t);return{status:e.status,now:t.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:r,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function L(e,t){return e.status!=="idle"?!1:(e.status="running",e.startedAt=t.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function F(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=y(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function H(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function M(e,t,r={}){return e.generation+=1,e.tick=0,e.status=r.autoStart?"running":"idle",e.startedAt=r.autoStart?t.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=r.autoStart?t.monotonicNow:null,e.now=t.wallNow,!0}function K(e,t){return M(e,t,{autoStart:!0})}function W(e,t,r){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=y(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=r??null,e.now=t.wallNow,!0)}function $(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=y(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function j(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function q(e,t){return{state:U(t),definition:e,endCalledGeneration:null}}function E(e){e.endCalledGeneration=null}function S(e,t){return w(e.state,t)}function z(e,t,r,n){let i=w(e.state,t);if(!e.definition.endWhen?.(i)||!$(e.state,t))return null;let s=w(e.state,t);return re(e,s,r,n),s}function re(e,t,r,n){let i=e.state.generation;if(e.endCalledGeneration!==i){e.endCalledGeneration=i;try{let s=e.definition.onEnd?.(t,r);s&&n&&Promise.resolve(s).catch(u=>n?.(u,t,i))}catch(s){if(n){n(s,t,i);return}throw s}}}function J(e={}){let t=(0,g.useRef)(null);return t.current===null&&(t.current=oe(e)),t.current.setOptions(e),(0,g.useEffect)(()=>{let n=t.current;return e.autoStart&&n.controls.start(),()=>n.destroy()},[]),{...(0,g.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getSnapshot),...t.current.controls}}function oe(e){let t=e;B(t);let r=new Set,n=q(t,T()),i=new Map,s=S(n,T()),u=null,c=(o=T())=>{s=S(n,o),r.forEach(a=>a())},m=()=>{u!==null&&(clearTimeout(u),u=null)},l=(o,a,p={})=>{b(t.diagnostics,{type:o,scope:"timer",...C(a,n.state.generation),...p})},v=(o,a,p)=>{b(t.diagnostics,{type:"callback:error",scope:"timer",error:o,...C(a,p)})},h=(o,a)=>p=>{b(t.diagnostics,{type:p.type,scope:"timer",...p.context,..."reason"in p?{reason:p.reason}:{},..."error"in p?{error:p.error}:{},...C(o,a)})},d=(o=T(),a=!1)=>{if(n.state.status!=="running")return!1;let p=z(n,o,x,v);if(p)return m(),l("timer:end",p),c(o),!0;let R=S(n,o);return G({schedules:t.schedules,states:i,snapshot:R,generation:n.state.generation,controls:x,activation:a,isLive:Q=>n.state.generation===Q,onEvent:h(R,n.state.generation)}),!1},f=()=>{if(m(),n.state.status!=="running")return;let o=O(t.schedules,i,T().wallNow,t.updateIntervalMs??1e3);l("scheduler:start",S(n,T())),u=setTimeout(()=>{if(n.state.status!=="running")return;let a=T();j(n.state,a);let p=S(n,a);l("timer:tick",p),d(a)||(c(a),f())},o)},x={start:()=>{let o=T();if(!L(n.state,o)){n.state.status==="running"&&f();return}l("timer:start",S(n,o)),d(o,!0),c(o),f()},pause:()=>{let o=T();F(n.state,o)&&(m(),l("timer:pause",S(n,o)),c(o))},resume:()=>{let o=T();H(n.state,o)&&(l("timer:resume",S(n,o)),d(o,!0),c(o),f())},reset:(o={})=>{let a=T();m(),M(n.state,a,o),i.clear(),E(n),l("timer:reset",S(n,a)),d(a,o.autoStart),c(a),f()},restart:()=>{let o=T();m(),K(n.state,o),i.clear(),E(n),l("timer:restart",S(n,o)),d(o,!0),c(o),f()},cancel:o=>{let a=T();W(n.state,a,o)&&(m(),l("timer:cancel",S(n,a),{reason:o}),c(a))}};return{controls:x,destroy:m,getSnapshot:()=>s,setOptions:o=>{B(o),t=o,n.definition=o,P(t.schedules,i,T().wallNow,n.state.status==="running")},subscribe:o=>(r.add(o),()=>r.delete(o))}}function B(e){k(e.updateIntervalMs??1e3,"updateIntervalMs"),e.schedules?.forEach(t=>k(t.everyMs,"schedule.everyMs"))}0&&(module.exports={useScheduledTimer});
1
+ "use strict";var M=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var _=(e,t)=>{for(var r in t)M(e,r,{get:t[r],enumerable:!0})},ee=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Y(t))!Z.call(e,i)&&i!==r&&M(e,i,{get:()=>t[i],enumerable:!(n=X(t,i))||n.enumerable});return e};var te=e=>ee(M({},"__esModule",{value:!0}),e);var le={};_(le,{useScheduledTimer:()=>Q});module.exports=te(le);var C=require("react");function m(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function E(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function ne(e){return e?typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger}:{enabled:!1,includeTicks:!1}}function v(e,t){let r=ne(e);!r.enabled||!r.logger||t.type==="timer:tick"&&!r.includeTicks||r.logger({...t,label:t.label??r.label})}function x(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function re(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null}}function P({schedules:e=[],states:t,snapshot:r,generation:n,controls:i,activation:s=!1,isLive:u,onEvent:p}){let d=new Set;e.forEach((a,f)=>{let h=a.id??String(f);d.add(h);let T=t.get(h);if(T||(T=re(),t.set(h,T)),s&&a.leading&&T.leadingGeneration!==n){T.leadingGeneration=n,G(a,h,T,r,n,i,N(a,h,r.now,r.now,0),u,p);return}T.lastRunAt===null&&(T.lastRunAt=r.now);let g=Math.floor((r.now-T.lastRunAt)/a.everyMs);if(g>=1){let b=T.lastRunAt+g*a.everyMs;G(a,h,T,r,n,i,N(a,h,b,r.now,g-1),u,p)}});for(let a of t.keys())d.has(a)||t.delete(a)}function O(e,t,r,n){let i=n;return e?.forEach((s,u)=>{let p=s.id??String(u),a=t.get(p)?.lastRunAt??r;i=Math.min(i,Math.max(1,a+s.everyMs-r))}),i}function U(e,t,r,n){let i=new Set;e?.forEach((s,u)=>{let p=s.id??String(u);i.add(p),t.has(p)||t.set(p,{lastRunAt:n?r:null,pendingCount:0,leadingGeneration:null})});for(let s of t.keys())i.has(s)||t.delete(s)}function I(e){return(e??[]).map((t,r)=>`${t.id??r}:${t.everyMs}:${t.leading??!1}:${t.overlap??"skip"}`).join(",")}function N(e,t,r,n,i){return{scheduleId:e.id??t,scheduledAt:r,firedAt:n,nextRunAt:r+e.everyMs,overdueCount:i,effectiveEveryMs:e.everyMs}}function G(e,t,r,n,i,s,u,p,d){if(r.pendingCount>0&&(e.overlap??"skip")==="skip"){r.lastRunAt=u.scheduledAt,d?.({type:"schedule:skip",context:u,reason:"overlap"});return}r.lastRunAt=u.scheduledAt,r.pendingCount+=1,d?.({type:"schedule:start",context:u}),Promise.resolve().then(()=>e.callback(n,s,u)).then(()=>d?.({type:"schedule:end",context:u}),a=>d?.({type:"schedule:error",context:u,error:a})).finally(()=>{p(i)&&(r.pendingCount=Math.max(0,r.pendingCount-1))})}function $(e){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:e.wallNow}}function k(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function A(e,t){let r=k(e,t);return{status:e.status,now:t.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:r,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function L(e,t){return e.status!=="idle"?!1:(e.status="running",e.startedAt=t.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function F(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=k(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function H(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function R(e,t,r={}){return e.generation+=1,e.tick=0,e.status=r.autoStart?"running":"idle",e.startedAt=r.autoStart?t.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=r.autoStart?t.monotonicNow:null,e.now=t.wallNow,!0}function K(e,t){return R(e,t,{autoStart:!0})}function W(e,t,r){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=k(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=r??null,e.now=t.wallNow,!0)}function j(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=k(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function q(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function z(e,t){return{state:$(t),definition:e,endCalledGeneration:null}}function D(e){e.endCalledGeneration=null}function S(e,t){return A(e.state,t)}function B(e,t,r,n){let i=A(e.state,t);if(!e.definition.endWhen?.(i)||!j(e.state,t))return null;let s=A(e.state,t);return oe(e,s,r,n),s}function oe(e,t,r,n){let i=e.state.generation;if(e.endCalledGeneration!==i){e.endCalledGeneration=i;try{let s=e.definition.onEnd?.(t,r);s&&n&&Promise.resolve(s).catch(u=>n?.(u,t,i))}catch(s){if(n){n(s,t,i);return}throw s}}}function Q(e={}){let t=(0,C.useRef)(null);return t.current===null&&(t.current=ie(e)),t.current.setOptions(e),(0,C.useEffect)(()=>{let n=t.current;return e.autoStart&&n.controls.start(),()=>n.destroy()},[]),{...(0,C.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getSnapshot),...t.current.controls}}function ie(e){let t=e;J(t);let r=new Set,n=z(t,m()),i=new Map,s=S(n,m()),u=null,p=I(t.schedules),d=(o=m())=>{s=S(n,o),r.forEach(l=>l())},a=()=>{u!==null&&(clearTimeout(u),u=null)},f=(o,l,c={})=>{v(t.diagnostics,{type:o,scope:"timer",...x(l,n.state.generation),...c})},h=(o,l,c)=>{t.onError?.(o,l,y),v(t.diagnostics,{type:"callback:error",scope:"timer",error:o,...x(l,c)})},T=(o,l)=>c=>{v(t.diagnostics,{type:c.type,scope:"timer",...c.context,..."reason"in c?{reason:c.reason}:{},..."error"in c?{error:c.error}:{},...x(o,l)})},g=(o=m(),l=!1)=>{if(n.state.status!=="running")return!1;let c=B(n,o,y,h);if(c)return a(),f("timer:end",c),d(o),!0;let w=S(n,o);return P({schedules:t.schedules,states:i,snapshot:w,generation:n.state.generation,controls:y,activation:l,isLive:V=>n.state.generation===V,onEvent:T(w,n.state.generation)}),!1},b=(o=!0)=>{if(a(),n.state.status!=="running")return;let l=O(t.schedules,i,m().wallNow,t.updateIntervalMs??1e3);o&&f("scheduler:start",S(n,m())),u=setTimeout(()=>{if(n.state.status!=="running")return;let c=m();q(n.state,c);let w=S(n,c);f("timer:tick",w),g(c)||(d(c),b())},l)},y={start:()=>{let o=m();if(!L(n.state,o)){n.state.status==="running"&&b();return}f("timer:start",S(n,o)),g(o,!0),d(o),b()},pause:()=>{let o=m();F(n.state,o)&&(a(),f("timer:pause",S(n,o)),d(o))},resume:()=>{let o=m();H(n.state,o)&&(f("timer:resume",S(n,o)),g(o,!0),d(o),b())},reset:(o={})=>{let l=m();a(),R(n.state,l,o),i.clear(),D(n),f("timer:reset",S(n,l)),g(l,o.autoStart),d(l),b()},restart:()=>{let o=m();a(),K(n.state,o),i.clear(),D(n),f("timer:restart",S(n,o)),g(o,!0),d(o),b()},cancel:o=>{let l=m();W(n.state,l,o)&&(a(),f("timer:cancel",S(n,l),{reason:o}),d(l))}};return{controls:y,destroy:a,getSnapshot:()=>s,setOptions:o=>{J(o);let l=I(o.schedules),c=l!==p;t=o,n.definition=o,c&&(p=l,U(t.schedules,i,m().wallNow,n.state.status==="running"),b(!1))},subscribe:o=>(r.add(o),()=>r.delete(o))}}function J(e){E(e.updateIntervalMs??1e3,"updateIntervalMs"),e.schedules?.forEach(t=>E(t.everyMs,"schedule.everyMs"))}0&&(module.exports={useScheduledTimer});
@@ -1,5 +1,5 @@
1
- import { h as UseScheduledTimerOptions, T as TimerSnapshot, a as TimerControls } from './types-DK7omKO-.cjs';
2
- export { i as TimerDiagnostics, j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger, l as TimerSchedule, m as TimerScheduleContext } from './types-DK7omKO-.cjs';
1
+ import { h as UseScheduledTimerOptions, T as TimerSnapshot, a as TimerControls } from './types--o_xW2FP.cjs';
2
+ export { i as TimerDiagnostics, j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger, l as TimerSchedule, m as TimerScheduleContext } from './types--o_xW2FP.cjs';
3
3
 
4
4
  declare function useScheduledTimer(options?: UseScheduledTimerOptions): TimerSnapshot & TimerControls;
5
5
 
@@ -1,5 +1,5 @@
1
- import { h as UseScheduledTimerOptions, T as TimerSnapshot, a as TimerControls } from './types-DK7omKO-.js';
2
- export { i as TimerDiagnostics, j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger, l as TimerSchedule, m as TimerScheduleContext } from './types-DK7omKO-.js';
1
+ import { h as UseScheduledTimerOptions, T as TimerSnapshot, a as TimerControls } from './types--o_xW2FP.js';
2
+ export { i as TimerDiagnostics, j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger, l as TimerSchedule, m as TimerScheduleContext } from './types--o_xW2FP.js';
3
3
 
4
4
  declare function useScheduledTimer(options?: UseScheduledTimerOptions): TimerSnapshot & TimerControls;
5
5
 
package/dist/schedules.js CHANGED
@@ -1 +1 @@
1
- import{a as T,b as f,c as M,d as x,e as N,f as P,g as v,h as i,i as R}from"./chunk-RT4C7DWO.js";import{a as o,b as y,e as k,f as I,g as D,h as O,i as w,j as C,l as U}from"./chunk-I3PNNG3I.js";import{useEffect as q,useRef as z,useSyncExternalStore as A}from"react";function B(c={}){let s=z(null);return s.current===null&&(s.current=H(c)),s.current.setOptions(c),q(()=>{let t=s.current;return c.autoStart&&t.controls.start(),()=>t.destroy()},[]),{...A(s.current.subscribe,s.current.getSnapshot,s.current.getSnapshot),...s.current.controls}}function H(c){let s=c;L(s);let S=new Set,t=P(s,o()),d=new Map,b=i(t,o()),h=null,u=(e=o())=>{b=i(t,e),S.forEach(r=>r())},l=()=>{h!==null&&(clearTimeout(h),h=null)},a=(e,r,n={})=>{T(s.diagnostics,{type:e,scope:"timer",...f(r,t.state.generation),...n})},F=(e,r,n)=>{T(s.diagnostics,{type:"callback:error",scope:"timer",error:e,...f(r,n)})},G=(e,r)=>n=>{T(s.diagnostics,{type:n.type,scope:"timer",...n.context,..."reason"in n?{reason:n.reason}:{},..."error"in n?{error:n.error}:{},...f(e,r)})},p=(e=o(),r=!1)=>{if(t.state.status!=="running")return!1;let n=R(t,e,g,F);if(n)return l(),a("timer:end",n),u(e),!0;let E=i(t,e);return M({schedules:s.schedules,states:d,snapshot:E,generation:t.state.generation,controls:g,activation:r,isLive:j=>t.state.generation===j,onEvent:G(E,t.state.generation)}),!1},m=()=>{if(l(),t.state.status!=="running")return;let e=x(s.schedules,d,o().wallNow,s.updateIntervalMs??1e3);a("scheduler:start",i(t,o())),h=setTimeout(()=>{if(t.state.status!=="running")return;let r=o();U(t.state,r);let n=i(t,r);a("timer:tick",n),p(r)||(u(r),m())},e)},g={start:()=>{let e=o();if(!k(t.state,e)){t.state.status==="running"&&m();return}a("timer:start",i(t,e)),p(e,!0),u(e),m()},pause:()=>{let e=o();I(t.state,e)&&(l(),a("timer:pause",i(t,e)),u(e))},resume:()=>{let e=o();D(t.state,e)&&(a("timer:resume",i(t,e)),p(e,!0),u(e),m())},reset:(e={})=>{let r=o();l(),O(t.state,r,e),d.clear(),v(t),a("timer:reset",i(t,r)),p(r,e.autoStart),u(r),m()},restart:()=>{let e=o();l(),w(t.state,e),d.clear(),v(t),a("timer:restart",i(t,e)),p(e,!0),u(e),m()},cancel:e=>{let r=o();C(t.state,r,e)&&(l(),a("timer:cancel",i(t,r),{reason:e}),u(r))}};return{controls:g,destroy:l,getSnapshot:()=>b,setOptions:e=>{L(e),s=e,t.definition=e,N(s.schedules,d,o().wallNow,t.state.status==="running")},subscribe:e=>(S.add(e),()=>S.delete(e))}}function L(c){y(c.updateIntervalMs??1e3,"updateIntervalMs"),c.schedules?.forEach(s=>y(s.everyMs,"schedule.everyMs"))}export{B as useScheduledTimer};
1
+ import{a as g,b as y,c as N,d as P,e as R,f as E,g as L,h as b,i,j as F}from"./chunk-N626U6HM.js";import{a as o,b as v,e as C,f as D,g as w,h as O,i as U,j as M,l as x}from"./chunk-I3PNNG3I.js";import{useEffect as A,useRef as B,useSyncExternalStore as H}from"react";function J(a={}){let s=B(null);return s.current===null&&(s.current=K(a)),s.current.setOptions(a),A(()=>{let t=s.current;return a.autoStart&&t.controls.start(),()=>t.destroy()},[]),{...H(s.current.subscribe,s.current.getSnapshot,s.current.getSnapshot),...s.current.controls}}function K(a){let s=a;G(s);let S=new Set,t=L(s,o()),d=new Map,k=i(t,o()),h=null,I=E(s.schedules),u=(e=o())=>{k=i(t,e),S.forEach(r=>r())},l=()=>{h!==null&&(clearTimeout(h),h=null)},c=(e,r,n={})=>{g(s.diagnostics,{type:e,scope:"timer",...y(r,t.state.generation),...n})},j=(e,r,n)=>{s.onError?.(e,r,T),g(s.diagnostics,{type:"callback:error",scope:"timer",error:e,...y(r,n)})},q=(e,r)=>n=>{g(s.diagnostics,{type:n.type,scope:"timer",...n.context,..."reason"in n?{reason:n.reason}:{},..."error"in n?{error:n.error}:{},...y(e,r)})},p=(e=o(),r=!1)=>{if(t.state.status!=="running")return!1;let n=F(t,e,T,j);if(n)return l(),c("timer:end",n),u(e),!0;let f=i(t,e);return N({schedules:s.schedules,states:d,snapshot:f,generation:t.state.generation,controls:T,activation:r,isLive:z=>t.state.generation===z,onEvent:q(f,t.state.generation)}),!1},m=(e=!0)=>{if(l(),t.state.status!=="running")return;let r=P(s.schedules,d,o().wallNow,s.updateIntervalMs??1e3);e&&c("scheduler:start",i(t,o())),h=setTimeout(()=>{if(t.state.status!=="running")return;let n=o();x(t.state,n);let f=i(t,n);c("timer:tick",f),p(n)||(u(n),m())},r)},T={start:()=>{let e=o();if(!C(t.state,e)){t.state.status==="running"&&m();return}c("timer:start",i(t,e)),p(e,!0),u(e),m()},pause:()=>{let e=o();D(t.state,e)&&(l(),c("timer:pause",i(t,e)),u(e))},resume:()=>{let e=o();w(t.state,e)&&(c("timer:resume",i(t,e)),p(e,!0),u(e),m())},reset:(e={})=>{let r=o();l(),O(t.state,r,e),d.clear(),b(t),c("timer:reset",i(t,r)),p(r,e.autoStart),u(r),m()},restart:()=>{let e=o();l(),U(t.state,e),d.clear(),b(t),c("timer:restart",i(t,e)),p(e,!0),u(e),m()},cancel:e=>{let r=o();M(t.state,r,e)&&(l(),c("timer:cancel",i(t,r),{reason:e}),u(r))}};return{controls:T,destroy:l,getSnapshot:()=>k,setOptions:e=>{G(e);let r=E(e.schedules),n=r!==I;s=e,t.definition=e,n&&(I=r,R(s.schedules,d,o().wallNow,t.state.status==="running"),m(!1))},subscribe:e=>(S.add(e),()=>S.delete(e))}}function G(a){v(a.updateIntervalMs??1e3,"updateIntervalMs"),a.schedules?.forEach(s=>v(s.everyMs,"schedule.everyMs"))}export{J as useScheduledTimer};
@@ -82,6 +82,7 @@ type UseTimerOptions = {
82
82
  updateIntervalMs?: number;
83
83
  endWhen?: TimerEndPredicate;
84
84
  onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
85
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerControls) => void;
85
86
  };
86
87
  type UseScheduledTimerOptions = UseTimerOptions & {
87
88
  schedules?: TimerSchedule[];
@@ -93,6 +94,7 @@ type TimerGroupItem = {
93
94
  autoStart?: boolean;
94
95
  endWhen?: TimerEndPredicate;
95
96
  onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
97
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void;
96
98
  schedules?: TimerSchedule[];
97
99
  };
98
100
  type UseTimerGroupOptions = {
@@ -82,6 +82,7 @@ type UseTimerOptions = {
82
82
  updateIntervalMs?: number;
83
83
  endWhen?: TimerEndPredicate;
84
84
  onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
85
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerControls) => void;
85
86
  };
86
87
  type UseScheduledTimerOptions = UseTimerOptions & {
87
88
  schedules?: TimerSchedule[];
@@ -93,6 +94,7 @@ type TimerGroupItem = {
93
94
  autoStart?: boolean;
94
95
  endWhen?: TimerEndPredicate;
95
96
  onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
97
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void;
96
98
  schedules?: TimerSchedule[];
97
99
  };
98
100
  type UseTimerGroupOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crup/react-timer-hook",
3
- "version": "0.0.1-alpha.14",
3
+ "version": "0.0.1-alpha.15",
4
4
  "description": "A lightweight React hooks library for building timers, stopwatches, and real-time clocks with minimal boilerplate.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -1 +0,0 @@
1
- import{c as f,d as c,k as p}from"./chunk-I3PNNG3I.js";function y(e){return e?typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger}:{enabled:!1,includeTicks:!1}}function v(e,n){let t=y(e);!t.enabled||!t.logger||n.type==="timer:tick"&&!t.includeTicks||t.logger({...n,label:n.label??t.label})}function k(e,n){return{generation:n,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function b(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null}}function E({schedules:e=[],states:n,snapshot:t,generation:i,controls:r,activation:o=!1,isLive:l,onEvent:d}){let u=new Set;e.forEach((s,C)=>{let m=s.id??String(C);u.add(m);let a=n.get(m);if(a||(a=b(),n.set(m,a)),o&&s.leading&&a.leadingGeneration!==i){a.leadingGeneration=i,g(s,m,a,t,i,r,S(s,m,t.now,t.now,0),l,d);return}a.lastRunAt===null&&(a.lastRunAt=t.now);let T=Math.floor((t.now-a.lastRunAt)/s.everyMs);if(T>=1){let h=a.lastRunAt+T*s.everyMs;g(s,m,a,t,i,r,S(s,m,h,t.now,T-1),l,d)}});for(let s of n.keys())u.has(s)||n.delete(s)}function I(e,n,t,i){let r=i;return e?.forEach((o,l)=>{let d=o.id??String(l),s=n.get(d)?.lastRunAt??t;r=Math.min(r,Math.max(1,s+o.everyMs-t))}),r}function M(e,n,t,i){let r=new Set;e?.forEach((o,l)=>{let d=o.id??String(l);r.add(d),n.has(d)||n.set(d,{lastRunAt:i?t:null,pendingCount:0,leadingGeneration:null})});for(let o of n.keys())r.has(o)||n.delete(o)}function S(e,n,t,i,r){return{scheduleId:e.id??n,scheduledAt:t,firedAt:i,nextRunAt:t+e.everyMs,overdueCount:r,effectiveEveryMs:e.everyMs}}function g(e,n,t,i,r,o,l,d,u){if(t.pendingCount>0&&(e.overlap??"skip")==="skip"){t.lastRunAt=l.scheduledAt,u?.({type:"schedule:skip",context:l,reason:"overlap"});return}t.lastRunAt=l.scheduledAt,t.pendingCount+=1,u?.({type:"schedule:start",context:l}),Promise.resolve().then(()=>e.callback(i,o,l)).then(()=>u?.({type:"schedule:end",context:l}),s=>u?.({type:"schedule:error",context:l,error:s})).finally(()=>{d(r)&&(t.pendingCount=Math.max(0,t.pendingCount-1))})}function w(e,n){return{state:f(n),definition:e,endCalledGeneration:null}}function G(e){e.endCalledGeneration=null}function P(e,n){return c(e.state,n)}function O(e,n,t,i){let r=c(e.state,n);if(!e.definition.endWhen?.(r)||!p(e.state,n))return null;let o=c(e.state,n);return x(e,o,t,i),o}function x(e,n,t,i){let r=e.state.generation;if(e.endCalledGeneration!==r){e.endCalledGeneration=r;try{let o=e.definition.onEnd?.(n,t);o&&i&&Promise.resolve(o).catch(l=>i?.(l,n,r))}catch(o){if(i){i(o,n,r);return}throw o}}}export{v as a,k as b,E as c,I as d,M as e,w as f,G as g,P as h,O as i};