@crup/react-timer-hook 0.0.1-alpha.12 → 0.0.1-alpha.13

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
@@ -15,18 +15,17 @@
15
15
 
16
16
  ## Why this exists
17
17
 
18
- Timer hooks look simple until real apps need pause/resume semantics, Strict Mode cleanup, async callbacks, polling that does not overlap, and lists with dozens of independent timers.
18
+ Timers get messy when a product needs pause and resume, countdowns tied to server time, async work, or a screen full of independent rows.
19
19
 
20
- `@crup/react-timer-hook` starts with a ~1.2 kB timer core and lets your app compose the heavier pieces only when it needs them:
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
- - 🔋 Batteries are optional: schedules, timer groups, duration helpers, and diagnostics live in subpath imports.
23
+ - 🔋 Add-ons are opt-in: schedules, timer groups, duration helpers, and diagnostics live in subpath imports.
24
24
  - 🧭 `useTimerGroup()` from `/group` for many keyed lifecycles with one shared scheduler.
25
- - 📡 `useScheduledTimer()` from `/schedules` for polling, overdue timing context, and opt-in diagnostics.
26
- - 🧩 `durationParts()` from `/duration` for display math without locale or timezone opinions.
27
- - 🧼 No formatting, timezone, audio, retry, cache, or data-fetching policy baked in.
28
- - 🧪 Built for rerenders, Strict Mode, async callbacks, cleanup, and many timers.
29
- - 🤖 Agent-friendly docs through hosted `llms.txt`, `llms-full.txt`, and an optional MCP docs helper.
25
+ - 📡 `useScheduledTimer()` from `/schedules` for polling and timing context.
26
+ - 🧩 `durationParts()` from `/duration` for common display math.
27
+ - 🧪 Tested for React Strict Mode, rerenders, async callbacks, cleanup, and multi-timer screens.
28
+ - 🤖 AI-ready docs are available through hosted `llms.txt`, `llms-full.txt`, and an optional MCP docs helper.
30
29
 
31
30
  ## Install
32
31
 
@@ -49,7 +48,7 @@ import { useScheduledTimer } from '@crup/react-timer-hook/schedules';
49
48
  Each recipe has a live playground and a focused code sample:
50
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/)
52
- - 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/), [debug logs](https://crup.github.io/react-timer-hook/recipes/intermediate/debug-logs/)
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/)
53
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/)
54
53
 
55
54
  ## Quick examples
@@ -143,7 +142,7 @@ const timers = useTimerGroup({
143
142
  });
