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

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
+ - 🧪 Tested against 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
@@ -36,6 +36,8 @@ npm install @crup/react-timer-hook@alpha
36
36
  pnpm add @crup/react-timer-hook@alpha
37
37
  ```
38
38
 
39
+ Runtime requirements: Node 18+ and React 18+.
40
+
39
41
  ```tsx
40
42
  import { useTimer } from '@crup/react-timer-hook';
41
43
  import { durationParts } from '@crup/react-timer-hook/duration';
@@ -47,9 +49,30 @@ import { useScheduledTimer } from '@crup/react-timer-hook/schedules';
47
49
 
48
50
  Each recipe has a live playground and a focused code sample:
49
51
 
50
- - Basic: [wall clock](https://crup.github.io/react-timer-hook/recipes/basic/wall-clock/), [stopwatch](https://crup.github.io/react-timer-hook/recipes/basic/stopwatch/), [absolute countdown](https://crup.github.io/react-timer-hook/recipes/basic/absolute-countdown/), [pausable countdown](https://crup.github.io/react-timer-hook/recipes/basic/pausable-countdown/), [manual controls](https://crup.github.io/react-timer-hook/recipes/basic/manual-controls/)
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
- - 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/)
52
+ - Basic: [wall clock](https://crup.github.io/react-timer-hook/recipes/basic/wall-clock/), [stopwatch](https://crup.github.io/react-timer-hook/recipes/basic/stopwatch/), [absolute countdown](https://crup.github.io/react-timer-hook/recipes/basic/absolute-countdown/), [pausable countdown](https://crup.github.io/react-timer-hook/recipes/basic/pausable-countdown/), [OTP resend cooldown](https://crup.github.io/react-timer-hook/recipes/basic/otp-resend/), [manual controls](https://crup.github.io/react-timer-hook/recipes/basic/manual-controls/)
53
+ - 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/), [autosave heartbeat](https://crup.github.io/react-timer-hook/recipes/intermediate/autosave-heartbeat/), [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/)
54
+ - 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/), [checkout holds](https://crup.github.io/react-timer-hook/recipes/advanced/checkout-holds/), [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/), [toast auto-dismiss](https://crup.github.io/react-timer-hook/recipes/advanced/toast-auto-dismiss/)
55
+
56
+ ## Use cases
57
+
58
+ | Product case | Use | Import | Recipe |
59
+ | --- | --- | --- | --- |
60
+ | Stopwatch, call timer, workout timer | Core | `@crup/react-timer-hook` | [Stopwatch](https://crup.github.io/react-timer-hook/recipes/basic/stopwatch/) |
61
+ | Wall clock or "last updated" display | Core | `@crup/react-timer-hook` | [Wall clock](https://crup.github.io/react-timer-hook/recipes/basic/wall-clock/) |
62
+ | Auction, reservation, or job deadline | Core | `@crup/react-timer-hook` | [Absolute countdown](https://crup.github.io/react-timer-hook/recipes/basic/absolute-countdown/) |
63
+ | 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/) |
64
+ | OTP resend or retry cooldown | Core + duration | `@crup/react-timer-hook` + `/duration` | [OTP resend cooldown](https://crup.github.io/react-timer-hook/recipes/basic/otp-resend/) |
65
+ | Backend status polling | Schedules | `@crup/react-timer-hook/schedules` | [Polling schedule](https://crup.github.io/react-timer-hook/recipes/intermediate/polling-schedule/) |
66
+ | Draft autosave or presence heartbeat | Schedules | `@crup/react-timer-hook/schedules` | [Autosave heartbeat](https://crup.github.io/react-timer-hook/recipes/intermediate/autosave-heartbeat/) |
67
+ | 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/) |
68
+ | 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/) |
69
+ | Checkout holds with independent controls | Timer group | `@crup/react-timer-hook/group` | [Checkout holds](https://crup.github.io/react-timer-hook/recipes/advanced/checkout-holds/) |
70
+ | 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/) |
71
+ | Toast expiry or runtime item timers | Timer group | `@crup/react-timer-hook/group` | [Toast auto-dismiss](https://crup.github.io/react-timer-hook/recipes/advanced/toast-auto-dismiss/) |
72
+
73
+ See the full use-case guide: https://crup.github.io/react-timer-hook/use-cases/
74
+
75
+ Design assumptions and runtime limits: https://crup.github.io/react-timer-hook/project/caveats/
53
76
 
54
77
  ## Quick examples
55
78
 
@@ -152,6 +175,7 @@ const timers = useTimerGroup({
152
175
  | `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
176
  | `endWhen` | `(snapshot) => boolean` | No | Ends the lifecycle when it returns `true`. Use this for countdowns, timeouts, and custom stop conditions. |
154
177
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per generation when `endWhen` ends the lifecycle. `restart()` creates a new generation. |
178
+ | `onError` | `(error, snapshot, controls) => void` | No | Handles sync throws and async rejections from `onEnd`. Also used as the fallback for schedule callback failures when a schedule does not define `onError`. |
155
179
 
156
180
  ### `useScheduledTimer()` settings
157
181
 
@@ -163,6 +187,7 @@ Import from `@crup/react-timer-hook/schedules` when you need polling or schedule
163
187
  | `updateIntervalMs` | `number` | No | Render/update cadence in milliseconds. Defaults to `1000`. Scheduled callbacks can run on their own cadence. |
164
188
  | `endWhen` | `(snapshot) => boolean` | No | Ends the lifecycle when it returns `true`. |
165
189
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per generation when `endWhen` ends the lifecycle. |
190
+ | `onError` | `(error, snapshot, controls) => void` | No | Handles sync throws and async rejections from `onEnd`. |
166
191
  | `schedules` | `TimerSchedule[]` | No | Scheduled side effects that run while the timer is active. Async overlap defaults to `skip`. |
167
192
  | `diagnostics` | `TimerDiagnostics` | No | Optional lifecycle and schedule events. No logs are emitted unless you pass a logger. |
168
193
 
@@ -175,6 +200,7 @@ Import from `@crup/react-timer-hook/schedules` when you need polling or schedule
175
200
  | `leading` | `boolean` | No | Runs the schedule immediately when the timer starts or resumes into a new generation. Defaults to `false`. |
176
201
  | `overlap` | `'skip' \| 'allow'` | No | Controls async overlap. Defaults to `skip`, so a pending callback prevents another run. |
177
202
  | `callback` | `(snapshot, controls, context) => void \| Promise<void>` | Yes | Scheduled side effect. Receives timing context with `scheduledAt`, `firedAt`, `nextRunAt`, `overdueCount`, and `effectiveEveryMs`. |
203
+ | `onError` | `(error, snapshot, controls, context) => void` | No | Handles sync throws and async rejections from that schedule's `callback`. Falls back to the timer or item `onError` when omitted. |
178
204
 
179
205
  ### `useTimerGroup()` settings
180
206
 
@@ -194,6 +220,7 @@ Import from `@crup/react-timer-hook/group` when many keyed items need independen
194
220
  | `autoStart` | `boolean` | No | Starts the item automatically when it is added or synced. Defaults to `false`. |
195
221
  | `endWhen` | `(snapshot) => boolean` | No | Ends that item when it returns `true`. |
196
222
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per item generation when that item ends naturally. |
223
+ | `onError` | `(error, snapshot, controls) => void` | No | Handles sync throws and async rejections from that item's `onEnd`. Also used as the fallback for that item's schedule callback failures. |
197
224
  | `schedules` | `TimerSchedule[]` | No | Per-item schedules with the same contract as `useScheduledTimer()`. |
198
225
 
199
226
  ### Values and controls
@@ -227,9 +254,9 @@ The default import stays small. Add the other pieces only when that screen needs
227
254
 
228
255
  | Piece | Import | Best for | Raw | Gzip | Brotli |
229
256
  | --- | --- | --- | ---: | ---: | ---: |
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 |
257
+ | ⏱️ Core | `@crup/react-timer-hook` | Stopwatch, countdown, clock, custom lifecycle | 4.44 kB | 1.52 kB | 1.40 kB |
258
+ | 🧭 Timer group | `@crup/react-timer-hook/group` | Many independent row/item timers | 10.93 kB | 3.83 kB | 3.50 kB |
259
+ | 📡 Schedules | `@crup/react-timer-hook/schedules` | Polling, cadence callbacks, overdue timing context | 8.62 kB | 3.02 kB | 2.78 kB |
233
260
  | 🧩 Duration | `@crup/react-timer-hook/duration` | `days`, `hours`, `minutes`, `seconds`, `milliseconds` | 318 B | 224 B | 192 B |
234
261
  | 🔎 Diagnostics | `@crup/react-timer-hook/diagnostics` | Optional lifecycle and schedule event logging | 105 B | 115 B | 90 B |
235
262
 
@@ -271,4 +298,4 @@ Issues, recipes, docs improvements, and focused bug reports are welcome.
271
298
  - Open an issue: https://github.com/crup/react-timer-hook/issues
272
299
  - See the contributing guide: ./CONTRIBUTING.md
273
300
 
274
- The package targets Node 24 for development and React 18+ as a peer dependency.
301
+ The package targets Node 18+ and React 18+.
@@ -0,0 +1 @@
1
+ import{c as C,d as y,e as T,l as b}from"./chunk-XXJAJJJ6.js";function E(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 M(e,n){let t=E(e);!t.enabled||!t.logger||n.type==="timer:tick"&&!t.includeTicks||t.logger({...n,label:n.label??t.label})}function R(e,n){return{generation:n,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function k(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null,signature:""}}function G({schedules:e=[],states:n,snapshot:t,generation:i,controls:r,activation:o=!1,isLive:s,onError:a,onEvent:m}){let u=new Set;e.forEach((l,h)=>{let c=f(l,h);u.add(c);let d=n.get(c);if(d||(d=k(),d.signature=g(l,h),n.set(c,d)),o&&l.leading&&d.leadingGeneration!==i){d.leadingGeneration=i,x(l,c,d,t,i,r,v(l,c,t.now,t.now,0),s,a,m);return}d.lastRunAt===null&&(d.lastRunAt=t.now);let p=Math.floor((t.now-d.lastRunAt)/l.everyMs);if(p>=1){let D=d.lastRunAt+p*l.everyMs;x(l,c,d,t,i,r,v(l,c,D,t.now,p-1),s,a,m)}});for(let l of n.keys())u.has(l)||n.delete(l)}function P(e,n,t,i){let r=i;return e?.forEach((o,s)=>{let a=f(o,s),u=n.get(a)?.lastRunAt??t;r=Math.min(r,Math.max(1,u+o.everyMs-t))}),r}function O(e,n,t,i){let r=new Set;e?.forEach((o,s)=>{let a=f(o,s),m=g(o,s);r.add(a);let u=n.get(a);if(u)u.signature!==m&&(u.lastRunAt=i?t:null,u.leadingGeneration=null,u.signature=m);else{let l=k();l.lastRunAt=i?t:null,l.signature=m,n.set(a,l)}});for(let o of n.keys())r.has(o)||n.delete(o)}function N(e){return JSON.stringify((e??[]).map((n,t)=>g(n,t)))}function H(e){let n=new Set;e?.forEach((t,i)=>{C(t.everyMs,"schedule.everyMs");let r=f(t,i);if(n.has(r))throw new Error(`Duplicate schedule id "${r}"`);n.add(r)})}function v(e,n,t,i,r){return{scheduleId:e.id??n,scheduledAt:t,firedAt:i,nextRunAt:t+e.everyMs,overdueCount:r,effectiveEveryMs:e.everyMs}}function x(e,n,t,i,r,o,s,a,m,u){if(t.pendingCount>0&&(e.overlap??"skip")==="skip"){t.lastRunAt=s.scheduledAt,S(a,r,u,{type:"schedule:skip",context:s,reason:"overlap"});return}t.lastRunAt=s.scheduledAt,t.pendingCount+=1,S(a,r,u,{type:"schedule:start",context:s}),Promise.resolve().then(()=>e.callback(i,o,s)).then(()=>S(a,r,u,{type:"schedule:end",context:s}),l=>{if(a(r))try{e.onError?e.onError(l,i,o,s):m?.(l,i,o,s)}finally{u?.({type:"schedule:error",context:s,error:l})}}).finally(()=>{a(r)&&(t.pendingCount=Math.max(0,t.pendingCount-1))})}function f(e,n){return e.id??String(n)}function g(e,n){return JSON.stringify([e.id??n,e.everyMs,e.leading??!1,e.overlap??"skip"])}function S(e,n,t,i){e(n)&&t?.(i)}function W(e,n){return{state:y(n),definition:e,endCalledGeneration:null}}function F(e){e.endCalledGeneration=null}function $(e,n){return T(e.state,n)}function j(e,n,t,i){let r=T(e.state,n);if(!e.definition.endWhen?.(r)||!b(e.state,n))return null;let o=T(e.state,n);return I(e,o,t,i),o}function I(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(s=>i?.(s,n,r))}catch(o){if(i){i(o,n,r);return}throw o}}}export{M as a,R as b,G as c,P as d,O as e,N as f,H as g,W as h,F as i,$ as j,j as k};
@@ -0,0 +1 @@
1
+ function o(n,e){return{start:()=>{e()&&n.start()},pause:()=>{e()&&n.pause()},resume:()=>{e()&&n.resume()},reset:t=>{e()&&n.reset(t)},restart:()=>{e()&&n.restart()},cancel:t=>{e()&&n.cancel(t)}}}function u(){let n=Date.now(),e=typeof performance<"u"&&typeof performance.now=="function"?performance.now():n;return{wallNow:n,monotonicNow:e}}function i(n,e){if(!Number.isFinite(n)||n<=0)throw new RangeError(`${e} must be a finite number greater than 0`)}function c(n){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:n.wallNow}}function r(n,e){return n.status!=="running"||n.activeStartedAtMonotonic===null?n.baseElapsedMilliseconds:Math.max(0,n.baseElapsedMilliseconds+e.monotonicNow-n.activeStartedAtMonotonic)}function s(n,e){let t=r(n,e);return{status:n.status,now:e.wallNow,tick:n.tick,startedAt:n.startedAt,pausedAt:n.pausedAt,endedAt:n.endedAt,cancelledAt:n.cancelledAt,cancelReason:n.cancelReason,elapsedMilliseconds:t,isIdle:n.status==="idle",isRunning:n.status==="running",isPaused:n.status==="paused",isEnded:n.status==="ended",isCancelled:n.status==="cancelled"}}function m(n,e){return n.status!=="idle"?!1:(n.status="running",n.startedAt=e.wallNow,n.pausedAt=null,n.endedAt=null,n.cancelledAt=null,n.cancelReason=null,n.activeStartedAtMonotonic=e.monotonicNow,n.now=e.wallNow,!0)}function p(n,e){return n.status!=="running"?!1:(n.baseElapsedMilliseconds=r(n,e),n.activeStartedAtMonotonic=null,n.status="paused",n.pausedAt=e.wallNow,n.now=e.wallNow,!0)}function w(n,e){return n.status!=="paused"?!1:(n.status="running",n.pausedAt=null,n.activeStartedAtMonotonic=e.monotonicNow,n.now=e.wallNow,!0)}function l(n,e,t={}){return n.generation+=1,n.tick=0,n.status=t.autoStart?"running":"idle",n.startedAt=t.autoStart?e.wallNow:null,n.pausedAt=null,n.endedAt=null,n.cancelledAt=null,n.cancelReason=null,n.baseElapsedMilliseconds=0,n.activeStartedAtMonotonic=t.autoStart?e.monotonicNow:null,n.now=e.wallNow,!0}function f(n,e){return l(n,e,{autoStart:!0})}function S(n,e,t){return n.status!=="running"&&n.status!=="paused"?!1:(n.baseElapsedMilliseconds=r(n,e),n.activeStartedAtMonotonic=null,n.status="cancelled",n.cancelledAt=e.wallNow,n.cancelReason=t??null,n.now=e.wallNow,!0)}function A(n,e){return n.status!=="running"?!1:(n.baseElapsedMilliseconds=r(n,e),n.activeStartedAtMonotonic=null,n.status="ended",n.endedAt=e.wallNow,n.now=e.wallNow,!0)}function b(n,e){return n.status!=="running"?!1:(n.tick+=1,n.now=e.wallNow,!0)}export{o as a,u as b,i as c,c as d,s as e,m as f,p as g,w as h,l as i,f as j,S as k,A as l,b as m};
@@ -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-D-Vzr-PF.cjs';
2
+ export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types-D-Vzr-PF.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-D-Vzr-PF.js';
2
+ export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types-D-Vzr-PF.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-D-Vzr-PF.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-D-Vzr-PF.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 B=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var Ge=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var Me=(e,t)=>{for(var o in t)B(e,o,{get:t[o],enumerable:!0})},Ne=(e,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let l of Ge(t))!Re.call(e,l)&&l!==o&&B(e,l,{get:()=>t[l],enumerable:!(i=Ee(t,l))||i.enumerable});return e};var De=e=>Ne(B({},"__esModule",{value:!0}),e);var ze={};Me(ze,{useTimerGroup:()=>we});module.exports=De(ze);var x=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 N(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function Q(e,t){return{start:()=>{t()&&e.start()},pause:()=>{t()&&e.pause()},resume:()=>{t()&&e.resume()},reset:o=>{t()&&e.reset(o)},restart:()=>{t()&&e.restart()},cancel:o=>{t()&&e.cancel(o)}}}function Oe(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 D(e,t){let o=Oe(e);!o.enabled||!o.logger||t.type==="timer:tick"&&!o.includeTicks||o.logger({...t,label:t.label??o.label})}function O(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function ie(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null,signature:""}}function se({schedules:e=[],states:t,snapshot:o,generation:i,controls:l,activation:c=!1,isLive:d,onError:p,onEvent:h}){let m=new Set;e.forEach((u,A)=>{let f=P(u,A);m.add(f);let y=t.get(f);if(y||(y=ie(),y.signature=X(u,A),t.set(f,y)),c&&u.leading&&y.leadingGeneration!==i){y.leadingGeneration=i,oe(u,f,y,o,i,l,re(u,f,o.now,o.now,0),d,p,h);return}y.lastRunAt===null&&(y.lastRunAt=o.now);let G=Math.floor((o.now-y.lastRunAt)/u.everyMs);if(G>=1){let M=y.lastRunAt+G*u.everyMs;oe(u,f,y,o,i,l,re(u,f,M,o.now,G-1),d,p,h)}});for(let u of t.keys())m.has(u)||t.delete(u)}function le(e,t,o,i){let l=i;return e?.forEach((c,d)=>{let p=P(c,d),m=t.get(p)?.lastRunAt??o;l=Math.min(l,Math.max(1,m+c.everyMs-o))}),l}function ae(e,t,o,i){let l=new Set;e?.forEach((c,d)=>{let p=P(c,d),h=X(c,d);l.add(p);let m=t.get(p);if(m)m.signature!==h&&(m.lastRunAt=i?o:null,m.leadingGeneration=null,m.signature=h);else{let u=ie();u.lastRunAt=i?o:null,u.signature=h,t.set(p,u)}});for(let c of t.keys())l.has(c)||t.delete(c)}function ue(e){return JSON.stringify((e??[]).map((t,o)=>X(t,o)))}function ce(e){let t=new Set;e?.forEach((o,i)=>{N(o.everyMs,"schedule.everyMs");let l=P(o,i);if(t.has(l))throw new Error(`Duplicate schedule id "${l}"`);t.add(l)})}function re(e,t,o,i,l){return{scheduleId:e.id??t,scheduledAt:o,firedAt:i,nextRunAt:o+e.everyMs,overdueCount:l,effectiveEveryMs:e.everyMs}}function oe(e,t,o,i,l,c,d,p,h,m){if(o.pendingCount>0&&(e.overlap??"skip")==="skip"){o.lastRunAt=d.scheduledAt,V(p,l,m,{type:"schedule:skip",context:d,reason:"overlap"});return}o.lastRunAt=d.scheduledAt,o.pendingCount+=1,V(p,l,m,{type:"schedule:start",context:d}),Promise.resolve().then(()=>e.callback(i,c,d)).then(()=>V(p,l,m,{type:"schedule:end",context:d}),u=>{if(p(l))try{e.onError?e.onError(u,i,c,d):h?.(u,i,c,d)}finally{m?.({type:"schedule:error",context:d,error:u})}}).finally(()=>{p(l)&&(o.pendingCount=Math.max(0,o.pendingCount-1))})}function P(e,t){return e.id??String(t)}function X(e,t){return JSON.stringify([e.id??t,e.everyMs,e.leading??!1,e.overlap??"skip"])}function V(e,t,o,i){e(t)&&o?.(i)}function de(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 U(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function z(e,t){let o=U(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 F(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 me(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=U(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function pe(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function Y(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 fe(e,t){return Y(e,t,{autoStart:!0})}function Te(e,t,o){return e.status!=="running"&&e.status!=="paused"?!1:(e.baseElapsedMilliseconds=U(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=o??null,e.now=t.wallNow,!0)}function Se(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=U(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function ge(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function he(e,t){return{state:de(t),definition:e,endCalledGeneration:null}}function Z(e){e.endCalledGeneration=null}function C(e,t){return z(e.state,t)}function ye(e,t,o,i){let l=z(e.state,t);if(!e.definition.endWhen?.(l)||!Se(e.state,t))return null;let c=z(e.state,t);return Pe(e,c,o,i),c}function Pe(e,t,o,i){let l=e.state.generation;if(e.endCalledGeneration!==l){e.endCalledGeneration=l;try{let c=e.definition.onEnd?.(t,o);c&&i&&Promise.resolve(c).catch(d=>i?.(d,t,l))}catch(c){if(i){i(c,t,l);return}throw c}}}function we(e={}){let t=(0,x.useRef)(null);return t.current===null&&(t.current=Ue(e)),t.current.setOptions(e),(0,x.useEffect)(()=>{t.current?.commitOptions()}),(0,x.useEffect)(()=>{let i=t.current;return()=>i.destroy()},[]),{...(0,x.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getServerSnapshot),get:t.current.getTimer,...t.current.controls}}function Ue(e){let t=e;L(t);let o=new Set,i=new Map,l=T(),c=_(i,l.wallNow),d=c,p=null,h=$(t),m=!0,u=(n=T())=>{l=n,c=_(i,n.wallNow),o.forEach(r=>r())},A=()=>{p!==null&&(clearTimeout(p),p=null)},f=(n,r,s,a={})=>{D(t.diagnostics,{type:n,scope:"timer-group",timerId:r?.id,...O(s,r?.state.generation??0),...a})},y=n=>(r,s,a)=>{let S=Q(M(n.id),()=>i.get(n.id)===n&&n.state.generation===a);n.definition.onError?.(r,s,S),D(t.diagnostics,{type:"callback:error",scope:"timer-group",timerId:n.id,error:r,...O(s,a)})},G=(n,r,s)=>a=>{D(t.diagnostics,{type:a.type,scope:"timer-group",timerId:n.id,...a.context,..."reason"in a?{reason:a.reason}:{},..."error"in a?{error:a.error}:{},...O(r,s)})},M=n=>({start:()=>H(n),pause:()=>J(n),resume:()=>K(n),reset:r=>W(n,r),restart:()=>q(n),cancel:r=>j(n,r)}),v=(n,r=T(),s=!1)=>{if(n.state.status!=="running")return!1;let a=n.state.generation,S=Q(M(n.id),()=>i.get(n.id)===n&&n.state.generation===a),b=ye(n,r,S,y(n));if(b)return f("timer:end",n,b),!0;let g=C(n,r);return se({schedules:n.definition.schedules,states:n.schedules,snapshot:g,generation:n.state.generation,controls:S,activation:s,isLive:I=>i.get(n.id)===n&&n.state.generation===I,onError:(I,k,E)=>n.definition.onError?.(I,k,E),onEvent:G(n,g,n.state.generation)}),!1},w=(n=!0)=>{A();let r=Array.from(i.values()).filter(S=>S.state.status==="running");if(r.length===0)return;let s=T(),a=t.updateIntervalMs??1e3;for(let S of r)a=Math.min(a,le(S.definition.schedules,S.schedules,s.wallNow,a));n&&f("scheduler:start",r[0],C(r[0],s)),p=setTimeout(()=>{let S=T();for(let b of i.values()){if(b.state.status!=="running")continue;ge(b.state,S);let g=C(b,S);f("timer:tick",b,g),v(b,S)}u(S),w()},a)},te=n=>{let r=i.get(n.id);if(r)return r.definition=n,R(r,T().wallNow),{item:r,added:!1};let s=T(),a={...he(n,s),id:n.id,schedules:new Map};return i.set(n.id,a),R(a,s.wallNow),{item:a,added:!0}},ne=(n={})=>{let r=n.notify??!0,s=n.process??!0,a=n.reschedule??!0,S=n.autoStart??!0;L(t);let b=new Set,g=!1,I=T();if(t.items){for(let k of t.items){b.add(k.id);let{item:E,added:Ae}=te(k);g=g||Ae,S&&k.autoStart&&E.state.status==="idle"&&F(E.state,I)&&(g=!0,s&&(g=v(E,I,!0)||g)),s&&(g=v(E,I)||g)}for(let k of i.keys())b.has(k)||(i.delete(k),g=!0)}g&&(r?u(I):(l=I,c=_(i,I.wallNow))),(g||a)&&w(r)},be=n=>{if(ee([n]),i.has(n.id))throw new Error(`Timer item "${n.id}" already exists`);let{item:r}=te(n),s=T();n.autoStart&&F(r.state,s)&&v(r,s,!0),h=$(t),u(s),w()},Ce=(n,r)=>{let s=i.get(n);if(!s)return;let a={...s.definition,...r,id:n};ee([a]),s.definition=a,R(s,T().wallNow),v(s),h=$(t),u(),w()},Ie=n=>{i.delete(n)&&(u(),w())},ve=()=>{i.clear(),A(),u()},H=n=>{let r=i.get(n);if(!r)return;let s=T();F(r.state,s)&&(f("timer:start",r,C(r,s)),v(r,s,!0),u(s),w())},J=n=>{let r=i.get(n);if(!r)return;let s=T();me(r.state,s)&&(f("timer:pause",r,C(r,s)),u(s),w())},K=n=>{let r=i.get(n);if(!r)return;let s=T();pe(r.state,s)&&(f("timer:resume",r,C(r,s)),v(r,s,!0),u(s),w())},W=(n,r={})=>{let s=i.get(n);if(!s)return;let a=T();Y(s.state,a,r),s.schedules.clear(),R(s,a.wallNow),Z(s),f("timer:reset",s,C(s,a)),v(s,a,r.autoStart),u(a),w()},q=n=>{let r=i.get(n);if(!r)return;let s=T();fe(r.state,s),r.schedules.clear(),R(r,s.wallNow),Z(r),f("timer:restart",r,C(r,s)),v(r,s,!0),u(s),w()},j=(n,r)=>{let s=i.get(n);if(!s)return;let a=T();Te(s.state,a,r)&&(f("timer:cancel",s,C(s,a),{reason:r}),u(a),w())},ke=n=>{let r=i.get(n);return r?C(r,l):void 0},xe={add:be,update:Ce,remove:Ie,clear:ve,start:H,pause:J,resume:K,reset:W,restart:q,cancel:j,startAll:()=>Array.from(i.keys()).forEach(H),pauseAll:()=>Array.from(i.keys()).forEach(J),resumeAll:()=>Array.from(i.keys()).forEach(K),resetAll:n=>Array.from(i.keys()).forEach(r=>W(r,n)),restartAll:()=>Array.from(i.keys()).forEach(q),cancelAll:n=>Array.from(i.keys()).forEach(r=>j(r,n))};return ne({notify:!1,process:!1,reschedule:!1,autoStart:!1}),{commitOptions:()=>{m&&(m=!1,ne({notify:!0,process:!0,reschedule:!0,autoStart:!0}))},controls:xe,destroy:A,getSnapshot:()=>c,getServerSnapshot:()=>d,getTimer:ke,setOptions:n=>{L(n);let r=$(n);m=m||n.items!==t.items||r!==h,t=n,h=r},subscribe:n=>(o.add(n),()=>o.delete(n))}}function _(e,t){return{now:t,size:e.size,ids:Array.from(e.keys())}}function R(e,t){ae(e.definition.schedules,e.schedules,t,e.state.status==="running")}function $(e){return JSON.stringify([e.updateIntervalMs??1e3,...(e.items??[]).map(t=>{let o=ue(t.schedules);return[t.id,t.autoStart??!1,o??""]})])}function L(e){N(e.updateIntervalMs??1e3,"updateIntervalMs"),ee(e.items)}function ee(e){let t=new Set;e?.forEach(o=>{if(!o.id)throw new Error("Timer item id is required");if(t.has(o.id))throw new Error(`Duplicate timer item id "${o.id}"`);t.add(o.id),ce(o.schedules)})}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-D-Vzr-PF.cjs';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-D-Vzr-PF.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-D-Vzr-PF.js';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-D-Vzr-PF.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 A,b as N,c as Z,d as _,e as ee,f as te,g as re,h as se,i as L,j as f,k as oe}from"./chunk-OYRPLLEV.js";import{a as D,b as a,c as H,f as b,g as K,h as Q,i as V,j as W,k as X,m as Y}from"./chunk-XXJAJJJ6.js";import{useEffect as ne,useRef as he,useSyncExternalStore as Se}from"react";function Te(i={}){let o=he(null);return o.current===null&&(o.current=ye(i)),o.current.setOptions(i),ne(()=>{o.current?.commitOptions()}),ne(()=>{let n=o.current;return()=>n.destroy()},[]),{...Se(o.current.subscribe,o.current.getSnapshot,o.current.getServerSnapshot),get:o.current.getTimer,...o.current.controls}}function ye(i){let o=i;q(o);let l=new Set,n=new Map,G=a(),w=$(n,G.wallNow),ie=w,k=null,v=R(o),E=!0,m=(e=a())=>{G=e,w=$(n,e.wallNow),l.forEach(t=>t())},C=()=>{k!==null&&(clearTimeout(k),k=null)},h=(e,t,r,s={})=>{A(o.diagnostics,{type:e,scope:"timer-group",timerId:t?.id,...N(r,t?.state.generation??0),...s})},ae=e=>(t,r,s)=>{let u=D(J(e.id),()=>n.get(e.id)===e&&e.state.generation===s);e.definition.onError?.(t,r,u),A(o.diagnostics,{type:"callback:error",scope:"timer-group",timerId:e.id,error:t,...N(r,s)})},ue=(e,t,r)=>s=>{A(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}:{},...N(t,r)})},J=e=>({start:()=>O(e),pause:()=>M(e),resume:()=>P(e),reset:t=>x(e,t),restart:()=>U(e),cancel:t=>z(e,t)}),S=(e,t=a(),r=!1)=>{if(e.state.status!=="running")return!1;let s=e.state.generation,u=D(J(e.id),()=>n.get(e.id)===e&&e.state.generation===s),p=oe(e,t,u,ae(e));if(p)return h("timer:end",e,p),!0;let c=f(e,t);return Z({schedules:e.definition.schedules,states:e.schedules,snapshot:c,generation:e.state.generation,controls:u,activation:r,isLive:g=>n.get(e.id)===e&&e.state.generation===g,onError:(g,T,y)=>e.definition.onError?.(g,T,y),onEvent:ue(e,c,e.state.generation)}),!1},d=(e=!0)=>{C();let t=Array.from(n.values()).filter(u=>u.state.status==="running");if(t.length===0)return;let r=a(),s=o.updateIntervalMs??1e3;for(let u of t)s=Math.min(s,_(u.definition.schedules,u.schedules,r.wallNow,s));e&&h("scheduler:start",t[0],f(t[0],r)),k=setTimeout(()=>{let u=a();for(let p of n.values()){if(p.state.status!=="running")continue;Y(p.state,u);let c=f(p,u);h("timer:tick",p,c),S(p,u)}m(u),d()},s)},j=e=>{let t=n.get(e.id);if(t)return t.definition=e,I(t,a().wallNow),{item:t,added:!1};let r=a(),s={...se(e,r),id:e.id,schedules:new Map};return n.set(e.id,s),I(s,r.wallNow),{item:s,added:!0}},B=(e={})=>{let t=e.notify??!0,r=e.process??!0,s=e.reschedule??!0,u=e.autoStart??!0;q(o);let p=new Set,c=!1,g=a();if(o.items){for(let T of o.items){p.add(T.id);let{item:y,added:ge}=j(T);c=c||ge,u&&T.autoStart&&y.state.status==="idle"&&b(y.state,g)&&(c=!0,r&&(c=S(y,g,!0)||c)),r&&(c=S(y,g)||c)}for(let T of n.keys())p.has(T)||(n.delete(T),c=!0)}c&&(t?m(g):(G=g,w=$(n,g.wallNow))),(c||s)&&d(t)},ce=e=>{if(F([e]),n.has(e.id))throw new Error(`Timer item "${e.id}" already exists`);let{item:t}=j(e),r=a();e.autoStart&&b(t.state,r)&&S(t,r,!0),v=R(o),m(r),d()},le=(e,t)=>{let r=n.get(e);if(!r)return;let s={...r.definition,...t,id:e};F([s]),r.definition=s,I(r,a().wallNow),S(r),v=R(o),m(),d()},me=e=>{n.delete(e)&&(m(),d())},de=()=>{n.clear(),C(),m()},O=e=>{let t=n.get(e);if(!t)return;let r=a();b(t.state,r)&&(h("timer:start",t,f(t,r)),S(t,r,!0),m(r),d())},M=e=>{let t=n.get(e);if(!t)return;let r=a();K(t.state,r)&&(h("timer:pause",t,f(t,r)),m(r),d())},P=e=>{let t=n.get(e);if(!t)return;let r=a();Q(t.state,r)&&(h("timer:resume",t,f(t,r)),S(t,r,!0),m(r),d())},x=(e,t={})=>{let r=n.get(e);if(!r)return;let s=a();V(r.state,s,t),r.schedules.clear(),I(r,s.wallNow),L(r),h("timer:reset",r,f(r,s)),S(r,s,t.autoStart),m(s),d()},U=e=>{let t=n.get(e);if(!t)return;let r=a();W(t.state,r),t.schedules.clear(),I(t,r.wallNow),L(t),h("timer:restart",t,f(t,r)),S(t,r,!0),m(r),d()},z=(e,t)=>{let r=n.get(e);if(!r)return;let s=a();X(r.state,s,t)&&(h("timer:cancel",r,f(r,s),{reason:t}),m(s),d())},pe=e=>{let t=n.get(e);return t?f(t,G):void 0},fe={add:ce,update:le,remove:me,clear:de,start:O,pause:M,resume:P,reset:x,restart:U,cancel:z,startAll:()=>Array.from(n.keys()).forEach(O),pauseAll:()=>Array.from(n.keys()).forEach(M),resumeAll:()=>Array.from(n.keys()).forEach(P),resetAll:e=>Array.from(n.keys()).forEach(t=>x(t,e)),restartAll:()=>Array.from(n.keys()).forEach(U),cancelAll:e=>Array.from(n.keys()).forEach(t=>z(t,e))};return B({notify:!1,process:!1,reschedule:!1,autoStart:!1}),{commitOptions:()=>{E&&(E=!1,B({notify:!0,process:!0,reschedule:!0,autoStart:!0}))},controls:fe,destroy:C,getSnapshot:()=>w,getServerSnapshot:()=>ie,getTimer:pe,setOptions:e=>{q(e);let t=R(e);E=E||e.items!==o.items||t!==v,o=e,v=t},subscribe:e=>(l.add(e),()=>l.delete(e))}}function $(i,o){return{now:o,size:i.size,ids:Array.from(i.keys())}}function I(i,o){ee(i.definition.schedules,i.schedules,o,i.state.status==="running")}function R(i){return JSON.stringify([i.updateIntervalMs??1e3,...(i.items??[]).map(o=>{let l=te(o.schedules);return[o.id,o.autoStart??!1,l??""]})])}function q(i){H(i.updateIntervalMs??1e3,"updateIntervalMs"),F(i.items)}function F(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),re(l.schedules)})}export{Te 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 g=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var j=(e,t)=>{for(var o in t)g(e,o,{get:t[o],enumerable:!0})},q=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of G(t))!$.call(e,i)&&i!==o&&g(e,i,{get:()=>t[i],enumerable:!(r=D(t,i))||r.enumerable});return e};var z=e=>q(g({},"__esModule",{value:!0}),e);var H={};j(H,{useTimer:()=>U});module.exports=z(H);var d=require("react");function R(e,t){return{start:()=>{t()&&e.start()},pause:()=>{t()&&e.pause()},resume:()=>{t()&&e.resume()},reset:o=>{t()&&e.reset(o)},restart:()=>{t()&&e.restart()},cancel:o=>{t()&&e.cancel(o)}}}function l(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function A(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function y(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 b(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=b(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 N(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 I(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=b(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function k(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function C(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 E(e,t){return C(e,t,{autoStart:!0})}function x(e,t,o){return e.status!=="running"&&e.status!=="paused"?!1:(e.baseElapsedMilliseconds=b(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=o??null,e.now=t.wallNow,!0)}function O(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=b(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function P(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function U(e={}){let t=(0,d.useRef)(null);return t.current===null&&(t.current=B(e)),t.current.setOptions(e),(0,d.useEffect)(()=>{t.current?.commitOptions()}),(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.getServerSnapshot),...t.current.controls}}function B(e){let t=e;A(t.updateIntervalMs??1e3,"updateIntervalMs");let o=new Set,r=y(l()),i=f(r,l()),F=i,S=null,T=null,w=!1,s=(n=l())=>{i=f(r,n),o.forEach(a=>a())},u=()=>{S!==null&&(clearTimeout(S),S=null)},W=n=>{if(T===r.generation)return;T=r.generation;let a=r.generation,M=R(h,()=>r.generation===a),v=p=>{if(t.onError){t.onError(p,n,M);return}setTimeout(()=>{throw p},0)};try{Promise.resolve(t.onEnd?.(n,M)).catch(p=>{v(p)})}catch(p){v(p)}},m=n=>{let a=f(r,n);return!t.endWhen?.(a)||!O(r,n)?!1:(u(),s(n),W(f(r,n)),!0)},c=()=>{u(),r.status==="running"&&(S=setTimeout(()=>{if(r.status!=="running")return;let n=l();P(r,n),!m(n)&&(s(n),c())},t.updateIntervalMs??1e3))},h={start:()=>{let n=l();if(!N(r,n)){r.status==="running"&&c();return}s(n),m(n)||c()},pause:()=>{let n=l();I(r,n)&&(u(),s(n))},resume:()=>{let n=l();k(r,n)&&(s(n),m(n)||c())},reset:(n={})=>{let a=l();u(),C(r,a,n),T=null,s(a),n.autoStart&&!m(a)&&c()},restart:()=>{let n=l();u(),E(r,n),T=null,s(n),m(n)||c()},cancel:n=>{let a=l();x(r,a,n)&&(u(),s(a))}};return{commitOptions:()=>{if(w&&(w=!1,r.status==="running")){let n=l();m(n)||c()}},controls:h,destroy:u,getSnapshot:()=>i,getServerSnapshot:()=>F,setOptions:n=>{A(n.updateIntervalMs??1e3,"updateIntervalMs"),w=w||(n.updateIntervalMs??1e3)!==(t.updateIntervalMs??1e3)||n.endWhen!==t.endWhen,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-D-Vzr-PF.cjs';
2
+ export { b as TimerEndPredicate, c as TimerStatus } from './types-D-Vzr-PF.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-D-Vzr-PF.js';
2
+ export { b as TimerEndPredicate, c as TimerStatus } from './types-D-Vzr-PF.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 C,b as o,c as h,d as k,e as m,f as I,g as b,h as E,i as O,j as M,k as U,l as R,m as w}from"./chunk-XXJAJJJ6.js";import{useEffect as P,useRef as F,useSyncExternalStore as G}from"react";function N(l={}){let r=F(null);return r.current===null&&(r.current=j(l)),r.current.setOptions(l),P(()=>{r.current?.commitOptions()}),P(()=>{let e=r.current;return l.autoStart&&e.controls.start(),()=>e.destroy()},[]),{...G(r.current.subscribe,r.current.getSnapshot,r.current.getServerSnapshot),...r.current.controls}}function j(l){let r=l;h(r.updateIntervalMs??1e3,"updateIntervalMs");let p=new Set,e=k(o()),d=m(e,o()),W=d,f=null,T=null,S=!1,s=(t=o())=>{d=m(e,t),p.forEach(n=>n())},i=()=>{f!==null&&(clearTimeout(f),f=null)},x=t=>{if(T===e.generation)return;T=e.generation;let n=e.generation,g=C(v,()=>e.generation===n),y=u=>{if(r.onError){r.onError(u,t,g);return}setTimeout(()=>{throw u},0)};try{Promise.resolve(r.onEnd?.(t,g)).catch(u=>{y(u)})}catch(u){y(u)}},c=t=>{let n=m(e,t);return!r.endWhen?.(n)||!R(e,t)?!1:(i(),s(t),x(m(e,t)),!0)},a=()=>{i(),e.status==="running"&&(f=setTimeout(()=>{if(e.status!=="running")return;let t=o();w(e,t),!c(t)&&(s(t),a())},r.updateIntervalMs??1e3))},v={start:()=>{let t=o();if(!I(e,t)){e.status==="running"&&a();return}s(t),c(t)||a()},pause:()=>{let t=o();b(e,t)&&(i(),s(t))},resume:()=>{let t=o();E(e,t)&&(s(t),c(t)||a())},reset:(t={})=>{let n=o();i(),O(e,n,t),T=null,s(n),t.autoStart&&!c(n)&&a()},restart:()=>{let t=o();i(),M(e,t),T=null,s(t),c(t)||a()},cancel:t=>{let n=o();U(e,n,t)&&(i(),s(n))}};return{commitOptions:()=>{if(S&&(S=!1,e.status==="running")){let t=o();c(t)||a()}},controls:v,destroy:i,getSnapshot:()=>d,getServerSnapshot:()=>W,setOptions:t=>{h(t.updateIntervalMs??1e3,"updateIntervalMs"),S=S||(t.updateIntervalMs??1e3)!==(r.updateIntervalMs??1e3)||t.endWhen!==r.endWhen,r=t},subscribe:t=>(p.add(t),()=>p.delete(t))}}export{N 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 N=Object.defineProperty;var ae=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var de=(e,t)=>{for(var r in t)N(e,r,{get:t[r],enumerable:!0})},me=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ue(t))!ce.call(e,i)&&i!==r&&N(e,i,{get:()=>t[i],enumerable:!(n=ae(t,i))||n.enumerable});return e};var pe=e=>me(N({},"__esModule",{value:!0}),e);var ge={};de(ge,{useScheduledTimer:()=>ie});module.exports=pe(ge);var y=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 x(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function O(e,t){return{start:()=>{t()&&e.start()},pause:()=>{t()&&e.pause()},resume:()=>{t()&&e.resume()},reset:r=>{t()&&e.reset(r)},restart:()=>{t()&&e.restart()},cancel:r=>{t()&&e.cancel(r)}}}function fe(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 k(e,t){let r=fe(e);!r.enabled||!r.logger||t.type==="timer:tick"&&!r.includeTicks||r.logger({...t,label:t.label??r.label})}function A(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function j(){return{lastRunAt:null,pendingCount:0,leadingGeneration:null,signature:""}}function q({schedules:e=[],states:t,snapshot:r,generation:n,controls:i,activation:s=!1,isLive:u,onError:m,onEvent:T}){let d=new Set;e.forEach((l,h)=>{let p=E(l,h);d.add(p);let S=t.get(p);if(S||(S=j(),S.signature=U(l,h),t.set(p,S)),s&&l.leading&&S.leadingGeneration!==n){S.leadingGeneration=n,$(l,p,S,r,n,i,J(l,p,r.now,r.now,0),u,m,T);return}S.lastRunAt===null&&(S.lastRunAt=r.now);let v=Math.floor((r.now-S.lastRunAt)/l.everyMs);if(v>=1){let C=S.lastRunAt+v*l.everyMs;$(l,p,S,r,n,i,J(l,p,C,r.now,v-1),u,m,T)}});for(let l of t.keys())d.has(l)||t.delete(l)}function z(e,t,r,n){let i=n;return e?.forEach((s,u)=>{let m=E(s,u),d=t.get(m)?.lastRunAt??r;i=Math.min(i,Math.max(1,d+s.everyMs-r))}),i}function B(e,t,r,n){let i=new Set;e?.forEach((s,u)=>{let m=E(s,u),T=U(s,u);i.add(m);let d=t.get(m);if(d)d.signature!==T&&(d.lastRunAt=n?r:null,d.leadingGeneration=null,d.signature=T);else{let l=j();l.lastRunAt=n?r:null,l.signature=T,t.set(m,l)}});for(let s of t.keys())i.has(s)||t.delete(s)}function G(e){return JSON.stringify((e??[]).map((t,r)=>U(t,r)))}function Q(e){let t=new Set;e?.forEach((r,n)=>{x(r.everyMs,"schedule.everyMs");let i=E(r,n);if(t.has(i))throw new Error(`Duplicate schedule id "${i}"`);t.add(i)})}function J(e,t,r,n,i){return{scheduleId:e.id??t,scheduledAt:r,firedAt:n,nextRunAt:r+e.everyMs,overdueCount:i,effectiveEveryMs:e.everyMs}}function $(e,t,r,n,i,s,u,m,T,d){if(r.pendingCount>0&&(e.overlap??"skip")==="skip"){r.lastRunAt=u.scheduledAt,P(m,i,d,{type:"schedule:skip",context:u,reason:"overlap"});return}r.lastRunAt=u.scheduledAt,r.pendingCount+=1,P(m,i,d,{type:"schedule:start",context:u}),Promise.resolve().then(()=>e.callback(n,s,u)).then(()=>P(m,i,d,{type:"schedule:end",context:u}),l=>{if(m(i))try{e.onError?e.onError(l,n,s,u):T?.(l,n,s,u)}finally{d?.({type:"schedule:error",context:u,error:l})}}).finally(()=>{m(i)&&(r.pendingCount=Math.max(0,r.pendingCount-1))})}function E(e,t){return e.id??String(t)}function U(e,t){return JSON.stringify([e.id??t,e.everyMs,e.leading??!1,e.overlap??"skip"])}function P(e,t,r,n){e(t)&&r?.(n)}function V(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 M(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function I(e,t){let r=M(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 X(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 Y(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=M(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function Z(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function F(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 _(e,t){return F(e,t,{autoStart:!0})}function L(e,t,r){return e.status!=="running"&&e.status!=="paused"?!1:(e.baseElapsedMilliseconds=M(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=r??null,e.now=t.wallNow,!0)}function ee(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=M(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function te(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function ne(e,t){return{state:V(t),definition:e,endCalledGeneration:null}}function W(e){e.endCalledGeneration=null}function g(e,t){return I(e.state,t)}function re(e,t,r,n){let i=I(e.state,t);if(!e.definition.endWhen?.(i)||!ee(e.state,t))return null;let s=I(e.state,t);return Se(e,s,r,n),s}function Se(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 ie(e={}){let t=(0,y.useRef)(null);return t.current===null&&(t.current=Te(e)),t.current.setOptions(e),(0,y.useEffect)(()=>{t.current?.commitOptions()}),(0,y.useEffect)(()=>{let n=t.current;return e.autoStart&&n.controls.start(),()=>n.destroy()},[]),{...(0,y.useSyncExternalStore)(t.current.subscribe,t.current.getSnapshot,t.current.getServerSnapshot),...t.current.controls}}function Te(e){let t=e;oe(t);let r=new Set,n=ne(t,f()),i=new Map,s=g(n,f()),u=s,m=null,T=G(t.schedules),d=!1,l=(o=f())=>{s=g(n,o),r.forEach(a=>a())},h=()=>{m!==null&&(clearTimeout(m),m=null)},p=(o,a,c={})=>{k(t.diagnostics,{type:o,scope:"timer",...A(a,n.state.generation),...c})},S=(o,a,c)=>{let w=O(R,()=>n.state.generation===c);t.onError?.(o,a,w),k(t.diagnostics,{type:"callback:error",scope:"timer",error:o,...A(a,c)})},v=(o,a)=>c=>{k(t.diagnostics,{type:c.type,scope:"timer",...c.context,..."reason"in c?{reason:c.reason}:{},..."error"in c?{error:c.error}:{},...A(o,a)})},C=(o=f(),a=!1)=>{if(n.state.status!=="running")return!1;let c=n.state.generation,w=O(R,()=>n.state.generation===c),H=re(n,o,w,S);if(H)return h(),p("timer:end",H),l(o),!0;let K=g(n,o);return q({schedules:t.schedules,states:i,snapshot:K,generation:n.state.generation,controls:w,activation:a,isLive:D=>n.state.generation===D,onError:(D,le,se)=>t.onError?.(D,le,se),onEvent:v(K,n.state.generation)}),!1},b=(o=!0)=>{if(h(),n.state.status!=="running")return;let a=z(t.schedules,i,f().wallNow,t.updateIntervalMs??1e3);o&&p("scheduler:start",g(n,f())),m=setTimeout(()=>{if(n.state.status!=="running")return;let c=f();te(n.state,c);let w=g(n,c);p("timer:tick",w),C(c)||(l(c),b())},a)},R={start:()=>{let o=f();if(!X(n.state,o)){n.state.status==="running"&&b();return}p("timer:start",g(n,o)),C(o,!0),l(o),b()},pause:()=>{let o=f();Y(n.state,o)&&(h(),p("timer:pause",g(n,o)),l(o))},resume:()=>{let o=f();Z(n.state,o)&&(p("timer:resume",g(n,o)),C(o,!0),l(o),b())},reset:(o={})=>{let a=f();h(),F(n.state,a,o),i.clear(),W(n),p("timer:reset",g(n,a)),C(a,o.autoStart),l(a),b()},restart:()=>{let o=f();h(),_(n.state,o),i.clear(),W(n),p("timer:restart",g(n,o)),C(o,!0),l(o),b()},cancel:o=>{let a=f();L(n.state,a,o)&&(h(),p("timer:cancel",g(n,a),{reason:o}),l(a))}};return{commitOptions:()=>{if(d&&(d=!1,B(t.schedules,i,f().wallNow,n.state.status==="running"),n.state.status==="running")){let o=f();C(o)||b(!1)}},controls:R,destroy:h,getSnapshot:()=>s,getServerSnapshot:()=>u,setOptions:o=>{oe(o);let a=G(o.schedules),c=a!==T;d=d||c||(o.updateIntervalMs??1e3)!==(t.updateIntervalMs??1e3)||o.endWhen!==t.endWhen,t=o,n.definition=o,c&&(T=a)},subscribe:o=>(r.add(o),()=>r.delete(o))}}function oe(e){x(e.updateIntervalMs??1e3,"updateIntervalMs"),Q(e.schedules)}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-D-Vzr-PF.cjs';
2
+ export { i as TimerDiagnostics, j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger, l as TimerSchedule, m as TimerScheduleContext } from './types-D-Vzr-PF.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-D-Vzr-PF.js';
2
+ export { i as TimerDiagnostics, j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger, l as TimerSchedule, m as TimerScheduleContext } from './types-D-Vzr-PF.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 F,d as G,e as j,f as C,g as q,h as z,i as I,j as i,k as A}from"./chunk-OYRPLLEV.js";import{a as E,b as o,c as U,f as M,g as N,h as P,i as x,j as R,k as L,m as W}from"./chunk-XXJAJJJ6.js";import{useEffect as B,useRef as Y,useSyncExternalStore as Z}from"react";function _(c={}){let r=Y(null);return r.current===null&&(r.current=$(c)),r.current.setOptions(c),B(()=>{r.current?.commitOptions()}),B(()=>{let t=r.current;return c.autoStart&&t.controls.start(),()=>t.destroy()},[]),{...Z(r.current.subscribe,r.current.getSnapshot,r.current.getServerSnapshot),...r.current.controls}}function $(c){let r=c;H(r);let h=new Set,t=z(r,o()),S=new Map,v=i(t,o()),J=v,f=null,O=C(r.schedules),T=!1,u=(e=o())=>{v=i(t,e),h.forEach(s=>s())},l=()=>{f!==null&&(clearTimeout(f),f=null)},a=(e,s,n={})=>{g(r.diagnostics,{type:e,scope:"timer",...y(s,t.state.generation),...n})},K=(e,s,n)=>{let p=E(b,()=>t.state.generation===n);r.onError?.(e,s,p),g(r.diagnostics,{type:"callback:error",scope:"timer",error:e,...y(s,n)})},Q=(e,s)=>n=>{g(r.diagnostics,{type:n.type,scope:"timer",...n.context,..."reason"in n?{reason:n.reason}:{},..."error"in n?{error:n.error}:{},...y(e,s)})},d=(e=o(),s=!1)=>{if(t.state.status!=="running")return!1;let n=t.state.generation,p=E(b,()=>t.state.generation===n),D=A(t,e,p,K);if(D)return l(),a("timer:end",D),u(e),!0;let w=i(t,e);return F({schedules:r.schedules,states:S,snapshot:w,generation:t.state.generation,controls:p,activation:s,isLive:k=>t.state.generation===k,onError:(k,V,X)=>r.onError?.(k,V,X),onEvent:Q(w,t.state.generation)}),!1},m=(e=!0)=>{if(l(),t.state.status!=="running")return;let s=G(r.schedules,S,o().wallNow,r.updateIntervalMs??1e3);e&&a("scheduler:start",i(t,o())),f=setTimeout(()=>{if(t.state.status!=="running")return;let n=o();W(t.state,n);let p=i(t,n);a("timer:tick",p),d(n)||(u(n),m())},s)},b={start:()=>{let e=o();if(!M(t.state,e)){t.state.status==="running"&&m();return}a("timer:start",i(t,e)),d(e,!0),u(e),m()},pause:()=>{let e=o();N(t.state,e)&&(l(),a("timer:pause",i(t,e)),u(e))},resume:()=>{let e=o();P(t.state,e)&&(a("timer:resume",i(t,e)),d(e,!0),u(e),m())},reset:(e={})=>{let s=o();l(),x(t.state,s,e),S.clear(),I(t),a("timer:reset",i(t,s)),d(s,e.autoStart),u(s),m()},restart:()=>{let e=o();l(),R(t.state,e),S.clear(),I(t),a("timer:restart",i(t,e)),d(e,!0),u(e),m()},cancel:e=>{let s=o();L(t.state,s,e)&&(l(),a("timer:cancel",i(t,s),{reason:e}),u(s))}};return{commitOptions:()=>{if(T&&(T=!1,j(r.schedules,S,o().wallNow,t.state.status==="running"),t.state.status==="running")){let e=o();d(e)||m(!1)}},controls:b,destroy:l,getSnapshot:()=>v,getServerSnapshot:()=>J,setOptions:e=>{H(e);let s=C(e.schedules),n=s!==O;T=T||n||(e.updateIntervalMs??1e3)!==(r.updateIntervalMs??1e3)||e.endWhen!==r.endWhen,r=e,t.definition=e,n&&(O=s)},subscribe:e=>(h.add(e),()=>h.delete(e))}}function H(c){U(c.updateIntervalMs??1e3,"updateIntervalMs"),q(c.schedules)}export{_ as useScheduledTimer};
@@ -50,6 +50,7 @@ type TimerSchedule = {
50
50
  leading?: boolean;
51
51
  overlap?: 'skip' | 'allow';
52
52
  callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
53
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void;
53
54
  };
54
55
  type TimerDiagnostics = TimerDiagnosticsLogger | {
55
56
  enabled?: boolean;
@@ -59,7 +60,7 @@ type TimerDiagnostics = TimerDiagnosticsLogger | {
59
60
  };
60
61
  type TimerDiagnosticsLogger = (event: TimerDiagnosticsEvent) => void;
61
62
  type TimerDiagnosticsEvent = {
62
- type: 'timer:start' | 'timer:pause' | 'timer:resume' | 'timer:reset' | 'timer:restart' | 'timer:cancel' | 'timer:end' | 'timer:tick' | 'scheduler:start' | 'scheduler:stop' | 'schedule:start' | 'schedule:skip' | 'schedule:end' | 'schedule:error' | 'callback:error';
63
+ type: 'timer:start' | 'timer:pause' | 'timer:resume' | 'timer:reset' | 'timer:restart' | 'timer:cancel' | 'timer:end' | 'timer:tick' | 'scheduler:start' | 'schedule:start' | 'schedule:skip' | 'schedule:end' | 'schedule:error' | 'callback:error';
63
64
  scope: 'timer' | 'timer-group';
64
65
  label?: string;
65
66
  timerId?: string;
@@ -82,6 +83,7 @@ type UseTimerOptions = {
82
83
  updateIntervalMs?: number;
83
84
  endWhen?: TimerEndPredicate;
84
85
  onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
86
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerControls) => void;
85
87
  };
86
88
  type UseScheduledTimerOptions = UseTimerOptions & {
87
89
  schedules?: TimerSchedule[];
@@ -93,6 +95,7 @@ type TimerGroupItem = {
93
95
  autoStart?: boolean;
94
96
  endWhen?: TimerEndPredicate;
95
97
  onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
98
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void;
96
99
  schedules?: TimerSchedule[];
97
100
  };
98
101
  type UseTimerGroupOptions = {
@@ -50,6 +50,7 @@ type TimerSchedule = {
50
50
  leading?: boolean;
51
51
  overlap?: 'skip' | 'allow';
52
52
  callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
53
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void;
53
54
  };
54
55
  type TimerDiagnostics = TimerDiagnosticsLogger | {
55
56
  enabled?: boolean;
@@ -59,7 +60,7 @@ type TimerDiagnostics = TimerDiagnosticsLogger | {
59
60
  };
60
61
  type TimerDiagnosticsLogger = (event: TimerDiagnosticsEvent) => void;
61
62
  type TimerDiagnosticsEvent = {
62
- type: 'timer:start' | 'timer:pause' | 'timer:resume' | 'timer:reset' | 'timer:restart' | 'timer:cancel' | 'timer:end' | 'timer:tick' | 'scheduler:start' | 'scheduler:stop' | 'schedule:start' | 'schedule:skip' | 'schedule:end' | 'schedule:error' | 'callback:error';
63
+ type: 'timer:start' | 'timer:pause' | 'timer:resume' | 'timer:reset' | 'timer:restart' | 'timer:cancel' | 'timer:end' | 'timer:tick' | 'scheduler:start' | 'schedule:start' | 'schedule:skip' | 'schedule:end' | 'schedule:error' | 'callback:error';
63
64
  scope: 'timer' | 'timer-group';
64
65
  label?: string;
65
66
  timerId?: string;
@@ -82,6 +83,7 @@ type UseTimerOptions = {
82
83
  updateIntervalMs?: number;
83
84
  endWhen?: TimerEndPredicate;
84
85
  onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
86
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerControls) => void;
85
87
  };
86
88
  type UseScheduledTimerOptions = UseTimerOptions & {
87
89
  schedules?: TimerSchedule[];
@@ -93,6 +95,7 @@ type TimerGroupItem = {
93
95
  autoStart?: boolean;
94
96
  endWhen?: TimerEndPredicate;
95
97
  onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
98
+ onError?: (error: unknown, snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void;
96
99
  schedules?: TimerSchedule[];
97
100
  };
98
101
  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.16",
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",
@@ -43,7 +43,7 @@
43
43
  "tag": "alpha"
44
44
  },
45
45
  "engines": {
46
- "node": ">=24.0.0"
46
+ "node": ">=18.0.0"
47
47
  },
48
48
  "keywords": [
49
49
  "react",
@@ -1 +0,0 @@
1
- function r(){let n=Date.now(),e=typeof performance<"u"&&typeof performance.now=="function"?performance.now():n;return{wallNow:n,monotonicNow:e}}function a(n,e){if(!Number.isFinite(n)||n<=0)throw new RangeError(`${e} must be a finite number greater than 0`)}function i(n){return{status:"idle",generation:0,tick:0,startedAt:null,pausedAt:null,endedAt:null,cancelledAt:null,cancelReason:null,baseElapsedMilliseconds:0,activeStartedAtMonotonic:null,now:n.wallNow}}function l(n,e){return n.status!=="running"||n.activeStartedAtMonotonic===null?n.baseElapsedMilliseconds:Math.max(0,n.baseElapsedMilliseconds+e.monotonicNow-n.activeStartedAtMonotonic)}function d(n,e){let t=l(n,e);return{status:n.status,now:e.wallNow,tick:n.tick,startedAt:n.startedAt,pausedAt:n.pausedAt,endedAt:n.endedAt,cancelledAt:n.cancelledAt,cancelReason:n.cancelReason,elapsedMilliseconds:t,isIdle:n.status==="idle",isRunning:n.status==="running",isPaused:n.status==="paused",isEnded:n.status==="ended",isCancelled:n.status==="cancelled"}}function c(n,e){return n.status!=="idle"?!1:(n.status="running",n.startedAt=e.wallNow,n.pausedAt=null,n.endedAt=null,n.cancelledAt=null,n.cancelReason=null,n.activeStartedAtMonotonic=e.monotonicNow,n.now=e.wallNow,!0)}function s(n,e){return n.status!=="running"?!1:(n.baseElapsedMilliseconds=l(n,e),n.activeStartedAtMonotonic=null,n.status="paused",n.pausedAt=e.wallNow,n.now=e.wallNow,!0)}function m(n,e){return n.status!=="paused"?!1:(n.status="running",n.pausedAt=null,n.activeStartedAtMonotonic=e.monotonicNow,n.now=e.wallNow,!0)}function o(n,e,t={}){return n.generation+=1,n.tick=0,n.status=t.autoStart?"running":"idle",n.startedAt=t.autoStart?e.wallNow:null,n.pausedAt=null,n.endedAt=null,n.cancelledAt=null,n.cancelReason=null,n.baseElapsedMilliseconds=0,n.activeStartedAtMonotonic=t.autoStart?e.monotonicNow:null,n.now=e.wallNow,!0}function w(n,e){return o(n,e,{autoStart:!0})}function p(n,e,t){return n.status==="ended"||n.status==="cancelled"?!1:(n.baseElapsedMilliseconds=l(n,e),n.activeStartedAtMonotonic=null,n.status="cancelled",n.cancelledAt=e.wallNow,n.cancelReason=t??null,n.now=e.wallNow,!0)}function S(n,e){return n.status!=="running"?!1:(n.baseElapsedMilliseconds=l(n,e),n.activeStartedAtMonotonic=null,n.status="ended",n.endedAt=e.wallNow,n.now=e.wallNow,!0)}function A(n,e){return n.status!=="running"?!1:(n.tick+=1,n.now=e.wallNow,!0)}export{r as a,a as b,i as c,d,c as e,s as f,m as g,o as h,w as i,p as j,S as k,A as l};
@@ -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};