144
143
  ```
145
144
 
146
- ## API tables
145
+ ## API reference
147
146
 
148
147
  ### `useTimer()` settings
149
148
 
@@ -165,13 +164,13 @@ Import from `@crup/react-timer-hook/schedules` when you need polling or schedule
165
164
  | `endWhen` | `(snapshot) => boolean` | No | Ends the lifecycle when it returns `true`. |
166
165
  | `onEnd` | `(snapshot, controls) => void \| Promise<void>` | No | Called once per generation when `endWhen` ends the lifecycle. |
167
166
  | `schedules` | `TimerSchedule[]` | No | Scheduled side effects that run while the timer is active. Async overlap defaults to `skip`. |
168
- | `debug` | `TimerDebug` | No | Opt-in semantic diagnostics. No logs are emitted by default. |
167
+ | `diagnostics` | `TimerDiagnostics` | No | Optional lifecycle and schedule events. No logs are emitted unless you pass a logger. |
169
168
 
170
169
  ### `TimerSchedule`
171
170
 
172
171
  | Key | Type | Required | Description |
173
172
  | --- | --- | --- | --- |
174
- | `id` | `string` | No | Stable identifier used in debug events and schedule context. Falls back to the array index. |
173
+ | `id` | `string` | No | Stable identifier used in diagnostics events and schedule context. Falls back to the array index. |
175
174
  | `everyMs` | `number` | Yes | Schedule cadence in milliseconds. Must be positive and finite. |
176
175
  | `leading` | `boolean` | No | Runs the schedule immediately when the timer starts or resumes into a new generation. Defaults to `false`. |
177
176
  | `overlap` | `'skip' \| 'allow'` | No | Controls async overlap. Defaults to `skip`, so a pending callback prevents another run. |
@@ -185,7 +184,7 @@ Import from `@crup/react-timer-hook/group` when many keyed items need independen
185
184
  | --- | --- | --- | --- |
186
185
  | `updateIntervalMs` | `number` | No | Shared scheduler cadence for the group. Defaults to `1000`. |
187
186
  | `items` | `TimerGroupItem[]` | No | Initial/synced timer item definitions. Each item has its own lifecycle state. |
188
- | `debug` | `TimerDebug` | No | Opt-in semantic diagnostics for group lifecycle and schedule events. |
187
+ | `diagnostics` | `TimerDiagnostics` | No | Optional lifecycle and schedule events for group timers. |
189
188
 
190
189
  ### `TimerGroupItem`
191
190
 
@@ -224,15 +223,15 @@ Import from `@crup/react-timer-hook/group` when many keyed items need independen
224
223
 
225
224
  ## Bundle size
226
225
 
227
- The core import stays small. Extra capabilities are opt-in batteries.
226
+ The default import stays small. Add the other pieces only when that screen needs them.
228
227
 
229
- | Entry | Raw | Gzip | Brotli |
230
- | --- | ---: | ---: | ---: |
231
- | core | 3.82 kB | 1.31 kB | 1.21 kB |
232
- | timer group add-on | 8.94 kB | 2.97 kB | 2.70 kB |
233
- | schedules add-on | 6.88 kB | 2.32 kB | 2.13 kB |
234
- | duration helper | 318 B | 224 B | 192 B |
235
- | diagnostics helper | 105 B | 115 B | 99 B |
228
+ | Piece | Import | Best for | Raw | Gzip | Brotli |
229
+ | --- | --- | --- | ---: | ---: | ---: |
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 |
233
+ | 🧩 Duration | `@crup/react-timer-hook/duration` | `days`, `hours`, `minutes`, `seconds`, `milliseconds` | 318 B | 224 B | 192 B |
234
+ | 🔎 Diagnostics | `@crup/react-timer-hook/diagnostics` | Optional lifecycle and schedule event logging | 105 B | 115 B | 90 B |
236
235
 
237
236
  CI writes a size summary to the GitHub Actions UI and posts bundle-size reports on pull requests.
238
237
 
@@ -0,0 +1 @@
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};
@@ -1 +1 @@
1
- "use strict";var t=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var n=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var b=(r,e)=>{for(var o in e)t(r,o,{get:e[o],enumerable:!0})},T=(r,e,o,g)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of n(e))!u.call(r,i)&&i!==o&&t(r,i,{get:()=>e[i],enumerable:!(g=m(e,i))||g.enumerable});return r};var s=r=>T(t({},"__esModule",{value:!0}),r);var l={};b(l,{consoleTimerDiagnostics:()=>D});module.exports=s(l);function D(r={}){return{...r,logger:e=>console.debug("[timer]",e)}}0&&(module.exports={consoleTimerDiagnostics});
1
+ "use strict";var t=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(e,i)=>{for(var s in i)t(e,s,{get:i[s],enumerable:!0})},a=(e,i,s,n)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of g(i))!c.call(e,o)&&o!==s&&t(e,o,{get:()=>i[o],enumerable:!(n=r(i,o))||n.enumerable});return e};var T=e=>a(t({},"__esModule",{value:!0}),e);var l={};m(l,{consoleTimerDiagnostics:()=>D});module.exports=T(l);function D(e={}){return{...e,logger:i=>console.debug("[timer]",i)}}0&&(module.exports={consoleTimerDiagnostics});
@@ -1,9 +1,9 @@
1
- import { i as TimerDebug } from './types-4uFJF2Fx.cjs';
2
- export { j as TimerDebugEvent, k as TimerDebugLogger } from './types-4uFJF2Fx.cjs';
1
+ import { i as TimerDiagnostics } from './types-DK7omKO-.cjs';
2
+ export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types-DK7omKO-.cjs';
3
3
 
4
4
  declare function consoleTimerDiagnostics(options?: {
5
5
  includeTicks?: boolean;
6
6
  label?: string;
7
- }): TimerDebug;
7
+ }): TimerDiagnostics;
8
8
 
9
- export { TimerDebug, consoleTimerDiagnostics };
9
+ export { TimerDiagnostics, consoleTimerDiagnostics };
@@ -1,9 +1,9 @@
1
- import { i as TimerDebug } from './types-4uFJF2Fx.js';
2
- export { j as TimerDebugEvent, k as TimerDebugLogger } from './types-4uFJF2Fx.js';
1
+ import { i as TimerDiagnostics } from './types-DK7omKO-.js';
2
+ export { j as TimerDiagnosticsEvent, k as TimerDiagnosticsLogger } from './types-DK7omKO-.js';
3
3
 
4
4
  declare function consoleTimerDiagnostics(options?: {
5
5
  includeTicks?: boolean;
6
6
  label?: string;
7
- }): TimerDebug;
7
+ }): TimerDiagnostics;
8
8
 
9
- export { TimerDebug, consoleTimerDiagnostics };
9
+ export { TimerDiagnostics, consoleTimerDiagnostics };
@@ -1 +1 @@
1
- function i(e={}){return{...e,logger:r=>console.debug("[timer]",r)}}export{i as consoleTimerDiagnostics};
1
+ function o(i={}){return{...i,logger:e=>console.debug("[timer]",e)}}export{o as consoleTimerDiagnostics};
@@ -1,4 +1,4 @@
1
- import { D as DurationParts } from './types-4uFJF2Fx.cjs';
1
+ import { D as DurationParts } from './types-DK7omKO-.cjs';
2
2
 
3
3
  declare function durationParts(milliseconds: number): DurationParts;
4
4
 
@@ -1,4 +1,4 @@
1
- import { D as DurationParts } from './types-4uFJF2Fx.js';
1
+ import { D as DurationParts } from './types-DK7omKO-.js';
2
2
 
3
3
  declare function durationParts(milliseconds: number): DurationParts;
4
4
 
package/dist/group.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var O=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var Se=(e,o)=>{for(var s in o)O(e,s,{get:o[s],enumerable:!0})},be=(e,o,s,u)=>{if(o&&typeof o=="object"||typeof o=="function")for(let S of ge(o))!Te.call(e,S)&&S!==s&&O(e,S,{get:()=>o[S],enumerable:!(u=pe(o,S))||u.enumerable});return e};var we=e=>be(O({},"__esModule",{value:!0}),e);var ye={};Se(ye,{useTimerGroup:()=>de});module.exports=we(ye);var l=require("react");function Ie(e){return e?e===!0?{enabled:!0,includeTicks:!1,logger:console.debug}:typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger??console.debug}:{enabled:!1,includeTicks:!1}}function I(e,o){let s=Ie(e);!s.enabled||!s.logger||o.type==="timer:tick"&&!s.includeTicks||s.logger({...o,label:o.label??s.label})}function y(e,o){return{generation:o,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function m(){let e=Date.now(),o=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:o}}function F(e,o){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${o} must be a finite number greater than 0`)}function ne(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 D(e,o){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+o.monotonicNow-e.activeStartedAtMonotonic)}function f(e,o){let s=D(e,o);return{status:e.status,now:o.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:s,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function P(e,o){return e.status!=="idle"?!1:(e.status="running",e.startedAt=o.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=o.monotonicNow,e.now=o.wallNow,!0)}function oe(e,o){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=D(e,o),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=o.wallNow,e.now=o.wallNow,!0)}function ae(e,o){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=o.monotonicNow,e.now=o.wallNow,!0)}function U(e,o,s={}){return e.generation+=1,e.tick=0,e.status=s.autoStart?"running":"idle",e.startedAt=s.autoStart?o.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=s.autoStart?o.monotonicNow:null,e.now=o.wallNow,!0}function le(e,o){return U(e,o,{autoStart:!0})}function ue(e,o,s){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=D(e,o),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=o.wallNow,e.cancelReason=s??null,e.now=o.wallNow,!0)}function se(e,o){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=D(e,o),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=o.wallNow,e.now=o.wallNow,!0)}function ie(e,o){return e.status!=="running"?!1:(e.tick+=1,e.now=o.wallNow,!0)}function de(e={}){let o=e.updateIntervalMs??1e3;F(o,"updateIntervalMs"),z(e.items);let s=(0,l.useRef)(e);s.current=e;let u=(0,l.useRef)(new Map),S=(0,l.useRef)(!1),h=(0,l.useRef)(null),[,p]=(0,l.useReducer)(t=>t+1,0),A=(0,l.useCallback)(()=>{h.current!==null&&(clearTimeout(h.current),h.current=null)},[]),L=(0,l.useCallback)((t,r=m())=>f(t.state,r),[]),c=(0,l.useCallback)((t,r,n,a={})=>{I(s.current.debug,{type:t,scope:"timer-group",timerId:r?.id,...y(n,r?.state.generation??0),...a})},[]),x=(0,l.useCallback)(t=>({start:()=>k(t),pause:()=>v(t),resume:()=>M(t),reset:r=>R(t,r),restart:()=>G(t),cancel:r=>C(t,r)}),[]),j=(0,l.useCallback)((t,r)=>{let n=t.state.generation;if(t.endCalledGeneration!==n){t.endCalledGeneration=n;try{t.definition.onEnd?.(r,x(t.id))}catch(a){I(s.current.debug,{type:"callback:error",scope:"timer-group",timerId:t.id,error:a,...y(r,n)})}}},[x]),$=(0,l.useCallback)((t,r,n,a,d,i,b)=>{if(a.pending&&(r.overlap??"skip")==="skip"){a.lastRunAt=b.scheduledAt,I(s.current.debug,{type:"schedule:skip",scope:"timer-group",timerId:t.id,reason:"overlap",...b,...y(d,i)});return}a.lastRunAt=b.scheduledAt,a.pending=!0,I(s.current.debug,{type:"schedule:start",scope:"timer-group",timerId:t.id,...b,...y(d,i)}),Promise.resolve().then(()=>r.callback(d,x(t.id),b)).then(()=>{I(s.current.debug,{type:"schedule:end",scope:"timer-group",timerId:t.id,...b,...y(d,i)})},g=>{I(s.current.debug,{type:"schedule:error",scope:"timer-group",timerId:t.id,error:g,...b,...y(d,i)})}).finally(()=>{u.current.get(t.id)?.state.generation===i&&(a.pending=!1)})},[x]),K=(0,l.useCallback)((t,r,n=!1)=>{let a=t.definition.schedules??[],d=new Set;a.forEach((i,b)=>{let g=i.id??String(b);d.add(g);let T=t.schedules.get(g);if(T||(T={lastRunAt:null,pending:!1,leadingGeneration:null},t.schedules.set(g,T)),n&&i.leading&&T.leadingGeneration!==t.state.generation){T.leadingGeneration=t.state.generation,$(t,i,g,T,r,t.state.generation,ce(i,g,r.now,r.now,0));return}T.lastRunAt===null&&(T.lastRunAt=t.state.startedAt??r.now);let E=Math.floor((r.now-T.lastRunAt)/i.everyMs);if(E>=1){let fe=T.lastRunAt+E*i.everyMs;$(t,i,g,T,r,t.state.generation,ce(i,g,fe,r.now,E-1))}});for(let i of t.schedules.keys())d.has(i)||t.schedules.delete(i)},[$]),w=(0,l.useCallback)((t,r=m(),n=!1)=>{if(t.state.status!=="running")return;let a=f(t.state,r);if(t.definition.endWhen?.(a)){if(se(t.state,r)){let d=f(t.state,r);c("timer:end",t,d),j(t,d)}return}K(t,a,n)},[j,c,K]),W=(0,l.useCallback)((t=m())=>{let n=s.current.updateIntervalMs??1e3;for(let a of u.current.values()){if(a.state.status!=="running")continue;(a.definition.schedules??[]).forEach((i,b)=>{let g=i.id??String(b),E=a.schedules.get(g)?.lastRunAt??t.wallNow;n=Math.min(n,Math.max(1,E+i.everyMs-t.wallNow))})}return n},[]),N=(0,l.useCallback)(t=>{let r=u.current.get(t.id);if(r)return r.definition=t,{item:r,added:!1};let n={id:t.id,state:ne(m()),definition:t,schedules:new Map,endCalledGeneration:null};return u.current.set(t.id,n),t.autoStart&&P(n.state,m()),{item:n,added:!0}},[]),q=(0,l.useCallback)(()=>{let t=s.current.items??[],r=new Set,n=!1;t.forEach(a=>{r.add(a.id);let{item:d,added:i}=N(a);n=n||i,a.autoStart&&d.state.status==="idle"&&(n=P(d.state,m())||n)});for(let a of u.current.keys())r.has(a)||(u.current.delete(a),n=!0);return n},[N]);(0,l.useEffect)(()=>{q()&&p()},[q,e.items]);let B=(0,l.useCallback)(t=>{if(z([t]),u.current.has(t.id))throw new Error(`Timer item "${t.id}" already exists`);N(t),p()},[N]),H=(0,l.useCallback)((t,r)=>{let n=u.current.get(t);if(!n)return;let a={...n.definition,...r,id:t};z([a]),n.definition=a,p()},[]),J=(0,l.useCallback)(t=>{u.current.delete(t),p()},[]),Q=(0,l.useCallback)(()=>{u.current.clear(),A(),p()},[A]),k=(0,l.useCallback)(t=>{let r=u.current.get(t);if(!r)return;let n=m();P(r.state,n)&&(c("timer:start",r,f(r.state,n)),w(r,n,!0),p())},[c,w]),v=(0,l.useCallback)(t=>{let r=u.current.get(t);if(!r)return;let n=m();oe(r.state,n)&&(c("timer:pause",r,f(r.state,n)),p())},[c]),M=(0,l.useCallback)(t=>{let r=u.current.get(t);if(!r)return;let n=m();ae(r.state,n)&&(c("timer:resume",r,f(r.state,n)),w(r,n,!0),p())},[c,w]),R=(0,l.useCallback)((t,r={})=>{let n=u.current.get(t);if(!n)return;let a=m();U(n.state,a,r),n.schedules.clear(),n.endCalledGeneration=null,c("timer:reset",n,f(n.state,a)),r.autoStart&&w(n,a,!0),p()},[c,w]),G=(0,l.useCallback)(t=>{let r=u.current.get(t);if(!r)return;let n=m();le(r.state,n),r.schedules.clear(),r.endCalledGeneration=null,c("timer:restart",r,f(r.state,n)),w(r,n,!0),p()},[c,w]),C=(0,l.useCallback)((t,r)=>{let n=u.current.get(t);if(!n)return;let a=m();ue(n.state,a,r)&&(c("timer:cancel",n,f(n.state,a),{reason:r}),p())},[c]),me=Array.from(u.current.keys()).map(t=>`${t}:${u.current.get(t).state.status}:${u.current.get(t).state.generation}:${u.current.get(t).state.tick}`).join("|");(0,l.useEffect)(()=>{S.current=!0;let t=Array.from(u.current.values()).filter(n=>n.state.status==="running");if(t.length===0){A();return}A();let r=t[0];return c("scheduler:start",r,f(r.state,m())),h.current=setTimeout(()=>{if(!S.current)return;let n=m();for(let a of u.current.values()){if(a.state.status!=="running")continue;ie(a.state,n);let d=f(a.state,n);c("timer:tick",a,d),w(a,n)}p()},W()),()=>{h.current!==null&&c("scheduler:stop",r,f(r.state,m())),A(),S.current=!1}},[me,A,c,W,w]);let V=(0,l.useCallback)(t=>{let r=u.current.get(t);if(r)return L(r)},[L]),X=m().wallNow,Y=(0,l.useCallback)(()=>Array.from(u.current.keys()).forEach(k),[k]),Z=(0,l.useCallback)(()=>Array.from(u.current.keys()).forEach(v),[v]),_=(0,l.useCallback)(()=>Array.from(u.current.keys()).forEach(M),[M]),ee=(0,l.useCallback)(t=>Array.from(u.current.keys()).forEach(r=>R(r,t)),[R]),te=(0,l.useCallback)(()=>Array.from(u.current.keys()).forEach(G),[G]),re=(0,l.useCallback)(t=>Array.from(u.current.keys()).forEach(r=>C(r,t)),[C]);return(0,l.useMemo)(()=>({now:X,size:u.current.size,ids:Array.from(u.current.keys()),get:V,add:B,update:H,remove:J,clear:Q,start:k,pause:v,resume:M,reset:R,restart:G,cancel:C,startAll:Y,pauseAll:Z,resumeAll:_,resetAll:ee,restartAll:te,cancelAll:re}),[B,C,re,Q,V,X,v,Z,J,R,ee,G,te,M,_,k,Y,H])}function z(e){let o=new Set;e?.forEach(s=>{if(o.has(s.id))throw new Error(`Duplicate timer item id "${s.id}"`);o.add(s.id),s.schedules?.forEach(u=>F(u.everyMs,"schedule.everyMs"))})}function ce(e,o,s,u,S){return{scheduleId:e.id??o,scheduledAt:s,firedAt:u,nextRunAt:s+e.everyMs,overdueCount:S,effectiveEveryMs:e.everyMs}}0&&(module.exports={useTimerGroup});
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});
package/dist/group.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-4uFJF2Fx.cjs';
2
- export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-4uFJF2Fx.cjs';
1
+ import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-DK7omKO-.cjs';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-DK7omKO-.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-4uFJF2Fx.js';
2
- export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-4uFJF2Fx.js';
1
+ import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-DK7omKO-.js';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-DK7omKO-.js';
3
3
 
4
4
  declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
5
5
 
package/dist/group.js CHANGED
@@ -1 +1 @@
1
- import{a as h,b as T}from"./chunk-65MJVHTI.js";import{a as l,b as O,c as te,d,e as P,f as re,g as ne,h as se,i as ue,j as ae,k as oe,l as ie}from"./chunk-I3PNNG3I.js";import{useCallback as u,useEffect as ce,useMemo as fe,useReducer as pe,useRef as $}from"react";function ge(g={}){let S=g.updateIntervalMs??1e3;O(S,"updateIntervalMs"),U(g.items);let i=$(g);i.current=g;let s=$(new Map),v=$(!1),k=$(null),[,m]=pe(e=>e+1,0),G=u(()=>{k.current!==null&&(clearTimeout(k.current),k.current=null)},[]),z=u((e,t=l())=>d(e.state,t),[]),o=u((e,t,r,n={})=>{h(i.current.debug,{type:e,scope:"timer-group",timerId:t?.id,...T(r,t?.state.generation??0),...n})},[]),x=u(e=>({start:()=>A(e),pause:()=>b(e),resume:()=>M(e),reset:t=>w(e,t),restart:()=>R(e),cancel:t=>C(e,t)}),[]),F=u((e,t)=>{let r=e.state.generation;if(e.endCalledGeneration!==r){e.endCalledGeneration=r;try{e.definition.onEnd?.(t,x(e.id))}catch(n){h(i.current.debug,{type:"callback:error",scope:"timer-group",timerId:e.id,error:n,...T(t,r)})}}},[x]),N=u((e,t,r,n,c,a,y)=>{if(n.pending&&(t.overlap??"skip")==="skip"){n.lastRunAt=y.scheduledAt,h(i.current.debug,{type:"schedule:skip",scope:"timer-group",timerId:e.id,reason:"overlap",...y,...T(c,a)});return}n.lastRunAt=y.scheduledAt,n.pending=!0,h(i.current.debug,{type:"schedule:start",scope:"timer-group",timerId:e.id,...y,...T(c,a)}),Promise.resolve().then(()=>t.callback(c,x(e.id),y)).then(()=>{h(i.current.debug,{type:"schedule:end",scope:"timer-group",timerId:e.id,...y,...T(c,a)})},f=>{h(i.current.debug,{type:"schedule:error",scope:"timer-group",timerId:e.id,error:f,...y,...T(c,a)})}).finally(()=>{s.current.get(e.id)?.state.generation===a&&(n.pending=!1)})},[x]),j=u((e,t,r=!1)=>{let n=e.definition.schedules??[],c=new Set;n.forEach((a,y)=>{let f=a.id??String(y);c.add(f);let p=e.schedules.get(f);if(p||(p={lastRunAt:null,pending:!1,leadingGeneration:null},e.schedules.set(f,p)),r&&a.leading&&p.leadingGeneration!==e.state.generation){p.leadingGeneration=e.state.generation,N(e,a,f,p,t,e.state.generation,le(a,f,t.now,t.now,0));return}p.lastRunAt===null&&(p.lastRunAt=e.state.startedAt??t.now);let E=Math.floor((t.now-p.lastRunAt)/a.everyMs);if(E>=1){let me=p.lastRunAt+E*a.everyMs;N(e,a,f,p,t,e.state.generation,le(a,f,me,t.now,E-1))}});for(let a of e.schedules.keys())c.has(a)||e.schedules.delete(a)},[N]),I=u((e,t=l(),r=!1)=>{if(e.state.status!=="running")return;let n=d(e.state,t);if(e.definition.endWhen?.(n)){if(oe(e.state,t)){let c=d(e.state,t);o("timer:end",e,c),F(e,c)}return}j(e,n,r)},[F,o,j]),K=u((e=l())=>{let r=i.current.updateIntervalMs??1e3;for(let n of s.current.values()){if(n.state.status!=="running")continue;(n.definition.schedules??[]).forEach((a,y)=>{let f=a.id??String(y),E=n.schedules.get(f)?.lastRunAt??e.wallNow;r=Math.min(r,Math.max(1,E+a.everyMs-e.wallNow))})}return r},[]),D=u(e=>{let t=s.current.get(e.id);if(t)return t.definition=e,{item:t,added:!1};let r={id:e.id,state:te(l()),definition:e,schedules:new Map,endCalledGeneration:null};return s.current.set(e.id,r),e.autoStart&&P(r.state,l()),{item:r,added:!0}},[]),W=u(()=>{let e=i.current.items??[],t=new Set,r=!1;e.forEach(n=>{t.add(n.id);let{item:c,added:a}=D(n);r=r||a,n.autoStart&&c.state.status==="idle"&&(r=P(c.state,l())||r)});for(let n of s.current.keys())t.has(n)||(s.current.delete(n),r=!0);return r},[D]);ce(()=>{W()&&m()},[W,g.items]);let q=u(e=>{if(U([e]),s.current.has(e.id))throw new Error(`Timer item "${e.id}" already exists`);D(e),m()},[D]),B=u((e,t)=>{let r=s.current.get(e);if(!r)return;let n={...r.definition,...t,id:e};U([n]),r.definition=n,m()},[]),H=u(e=>{s.current.delete(e),m()},[]),J=u(()=>{s.current.clear(),G(),m()},[G]),A=u(e=>{let t=s.current.get(e);if(!t)return;let r=l();P(t.state,r)&&(o("timer:start",t,d(t.state,r)),I(t,r,!0),m())},[o,I]),b=u(e=>{let t=s.current.get(e);if(!t)return;let r=l();re(t.state,r)&&(o("timer:pause",t,d(t.state,r)),m())},[o]),M=u(e=>{let t=s.current.get(e);if(!t)return;let r=l();ne(t.state,r)&&(o("timer:resume",t,d(t.state,r)),I(t,r,!0),m())},[o,I]),w=u((e,t={})=>{let r=s.current.get(e);if(!r)return;let n=l();se(r.state,n,t),r.schedules.clear(),r.endCalledGeneration=null,o("timer:reset",r,d(r.state,n)),t.autoStart&&I(r,n,!0),m()},[o,I]),R=u(e=>{let t=s.current.get(e);if(!t)return;let r=l();ue(t.state,r),t.schedules.clear(),t.endCalledGeneration=null,o("timer:restart",t,d(t.state,r)),I(t,r,!0),m()},[o,I]),C=u((e,t)=>{let r=s.current.get(e);if(!r)return;let n=l();ae(r.state,n,t)&&(o("timer:cancel",r,d(r.state,n),{reason:t}),m())},[o]),de=Array.from(s.current.keys()).map(e=>`${e}:${s.current.get(e).state.status}:${s.current.get(e).state.generation}:${s.current.get(e).state.tick}`).join("|");ce(()=>{v.current=!0;let e=Array.from(s.current.values()).filter(r=>r.state.status==="running");if(e.length===0){G();return}G();let t=e[0];return o("scheduler:start",t,d(t.state,l())),k.current=setTimeout(()=>{if(!v.current)return;let r=l();for(let n of s.current.values()){if(n.state.status!=="running")continue;ie(n.state,r);let c=d(n.state,r);o("timer:tick",n,c),I(n,r)}m()},K()),()=>{k.current!==null&&o("scheduler:stop",t,d(t.state,l())),G(),v.current=!1}},[de,G,o,K,I]);let L=u(e=>{let t=s.current.get(e);if(t)return z(t)},[z]),Q=l().wallNow,V=u(()=>Array.from(s.current.keys()).forEach(A),[A]),X=u(()=>Array.from(s.current.keys()).forEach(b),[b]),Y=u(()=>Array.from(s.current.keys()).forEach(M),[M]),Z=u(e=>Array.from(s.current.keys()).forEach(t=>w(t,e)),[w]),_=u(()=>Array.from(s.current.keys()).forEach(R),[R]),ee=u(e=>Array.from(s.current.keys()).forEach(t=>C(t,e)),[C]);return fe(()=>({now:Q,size:s.current.size,ids:Array.from(s.current.keys()),get:L,add:q,update:B,remove:H,clear:J,start:A,pause:b,resume:M,reset:w,restart:R,cancel:C,startAll:V,pauseAll:X,resumeAll:Y,resetAll:Z,restartAll:_,cancelAll:ee}),[q,C,ee,J,L,Q,b,X,H,w,Z,R,_,M,Y,A,V,B])}function U(g){let S=new Set;g?.forEach(i=>{if(S.has(i.id))throw new Error(`Duplicate timer item id "${i.id}"`);S.add(i.id),i.schedules?.forEach(s=>O(s.everyMs,"schedule.everyMs"))})}function le(g,S,i,s,v){return{scheduleId:g.id??S,scheduledAt:i,firedAt:s,nextRunAt:i+g.everyMs,overdueCount:v,effectiveEveryMs:g.everyMs}}export{ge as useTimerGroup};
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};
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 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});
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UseTimerOptions, T as TimerSnapshot, a as TimerControls } from './types-4uFJF2Fx.cjs';
2
- export { b as TimerEndPredicate, c as TimerStatus } from './types-4uFJF2Fx.cjs';
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';
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-4uFJF2Fx.js';
2
- export { b as TimerEndPredicate, c as TimerStatus } from './types-4uFJF2Fx.js';
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';
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 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 +1 @@
1
- "use strict";var I=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var le=Object.prototype.hasOwnProperty;var oe=(e,t)=>{for(var r in t)I(e,r,{get:t[r],enumerable:!0})},ie=(e,t,r,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let d of ue(t))!le.call(e,d)&&d!==r&&I(e,d,{get:()=>t[d],enumerable:!(l=re(t,d))||l.enumerable});return e};var ae=e=>ie(I({},"__esModule",{value:!0}),e);var de={};oe(de,{useScheduledTimer:()=>te});module.exports=ae(de);var o=require("react");function ce(e){return e?e===!0?{enabled:!0,includeTicks:!1,logger:console.debug}:typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger??console.debug}:{enabled:!1,includeTicks:!1}}function h(e,t){let r=ce(e);!r.enabled||!r.logger||t.type==="timer:tick"&&!r.includeTicks||r.logger({...t,label:t.label??r.label})}function y(e,t){return{generation:t,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function f(){let e=Date.now(),t=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:t}}function P(e,t){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${t} must be a finite number greater than 0`)}function H(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 x(e,t){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+t.monotonicNow-e.activeStartedAtMonotonic)}function g(e,t){let r=x(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 J(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 Q(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=x(e,t),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=t.wallNow,e.now=t.wallNow,!0)}function V(e,t){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=t.monotonicNow,e.now=t.wallNow,!0)}function G(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 X(e,t){return G(e,t,{autoStart:!0})}function Y(e,t,r){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=x(e,t),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=t.wallNow,e.cancelReason=r??null,e.now=t.wallNow,!0)}function Z(e,t){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=x(e,t),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=t.wallNow,e.now=t.wallNow,!0)}function _(e,t){return e.status!=="running"?!1:(e.tick+=1,e.now=t.wallNow,!0)}function te(e={}){let t=e.updateIntervalMs??1e3;P(t,"updateIntervalMs"),se(e.schedules);let r=(0,o.useRef)(e);r.current=e;let l=(0,o.useRef)(null);l.current===null&&(l.current=H(f()));let d=(0,o.useRef)(!1),R=(0,o.useRef)(null),A=(0,o.useRef)(new Map),C=(0,o.useRef)(null),[,w]=(0,o.useReducer)(n=>n+1,0),s=(0,o.useCallback)(()=>{R.current!==null&&(clearTimeout(R.current),R.current=null)},[]),N=(0,o.useCallback)((n=f())=>g(l.current,n),[]),c=(0,o.useCallback)((n,u,i={})=>{h(r.current.debug,{type:n,scope:"timer",...y(u,l.current.generation),...i})},[]),k=(0,o.useRef)(null),O=(0,o.useCallback)(n=>{let u=l.current.generation;if(C.current!==u){C.current=u;try{r.current.onEnd?.(n,k.current)}catch(i){h(r.current.debug,{type:"callback:error",scope:"timer",...y(n,u),error:i})}}},[]),E=(0,o.useCallback)((n,u,i,p,S,a)=>{if(i.pending&&(n.overlap??"skip")==="skip"){i.lastRunAt=a.scheduledAt,h(r.current.debug,{type:"schedule:skip",scope:"timer",reason:"overlap",...a,...y(p,S)});return}i.lastRunAt=a.scheduledAt,i.pending=!0,h(r.current.debug,{type:"schedule:start",scope:"timer",...a,...y(p,S)}),Promise.resolve().then(()=>n.callback(p,k.current,a)).then(()=>{h(r.current.debug,{type:"schedule:end",scope:"timer",...a,...y(p,S)})},M=>{h(r.current.debug,{type:"schedule:error",scope:"timer",error:M,...a,...y(p,S)})}).finally(()=>{l.current?.generation===S&&(i.pending=!1)})},[]),F=(0,o.useCallback)((n,u,i=!1)=>{let p=r.current.schedules??[],S=new Set;p.forEach((a,M)=>{let T=a.id??String(M);S.add(T);let m=A.current.get(T);if(m||(m={lastRunAt:null,pending:!1,leadingGeneration:null},A.current.set(T,m)),i&&a.leading&&m.leadingGeneration!==u){m.leadingGeneration=u,E(a,T,m,n,u,ee(a,T,n.now,n.now,0));return}m.lastRunAt===null&&(m.lastRunAt=l.current.startedAt??n.now);let v=Math.floor((n.now-m.lastRunAt)/a.everyMs);if(v>=1){let ne=m.lastRunAt+v*a.everyMs;E(a,T,m,n,u,ee(a,T,ne,n.now,v-1))}});for(let a of A.current.keys())S.has(a)||A.current.delete(a)},[E]),b=(0,o.useCallback)((n=f(),u=!1)=>{let i=l.current;if(i.status!=="running")return;let p=g(i,n),S=i.generation;if(r.current.endWhen?.(p)){if(Z(i,n)){let a=g(i,n);c("timer:end",a),s(),O(a),w()}return}F(p,S,u)},[O,s,c,F]),L=(0,o.useCallback)((n=f())=>{let u=r.current.updateIntervalMs??1e3,i=u;return l.current.status!=="running"?u:((r.current.schedules??[]).forEach((a,M)=>{let T=a.id??String(M),v=A.current.get(T)?.lastRunAt??n.wallNow;i=Math.min(i,Math.max(1,v+a.everyMs-n.wallNow))}),i)},[]),U=(0,o.useCallback)(()=>{let n=f();if(!J(l.current,n))return;let u=g(l.current,n);c("timer:start",u),b(n,!0),w()},[c,b]),K=(0,o.useCallback)(()=>{let n=f();if(!Q(l.current,n))return;s();let u=g(l.current,n);c("timer:pause",u),w()},[s,c]),W=(0,o.useCallback)(()=>{let n=f();if(!V(l.current,n))return;let u=g(l.current,n);c("timer:resume",u),b(n,!0),w()},[c,b]),$=(0,o.useCallback)((n={})=>{let u=f();s(),G(l.current,u,n),A.current.clear(),C.current=null;let i=g(l.current,u);c("timer:reset",i),n.autoStart&&b(u,!0),w()},[s,c,b]),j=(0,o.useCallback)(()=>{let n=f();s(),X(l.current,n),A.current.clear(),C.current=null;let u=g(l.current,n);c("timer:restart",u),b(n,!0),w()},[s,c,b]),q=(0,o.useCallback)(n=>{let u=f();if(!Y(l.current,u,n))return;s();let i=g(l.current,u);c("timer:cancel",i,{reason:n}),w()},[s,c]);k.current=(0,o.useMemo)(()=>({start:U,pause:K,resume:W,reset:$,restart:j,cancel:q}),[q,K,$,j,W,U]),(0,o.useEffect)(()=>(d.current=!0,r.current.autoStart&&l.current.status==="idle"&&k.current.start(),()=>{d.current=!1,s()}),[s]);let D=N(),z=l.current.generation,B=D.status;return(0,o.useEffect)(()=>{if(!d.current||B!=="running"){s();return}return s(),c("scheduler:start",N()),R.current=setTimeout(()=>{if(!d.current||l.current.generation!==z||l.current.status!=="running")return;let n=f();_(l.current,n);let u=g(l.current,n);c("timer:tick",u),b(n),w()},L()),()=>{R.current!==null&&c("scheduler:stop",N()),s()}},[s,c,z,L,N,b,D.tick,B]),{...D,...k.current}}function se(e){e?.forEach(t=>P(t.everyMs,"schedule.everyMs"))}function ee(e,t,r,l,d){return{scheduleId:e.id??t,scheduledAt:r,firedAt:l,nextRunAt:r+e.everyMs,overdueCount:d,effectiveEveryMs:e.everyMs}}0&&(module.exports={useScheduledTimer});
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,5 +1,5 @@
1
- import { h as UseScheduledTimerOptions, T as TimerSnapshot, a as TimerControls } from './types-4uFJF2Fx.cjs';
2
- export { i as TimerDebug, j as TimerDebugEvent, k as TimerDebugLogger, l as TimerSchedule, m as TimerScheduleContext } from './types-4uFJF2Fx.cjs';
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';
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-4uFJF2Fx.js';
2
- export { i as TimerDebug, j as TimerDebugEvent, k as TimerDebugLogger, l as TimerSchedule, m as TimerScheduleContext } from './types-4uFJF2Fx.js';
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';
3
3
 
4
4
  declare function useScheduledTimer(options?: UseScheduledTimerOptions): TimerSnapshot & TimerControls;
5
5
 
package/dist/schedules.js CHANGED
@@ -1 +1 @@
1
- import{a as y,b}from"./chunk-65MJVHTI.js";import{a as l,b as G,c as B,d as f,e as H,f as J,g as Q,h as V,i as X,j as Y,k as Z,l as _}from"./chunk-I3PNNG3I.js";import{useCallback as i,useEffect as $,useMemo as re,useReducer as ne,useRef as v}from"react";function ue(p={}){let k=p.updateIntervalMs??1e3;G(k,"updateIntervalMs"),ce(p.schedules);let s=v(p);s.current=p;let r=v(null);r.current===null&&(r.current=B(l()));let R=v(!1),M=v(null),T=v(new Map),D=v(null),[,g]=ne(e=>e+1,0),o=i(()=>{M.current!==null&&(clearTimeout(M.current),M.current=null)},[]),E=i((e=l())=>f(r.current,e),[]),c=i((e,t,n={})=>{y(s.current.debug,{type:e,scope:"timer",...b(t,r.current.generation),...n})},[]),A=v(null),P=i(e=>{let t=r.current.generation;if(D.current!==t){D.current=t;try{s.current.onEnd?.(e,A.current)}catch(n){y(s.current.debug,{type:"callback:error",scope:"timer",...b(e,t),error:n})}}},[]),I=i((e,t,n,m,d,u)=>{if(n.pending&&(e.overlap??"skip")==="skip"){n.lastRunAt=u.scheduledAt,y(s.current.debug,{type:"schedule:skip",scope:"timer",reason:"overlap",...u,...b(m,d)});return}n.lastRunAt=u.scheduledAt,n.pending=!0,y(s.current.debug,{type:"schedule:start",scope:"timer",...u,...b(m,d)}),Promise.resolve().then(()=>e.callback(m,A.current,u)).then(()=>{y(s.current.debug,{type:"schedule:end",scope:"timer",...u,...b(m,d)})},C=>{y(s.current.debug,{type:"schedule:error",scope:"timer",error:C,...u,...b(m,d)})}).finally(()=>{r.current?.generation===d&&(n.pending=!1)})},[]),N=i((e,t,n=!1)=>{let m=s.current.schedules??[],d=new Set;m.forEach((u,C)=>{let h=u.id??String(C);d.add(h);let a=T.current.get(h);if(a||(a={lastRunAt:null,pending:!1,leadingGeneration:null},T.current.set(h,a)),n&&u.leading&&a.leadingGeneration!==t){a.leadingGeneration=t,I(u,h,a,e,t,ee(u,h,e.now,e.now,0));return}a.lastRunAt===null&&(a.lastRunAt=r.current.startedAt??e.now);let w=Math.floor((e.now-a.lastRunAt)/u.everyMs);if(w>=1){let te=a.lastRunAt+w*u.everyMs;I(u,h,a,e,t,ee(u,h,te,e.now,w-1))}});for(let u of T.current.keys())d.has(u)||T.current.delete(u)},[I]),S=i((e=l(),t=!1)=>{let n=r.current;if(n.status!=="running")return;let m=f(n,e),d=n.generation;if(s.current.endWhen?.(m)){if(Z(n,e)){let u=f(n,e);c("timer:end",u),o(),P(u),g()}return}N(m,d,t)},[P,o,c,N]),O=i((e=l())=>{let t=s.current.updateIntervalMs??1e3,n=t;return r.current.status!=="running"?t:((s.current.schedules??[]).forEach((u,C)=>{let h=u.id??String(C),w=T.current.get(h)?.lastRunAt??e.wallNow;n=Math.min(n,Math.max(1,w+u.everyMs-e.wallNow))}),n)},[]),U=i(()=>{let e=l();if(!H(r.current,e))return;let t=f(r.current,e);c("timer:start",t),S(e,!0),g()},[c,S]),F=i(()=>{let e=l();if(!J(r.current,e))return;o();let t=f(r.current,e);c("timer:pause",t),g()},[o,c]),K=i(()=>{let e=l();if(!Q(r.current,e))return;let t=f(r.current,e);c("timer:resume",t),S(e,!0),g()},[c,S]),L=i((e={})=>{let t=l();o(),V(r.current,t,e),T.current.clear(),D.current=null;let n=f(r.current,t);c("timer:reset",n),e.autoStart&&S(t,!0),g()},[o,c,S]),W=i(()=>{let e=l();o(),X(r.current,e),T.current.clear(),D.current=null;let t=f(r.current,e);c("timer:restart",t),S(e,!0),g()},[o,c,S]),j=i(e=>{let t=l();if(!Y(r.current,t,e))return;o();let n=f(r.current,t);c("timer:cancel",n,{reason:e}),g()},[o,c]);A.current=re(()=>({start:U,pause:F,resume:K,reset:L,restart:W,cancel:j}),[j,F,L,W,K,U]),$(()=>(R.current=!0,s.current.autoStart&&r.current.status==="idle"&&A.current.start(),()=>{R.current=!1,o()}),[o]);let x=E(),q=r.current.generation,z=x.status;return $(()=>{if(!R.current||z!=="running"){o();return}return o(),c("scheduler:start",E()),M.current=setTimeout(()=>{if(!R.current||r.current.generation!==q||r.current.status!=="running")return;let e=l();_(r.current,e);let t=f(r.current,e);c("timer:tick",t),S(e),g()},O()),()=>{M.current!==null&&c("scheduler:stop",E()),o()}},[o,c,q,O,E,S,x.tick,z]),{...x,...A.current}}function ce(p){p?.forEach(k=>G(k.everyMs,"schedule.everyMs"))}function ee(p,k,s,r,R){return{scheduleId:p.id??k,scheduledAt:s,firedAt:r,nextRunAt:s+p.everyMs,overdueCount:R,effectiveEveryMs:p.everyMs}}export{ue as useScheduledTimer};
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};
@@ -24,7 +24,7 @@ type TimerSnapshot = {
24
24
  isEnded: boolean;
25
25
  isCancelled: boolean;
26
26
  };
27
- type TimerControls = {
27
+ type TimerLifecycleControls = {
28
28
  start(): void;
29
29
  pause(): void;
30
30
  resume(): void;
@@ -34,6 +34,7 @@ type TimerControls = {
34
34
  restart(): void;
35
35
  cancel(reason?: string): void;
36
36
  };
37
+ type TimerControls = TimerLifecycleControls;
37
38
  type TimerEndPredicate = (snapshot: TimerSnapshot) => boolean;
38
39
  type TimerScheduleContext = {
39
40
  scheduleId: string;
@@ -50,14 +51,14 @@ type TimerSchedule = {
50
51
  overlap?: 'skip' | 'allow';
51
52
  callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
52
53
  };
53
- type TimerDebug = boolean | TimerDebugLogger | {
54
+ type TimerDiagnostics = TimerDiagnosticsLogger | {
54
55
  enabled?: boolean;
55
- logger?: TimerDebugLogger;
56
+ logger: TimerDiagnosticsLogger;
56
57
  includeTicks?: boolean;
57
58
  label?: string;
58
59
  };
59
- type TimerDebugLogger = (event: TimerDebugEvent) => void;
60
- type TimerDebugEvent = {
60
+ type TimerDiagnosticsLogger = (event: TimerDiagnosticsEvent) => void;
61
+ type TimerDiagnosticsEvent = {
61
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';
62
63
  scope: 'timer' | 'timer-group';
63
64
  label?: string;
@@ -84,18 +85,9 @@ type UseTimerOptions = {
84
85
  };
85
86
  type UseScheduledTimerOptions = UseTimerOptions & {
86
87
  schedules?: TimerSchedule[];
87
- debug?: TimerDebug;
88
- };
89
- type TimerGroupItemControls = {
90
- start(): void;
91
- pause(): void;
92
- resume(): void;
93
- reset(options?: {
94
- autoStart?: boolean;
95
- }): void;
96
- restart(): void;
97
- cancel(reason?: string): void;
88
+ diagnostics?: TimerDiagnostics;
98
89
  };
90
+ type TimerGroupItemControls = TimerLifecycleControls;
99
91
  type TimerGroupItem = {
100
92
  id: string;
101
93
  autoStart?: boolean;
@@ -106,7 +98,7 @@ type TimerGroupItem = {
106
98
  type UseTimerGroupOptions = {
107
99
  updateIntervalMs?: number;
108
100
  items?: TimerGroupItem[];
109
- debug?: TimerDebug;
101
+ diagnostics?: TimerDiagnostics;
110
102
  };
111
103
  type TimerGroupResult = {
112
104
  now: number;
@@ -135,4 +127,4 @@ type TimerGroupResult = {
135
127
  cancelAll(reason?: string): void;
136
128
  };
137
129
 
138
- export type { DurationParts as D, TimerSnapshot as T, UseTimerOptions as U, TimerControls as a, TimerEndPredicate as b, TimerStatus as c, UseTimerGroupOptions as d, TimerGroupResult as e, TimerGroupItem as f, TimerGroupItemControls as g, UseScheduledTimerOptions as h, TimerDebug as i, TimerDebugEvent as j, TimerDebugLogger as k, TimerSchedule as l, TimerScheduleContext as m };
130
+ export type { DurationParts as D, TimerSnapshot as T, UseTimerOptions as U, TimerControls as a, TimerEndPredicate as b, TimerStatus as c, UseTimerGroupOptions as d, TimerGroupResult as e, TimerGroupItem as f, TimerGroupItemControls as g, UseScheduledTimerOptions as h, TimerDiagnostics as i, TimerDiagnosticsEvent as j, TimerDiagnosticsLogger as k, TimerSchedule as l, TimerScheduleContext as m };
@@ -24,7 +24,7 @@ type TimerSnapshot = {
24
24
  isEnded: boolean;
25
25
  isCancelled: boolean;
26
26
  };
27
- type TimerControls = {
27
+ type TimerLifecycleControls = {
28
28
  start(): void;
29
29
  pause(): void;
30
30
  resume(): void;
@@ -34,6 +34,7 @@ type TimerControls = {
34
34
  restart(): void;
35
35
  cancel(reason?: string): void;
36
36
  };
37
+ type TimerControls = TimerLifecycleControls;
37
38
  type TimerEndPredicate = (snapshot: TimerSnapshot) => boolean;
38
39
  type TimerScheduleContext = {
39
40
  scheduleId: string;
@@ -50,14 +51,14 @@ type TimerSchedule = {
50
51
  overlap?: 'skip' | 'allow';
51
52
  callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
52
53
  };
53
- type TimerDebug = boolean | TimerDebugLogger | {
54
+ type TimerDiagnostics = TimerDiagnosticsLogger | {
54
55
  enabled?: boolean;
55
- logger?: TimerDebugLogger;
56
+ logger: TimerDiagnosticsLogger;
56
57
  includeTicks?: boolean;
57
58
  label?: string;
58
59
  };
59
- type TimerDebugLogger = (event: TimerDebugEvent) => void;
60
- type TimerDebugEvent = {
60
+ type TimerDiagnosticsLogger = (event: TimerDiagnosticsEvent) => void;
61
+ type TimerDiagnosticsEvent = {
61
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';
62
63
  scope: 'timer' | 'timer-group';
63
64
  label?: string;
@@ -84,18 +85,9 @@ type UseTimerOptions = {
84
85
  };
85
86
  type UseScheduledTimerOptions = UseTimerOptions & {
86
87
  schedules?: TimerSchedule[];
87
- debug?: TimerDebug;
88
- };
89
- type TimerGroupItemControls = {
90
- start(): void;
91
- pause(): void;
92
- resume(): void;
93
- reset(options?: {
94
- autoStart?: boolean;
95
- }): void;
96
- restart(): void;
97
- cancel(reason?: string): void;
88
+ diagnostics?: TimerDiagnostics;
98
89
  };
90
+ type TimerGroupItemControls = TimerLifecycleControls;
99
91
  type TimerGroupItem = {
100
92
  id: string;
101
93
  autoStart?: boolean;
@@ -106,7 +98,7 @@ type TimerGroupItem = {
106
98
  type UseTimerGroupOptions = {
107
99
  updateIntervalMs?: number;
108
100
  items?: TimerGroupItem[];
109
- debug?: TimerDebug;
101
+ diagnostics?: TimerDiagnostics;
110
102
  };
111
103
  type TimerGroupResult = {
112
104
  now: number;
@@ -135,4 +127,4 @@ type TimerGroupResult = {
135
127
  cancelAll(reason?: string): void;
136
128
  };
137
129
 
138
- export type { DurationParts as D, TimerSnapshot as T, UseTimerOptions as U, TimerControls as a, TimerEndPredicate as b, TimerStatus as c, UseTimerGroupOptions as d, TimerGroupResult as e, TimerGroupItem as f, TimerGroupItemControls as g, UseScheduledTimerOptions as h, TimerDebug as i, TimerDebugEvent as j, TimerDebugLogger as k, TimerSchedule as l, TimerScheduleContext as m };
130
+ export type { DurationParts as D, TimerSnapshot as T, UseTimerOptions as U, TimerControls as a, TimerEndPredicate as b, TimerStatus as c, UseTimerGroupOptions as d, TimerGroupResult as e, TimerGroupItem as f, TimerGroupItemControls as g, UseScheduledTimerOptions as h, TimerDiagnostics as i, TimerDiagnosticsEvent as j, TimerDiagnosticsLogger as k, TimerSchedule as l, TimerScheduleContext as m };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crup/react-timer-hook",
3
- "version": "0.0.1-alpha.12",
3
+ "version": "0.0.1-alpha.13",
4
4
  "description": "A lightweight React hooks library for building timers, stopwatches, and real-time clocks with minimal boilerplate.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -1 +0,0 @@
1
- function n(e){return e?e===!0?{enabled:!0,includeTicks:!1,logger:console.debug}:typeof e=="function"?{enabled:!0,includeTicks:!1,logger:e}:{enabled:e.enabled!==!1,includeTicks:e.includeTicks??!1,label:e.label,logger:e.logger??console.debug}:{enabled:!1,includeTicks:!1}}function r(e,i){let l=n(e);!l.enabled||!l.logger||i.type==="timer:tick"&&!l.includeTicks||l.logger({...i,label:i.label??l.label})}function t(e,i){return{generation:i,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}export{r as a,t as b};