@crup/react-timer-hook 0.0.1-alpha.10 → 0.0.1-alpha.11

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
@@ -1,6 +1,6 @@
1
1
  # @crup/react-timer-hook
2
2
 
3
- > React timer hooks for countdowns, stopwatches, clocks, polling schedules, and many independent timer lifecycles.
3
+ > ~1.2 kB timer core for React, with opt-in batteries for schedules, diagnostics, duration math, and many independent timers.
4
4
 
5
5
  [![npm alpha](https://img.shields.io/npm/v/%40crup%2Freact-timer-hook/alpha?label=npm%20alpha&color=00b894)](https://www.npmjs.com/package/@crup/react-timer-hook?activeTab=versions)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/%40crup%2Freact-timer-hook?color=0f766e)](https://www.npmjs.com/package/@crup/react-timer-hook)
@@ -17,11 +17,13 @@
17
17
 
18
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.
19
19
 
20
- `@crup/react-timer-hook` keeps the API small and lets your app decide what time means:
20
+ `@crup/react-timer-hook` starts with a tiny core and lets your app compose the heavier pieces only when it needs them:
21
21
 
22
- - ⏱️ `useTimer()` for one lifecycle: stopwatch, countdown, clock, schedule, or custom flow.
23
- - 🧭 `useTimerGroup()` for many keyed lifecycles with one shared scheduler.
24
- - 🧩 `durationParts()` for display math without locale or timezone opinions.
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.
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.
25
27
  - 🧼 No formatting, timezone, audio, retry, cache, or data-fetching policy baked in.
26
28
  - 🧪 Built for rerenders, Strict Mode, async callbacks, cleanup, and many timers.
27
29
  - 🤖 Agent-friendly docs through hosted `llms.txt`, `llms-full.txt`, and an optional MCP docs helper.
@@ -36,7 +38,10 @@ pnpm add @crup/react-timer-hook@alpha
36
38
  ```
37
39
 
38
40
  ```tsx
39
- import { durationParts, useTimer, useTimerGroup } from '@crup/react-timer-hook';
41
+ import { useTimer } from '@crup/react-timer-hook';
42
+ import { durationParts } from '@crup/react-timer-hook/duration';
43
+ import { useTimerGroup } from '@crup/react-timer-hook/group';
44
+ import { useScheduledTimer } from '@crup/react-timer-hook/schedules';
40
45
  ```
41
46
 
42
47
  ## Live recipes
@@ -99,7 +104,9 @@ export function AuctionTimer({ auctionId, expiresAt }: {
99
104
  Schedules run while the timer is active. Slow async work is skipped by default with `overlap: 'skip'`.
100
105
 
101
106
  ```tsx
102
- const timer = useTimer({
107
+ import { useScheduledTimer } from '@crup/react-timer-hook/schedules';
108
+
109
+ const timer = useScheduledTimer({
103
110
  autoStart: true,
104
111
  updateIntervalMs: 1000,
105
112
  endWhen: snapshot => snapshot.now >= expiresAt,
@@ -123,6 +130,8 @@ const timer = useTimer({
123
130
  Use `useTimerGroup()` when every row needs its own pause, resume, cancel, restart, schedules, or `onEnd`.
124
131
 
125
132
  ```tsx
133
+ import { useTimerGroup } from '@crup/react-timer-hook/group';
134
+
126
135
  const timers = useTimerGroup({
127
136
  updateIntervalMs: 1000,
128
137
  items: auctions.map(auction => ({
@@ -136,13 +145,15 @@ const timers = useTimerGroup({
136
145
 
137
146
  ## Bundle size
138
147
 
139
- Current build:
148
+ The core import stays small. Extra capabilities are opt-in batteries.
140
149
 
141
- | File | Raw | Gzip | Brotli |
150
+ | Entry | Raw | Gzip | Brotli |
142
151
  | --- | ---: | ---: | ---: |
143
- | `dist/index.js` | 12.80 kB | 3.88 kB | 3.47 kB |
144
- | `dist/index.cjs` | 14.04 kB | 4.12 kB | 3.70 kB |
145
- | `dist/index.d.ts` | 4.32 kB | 1.04 kB | 951 B |
152
+ | core | 3.82 kB | 1.31 kB | 1.21 kB |
153
+ | timer group add-on | 8.94 kB | 2.97 kB | 2.70 kB |
154
+ | schedules add-on | 6.88 kB | 2.32 kB | 2.13 kB |
155
+ | duration helper | 318 B | 224 B | 192 B |
156
+ | diagnostics helper | 105 B | 115 B | 99 B |
146
157
 
147
158
  CI writes a size summary to the GitHub Actions UI and posts bundle-size reports on pull requests.
148
159
 
@@ -0,0 +1 @@
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};
@@ -0,0 +1 @@
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};
@@ -0,0 +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});
@@ -0,0 +1,9 @@
1
+ import { i as TimerDebug } from './types-4uFJF2Fx.cjs';
2
+ export { j as TimerDebugEvent, k as TimerDebugLogger } from './types-4uFJF2Fx.cjs';
3
+
4
+ declare function consoleTimerDiagnostics(options?: {
5
+ includeTicks?: boolean;
6
+ label?: string;
7
+ }): TimerDebug;
8
+
9
+ export { TimerDebug, consoleTimerDiagnostics };
@@ -0,0 +1,9 @@
1
+ import { i as TimerDebug } from './types-4uFJF2Fx.js';
2
+ export { j as TimerDebugEvent, k as TimerDebugLogger } from './types-4uFJF2Fx.js';
3
+
4
+ declare function consoleTimerDiagnostics(options?: {
5
+ includeTicks?: boolean;
6
+ label?: string;
7
+ }): TimerDebug;
8
+
9
+ export { TimerDebug, consoleTimerDiagnostics };
@@ -0,0 +1 @@
1
+ function i(e={}){return{...e,logger:r=>console.debug("[timer]",r)}}export{i as consoleTimerDiagnostics};
@@ -0,0 +1 @@
1
+ "use strict";var a=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var l=(o,t)=>{for(var s in t)a(o,s,{get:t[s],enumerable:!0})},E=(o,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of D(t))!N.call(o,r)&&r!==s&&a(o,r,{get:()=>t[r],enumerable:!(n=f(t,r))||n.enumerable});return o};var O=o=>E(a({},"__esModule",{value:!0}),o);var h={};l(h,{durationParts:()=>i});module.exports=O(h);function i(o){let t=Math.max(0,Math.trunc(Number.isFinite(o)?o:0)),s=Math.floor(t/864e5),n=t%864e5,r=Math.floor(n/36e5),e=n%36e5,u=Math.floor(e/6e4),c=e%6e4,M=Math.floor(c/1e3);return{totalMilliseconds:t,totalSeconds:Math.floor(t/1e3),milliseconds:c%1e3,seconds:M,minutes:u,hours:r,days:s}}0&&(module.exports={durationParts});
@@ -0,0 +1,5 @@
1
+ import { D as DurationParts } from './types-4uFJF2Fx.cjs';
2
+
3
+ declare function durationParts(milliseconds: number): DurationParts;
4
+
5
+ export { DurationParts, durationParts };
@@ -0,0 +1,5 @@
1
+ import { D as DurationParts } from './types-4uFJF2Fx.js';
2
+
3
+ declare function durationParts(milliseconds: number): DurationParts;
4
+
5
+ export { DurationParts, durationParts };
@@ -0,0 +1 @@
1
+ function u(o){let t=Math.max(0,Math.trunc(Number.isFinite(o)?o:0)),a=Math.floor(t/864e5),r=t%864e5,e=Math.floor(r/36e5),s=r%36e5,c=Math.floor(s/6e4),n=s%6e4,i=Math.floor(n/1e3);return{totalMilliseconds:t,totalSeconds:Math.floor(t/1e3),milliseconds:n%1e3,seconds:i,minutes:c,hours:e,days:a}}export{u as durationParts};
package/dist/group.cjs ADDED
@@ -0,0 +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});
@@ -0,0 +1,6 @@
1
+ import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-4uFJF2Fx.cjs';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-4uFJF2Fx.cjs';
3
+
4
+ declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
5
+
6
+ export { TimerGroupResult, UseTimerGroupOptions, useTimerGroup };
@@ -0,0 +1,6 @@
1
+ import { d as UseTimerGroupOptions, e as TimerGroupResult } from './types-4uFJF2Fx.js';
2
+ export { f as TimerGroupItem, g as TimerGroupItemControls } from './types-4uFJF2Fx.js';
3
+
4
+ declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
5
+
6
+ export { TimerGroupResult, UseTimerGroupOptions, useTimerGroup };
package/dist/group.js ADDED
@@ -0,0 +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};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var de=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var Ae=(e,o)=>{for(var a in o)de(e,a,{get:o[a],enumerable:!0})},Ie=(e,o,a,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let y of ye(o))!we.call(e,y)&&y!==a&&de(e,y,{get:()=>o[y],enumerable:!(n=he(o,y))||n.enumerable});return e};var Me=e=>Ie(de({},"__esModule",{value:!0}),e);var Re={};Ae(Re,{durationParts:()=>fe,useTimer:()=>ge,useTimerGroup:()=>Te});module.exports=Me(Re);function fe(e){let o=Math.max(0,Math.trunc(Number.isFinite(e)?e:0)),a=Math.floor(o/864e5),n=o%864e5,y=Math.floor(n/36e5),M=n%36e5,T=Math.floor(M/6e4),v=M%6e4,D=Math.floor(v/1e3);return{totalMilliseconds:o,totalSeconds:Math.floor(o/1e3),milliseconds:v%1e3,seconds:D,minutes:T,hours:y,days:a}}var m=require("react");function ve(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 E(e,o){let a=ve(e);!a.enabled||!a.logger||o.type==="timer:tick"&&!a.includeTicks||a.logger({...o,label:o.label??a.label})}function G(e,o){return{generation:o,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function f(){let e=Date.now(),o=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:o}}function j(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 oe(e,o){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+o.monotonicNow-e.activeStartedAtMonotonic)}function S(e,o){let a=oe(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:a,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function q(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 ue(e,o){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=oe(e,o),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=o.wallNow,e.now=o.wallNow,!0)}function se(e,o){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=o.monotonicNow,e.now=o.wallNow,!0)}function te(e,o,a={}){return e.generation+=1,e.tick=0,e.status=a.autoStart?"running":"idle",e.startedAt=a.autoStart?o.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=a.autoStart?o.monotonicNow:null,e.now=o.wallNow,!0}function ae(e,o){return te(e,o,{autoStart:!0})}function ie(e,o,a){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=oe(e,o),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=o.wallNow,e.cancelReason=a??null,e.now=o.wallNow,!0)}function le(e,o){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=oe(e,o),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=o.wallNow,e.now=o.wallNow,!0)}function ce(e,o){return e.status!=="running"?!1:(e.tick+=1,e.now=o.wallNow,!0)}function ge(e={}){let o=e.updateIntervalMs??1e3;j(o,"updateIntervalMs"),ke(e.schedules);let a=(0,m.useRef)(e);a.current=e;let n=(0,m.useRef)(null);n.current===null&&(n.current=ne(f()));let y=(0,m.useRef)(!1),M=(0,m.useRef)(null),T=(0,m.useRef)(new Map),v=(0,m.useRef)(null),[,D]=(0,m.useReducer)(s=>s+1,0),c=(0,m.useCallback)(()=>{M.current!==null&&(clearTimeout(M.current),M.current=null)},[]),U=(0,m.useCallback)((s=f())=>S(n.current,s),[]),h=(0,m.useCallback)((s,d,g={})=>{E(a.current.debug,{type:s,scope:"timer",...G(d,n.current.generation),...g})},[]),$=(0,m.useRef)(null),B=(0,m.useCallback)(s=>{let d=n.current.generation;if(v.current!==d){v.current=d;try{a.current.onEnd?.(s,$.current)}catch(g){E(a.current.debug,{type:"callback:error",scope:"timer",...G(s,d),error:g})}}},[]),k=(0,m.useCallback)((s,d,g,R,C,p)=>{if(g.pending&&(s.overlap??"skip")==="skip"){g.lastRunAt=p.scheduledAt,E(a.current.debug,{type:"schedule:skip",scope:"timer",reason:"overlap",...p,...G(R,C)});return}g.lastRunAt=p.scheduledAt,g.pending=!0,E(a.current.debug,{type:"schedule:start",scope:"timer",...p,...G(R,C)}),Promise.resolve().then(()=>s.callback(R,$.current,p)).then(()=>{E(a.current.debug,{type:"schedule:end",scope:"timer",...p,...G(R,C)})},K=>{E(a.current.debug,{type:"schedule:error",scope:"timer",error:K,...p,...G(R,C)})}).finally(()=>{n.current?.generation===C&&(g.pending=!1)})},[]),J=(0,m.useCallback)((s,d,g=!1)=>{let R=a.current.schedules??[],C=new Set;R.forEach((p,K)=>{let N=p.id??String(K);C.add(N);let I=T.current.get(N);if(I||(I={lastRunAt:null,pending:!1,leadingGeneration:null},T.current.set(N,I)),g&&p.leading&&I.leadingGeneration!==d){I.leadingGeneration=d,k(p,N,I,s,d,pe(p,N,s.now,s.now,0));return}I.lastRunAt===null&&(I.lastRunAt=n.current.startedAt??s.now);let W=Math.floor((s.now-I.lastRunAt)/p.everyMs);if(W>=1){let re=I.lastRunAt+W*p.everyMs;k(p,N,I,s,d,pe(p,N,re,s.now,W-1))}});for(let p of T.current.keys())C.has(p)||T.current.delete(p)},[k]),A=(0,m.useCallback)((s=f(),d=!1)=>{let g=n.current;if(g.status!=="running")return;let R=S(g,s),C=g.generation;if(a.current.endWhen?.(R)){if(le(g,s)){let p=S(g,s);h("timer:end",p),c(),B(p),D()}return}J(R,C,d)},[B,c,h,J]),Q=(0,m.useCallback)((s=f())=>{let d=a.current.updateIntervalMs??1e3,g=d;return n.current.status!=="running"?d:((a.current.schedules??[]).forEach((p,K)=>{let N=p.id??String(K),W=T.current.get(N)?.lastRunAt??s.wallNow;g=Math.min(g,Math.max(1,W+p.everyMs-s.wallNow))}),g)},[]),V=(0,m.useCallback)(()=>{let s=f();if(!q(n.current,s))return;let d=S(n.current,s);h("timer:start",d),A(s,!0),D()},[h,A]),X=(0,m.useCallback)(()=>{let s=f();if(!ue(n.current,s))return;c();let d=S(n.current,s);h("timer:pause",d),D()},[c,h]),Z=(0,m.useCallback)(()=>{let s=f();if(!se(n.current,s))return;let d=S(n.current,s);h("timer:resume",d),A(s,!0),D()},[h,A]),_=(0,m.useCallback)((s={})=>{let d=f();c(),te(n.current,d,s),T.current.clear(),v.current=null;let g=S(n.current,d);h("timer:reset",g),s.autoStart&&A(d,!0),D()},[c,h,A]),H=(0,m.useCallback)(()=>{let s=f();c(),ae(n.current,s),T.current.clear(),v.current=null;let d=S(n.current,s);h("timer:restart",d),A(s,!0),D()},[c,h,A]),L=(0,m.useCallback)(s=>{let d=f();if(!ie(n.current,d,s))return;c();let g=S(n.current,d);h("timer:cancel",g,{reason:s}),D()},[c,h]);$.current=(0,m.useMemo)(()=>({start:V,pause:X,resume:Z,reset:_,restart:H,cancel:L}),[L,X,_,H,Z,V]),(0,m.useEffect)(()=>(y.current=!0,a.current.autoStart&&n.current.status==="idle"&&$.current.start(),()=>{y.current=!1,c()}),[c]);let F=U(),Y=n.current.generation,z=F.status;return(0,m.useEffect)(()=>{if(!y.current||z!=="running"){c();return}return c(),h("scheduler:start",U()),M.current=setTimeout(()=>{if(!y.current||n.current.generation!==Y||n.current.status!=="running")return;let s=f();ce(n.current,s);let d=S(n.current,s);h("timer:tick",d),A(s),D()},Q()),()=>{M.current!==null&&h("scheduler:stop",U()),c()}},[c,h,Y,Q,U,A,F.tick,z]),{...F,...$.current}}function ke(e){e?.forEach(o=>j(o.everyMs,"schedule.everyMs"))}function pe(e,o,a,n,y){return{scheduleId:e.id??o,scheduledAt:a,firedAt:n,nextRunAt:a+e.everyMs,overdueCount:y,effectiveEveryMs:e.everyMs}}var l=require("react");function Te(e={}){let o=e.updateIntervalMs??1e3;j(o,"updateIntervalMs"),me(e.items);let a=(0,l.useRef)(e);a.current=e;let n=(0,l.useRef)(new Map),y=(0,l.useRef)(!1),M=(0,l.useRef)(null),[,T]=(0,l.useReducer)(t=>t+1,0),v=(0,l.useCallback)(()=>{M.current!==null&&(clearTimeout(M.current),M.current=null)},[]),D=(0,l.useCallback)((t,r=f())=>S(t.state,r),[]),c=(0,l.useCallback)((t,r,u,i={})=>{E(a.current.debug,{type:t,scope:"timer-group",timerId:r?.id,...G(u,r?.state.generation??0),...i})},[]),U=(0,l.useCallback)(t=>({start:()=>H(t),pause:()=>L(t),resume:()=>F(t),reset:r=>Y(t,r),restart:()=>z(t),cancel:r=>s(t,r)}),[]),h=(0,l.useCallback)((t,r)=>{let u=t.state.generation;if(t.endCalledGeneration!==u){t.endCalledGeneration=u;try{t.definition.onEnd?.(r,U(t.id))}catch(i){E(a.current.debug,{type:"callback:error",scope:"timer-group",timerId:t.id,error:i,...G(r,u)})}}},[U]),$=(0,l.useCallback)((t,r,u,i,w,b,O)=>{if(i.pending&&(r.overlap??"skip")==="skip"){i.lastRunAt=O.scheduledAt,E(a.current.debug,{type:"schedule:skip",scope:"timer-group",timerId:t.id,reason:"overlap",...O,...G(w,b)});return}i.lastRunAt=O.scheduledAt,i.pending=!0,E(a.current.debug,{type:"schedule:start",scope:"timer-group",timerId:t.id,...O,...G(w,b)}),Promise.resolve().then(()=>r.callback(w,U(t.id),O)).then(()=>{E(a.current.debug,{type:"schedule:end",scope:"timer-group",timerId:t.id,...O,...G(w,b)})},x=>{E(a.current.debug,{type:"schedule:error",scope:"timer-group",timerId:t.id,error:x,...O,...G(w,b)})}).finally(()=>{n.current.get(t.id)?.state.generation===b&&(i.pending=!1)})},[U]),B=(0,l.useCallback)((t,r,u=!1)=>{let i=t.definition.schedules??[],w=new Set;i.forEach((b,O)=>{let x=b.id??String(O);w.add(x);let P=t.schedules.get(x);if(P||(P={lastRunAt:null,pending:!1,leadingGeneration:null},t.schedules.set(x,P)),u&&b.leading&&P.leadingGeneration!==t.state.generation){P.leadingGeneration=t.state.generation,$(t,b,x,P,r,t.state.generation,Se(b,x,r.now,r.now,0));return}P.lastRunAt===null&&(P.lastRunAt=t.state.startedAt??r.now);let ee=Math.floor((r.now-P.lastRunAt)/b.everyMs);if(ee>=1){let be=P.lastRunAt+ee*b.everyMs;$(t,b,x,P,r,t.state.generation,Se(b,x,be,r.now,ee-1))}});for(let b of t.schedules.keys())w.has(b)||t.schedules.delete(b)},[$]),k=(0,l.useCallback)((t,r=f(),u=!1)=>{if(t.state.status!=="running")return;let i=S(t.state,r);if(t.definition.endWhen?.(i)){if(le(t.state,r)){let w=S(t.state,r);c("timer:end",t,w),h(t,w)}return}B(t,i,u)},[h,c,B]),J=(0,l.useCallback)((t=f())=>{let u=a.current.updateIntervalMs??1e3;for(let i of n.current.values()){if(i.state.status!=="running")continue;(i.definition.schedules??[]).forEach((b,O)=>{let x=b.id??String(O),ee=i.schedules.get(x)?.lastRunAt??t.wallNow;u=Math.min(u,Math.max(1,ee+b.everyMs-t.wallNow))})}return u},[]),A=(0,l.useCallback)(t=>{let r=n.current.get(t.id);if(r)return r.definition=t,{item:r,added:!1};let u={id:t.id,state:ne(f()),definition:t,schedules:new Map,endCalledGeneration:null};return n.current.set(t.id,u),t.autoStart&&q(u.state,f()),{item:u,added:!0}},[]),Q=(0,l.useCallback)(()=>{let t=a.current.items??[],r=new Set,u=!1;t.forEach(i=>{r.add(i.id);let{item:w,added:b}=A(i);u=u||b,i.autoStart&&w.state.status==="idle"&&(u=q(w.state,f())||u)});for(let i of n.current.keys())r.has(i)||(n.current.delete(i),u=!0);return u},[A]);(0,l.useEffect)(()=>{Q()&&T()},[Q,e.items]);let V=(0,l.useCallback)(t=>{if(me([t]),n.current.has(t.id))throw new Error(`Timer item "${t.id}" already exists`);A(t),T()},[A]),X=(0,l.useCallback)((t,r)=>{let u=n.current.get(t);if(!u)return;let i={...u.definition,...r,id:t};me([i]),u.definition=i,T()},[]),Z=(0,l.useCallback)(t=>{n.current.delete(t),T()},[]),_=(0,l.useCallback)(()=>{n.current.clear(),v(),T()},[v]),H=(0,l.useCallback)(t=>{let r=n.current.get(t);if(!r)return;let u=f();q(r.state,u)&&(c("timer:start",r,S(r.state,u)),k(r,u,!0),T())},[c,k]),L=(0,l.useCallback)(t=>{let r=n.current.get(t);if(!r)return;let u=f();ue(r.state,u)&&(c("timer:pause",r,S(r.state,u)),T())},[c]),F=(0,l.useCallback)(t=>{let r=n.current.get(t);if(!r)return;let u=f();se(r.state,u)&&(c("timer:resume",r,S(r.state,u)),k(r,u,!0),T())},[c,k]),Y=(0,l.useCallback)((t,r={})=>{let u=n.current.get(t);if(!u)return;let i=f();te(u.state,i,r),u.schedules.clear(),u.endCalledGeneration=null,c("timer:reset",u,S(u.state,i)),r.autoStart&&k(u,i,!0),T()},[c,k]),z=(0,l.useCallback)(t=>{let r=n.current.get(t);if(!r)return;let u=f();ae(r.state,u),r.schedules.clear(),r.endCalledGeneration=null,c("timer:restart",r,S(r.state,u)),k(r,u,!0),T()},[c,k]),s=(0,l.useCallback)((t,r)=>{let u=n.current.get(t);if(!u)return;let i=f();ie(u.state,i,r)&&(c("timer:cancel",u,S(u.state,i),{reason:r}),T())},[c]),g=Array.from(n.current.keys()).map(t=>`${t}:${n.current.get(t).state.status}:${n.current.get(t).state.generation}:${n.current.get(t).state.tick}`).join("|");(0,l.useEffect)(()=>{y.current=!0;let t=Array.from(n.current.values()).filter(u=>u.state.status==="running");if(t.length===0){v();return}v();let r=t[0];return c("scheduler:start",r,S(r.state,f())),M.current=setTimeout(()=>{if(!y.current)return;let u=f();for(let i of n.current.values()){if(i.state.status!=="running")continue;ce(i.state,u);let w=S(i.state,u);c("timer:tick",i,w),k(i,u)}T()},J()),()=>{M.current!==null&&c("scheduler:stop",r,S(r.state,f())),v(),y.current=!1}},[g,v,c,J,k]);let R=(0,l.useCallback)(t=>{let r=n.current.get(t);if(r)return D(r)},[D]),C=f().wallNow,p=(0,l.useCallback)(()=>Array.from(n.current.keys()).forEach(H),[H]),K=(0,l.useCallback)(()=>Array.from(n.current.keys()).forEach(L),[L]),N=(0,l.useCallback)(()=>Array.from(n.current.keys()).forEach(F),[F]),I=(0,l.useCallback)(t=>Array.from(n.current.keys()).forEach(r=>Y(r,t)),[Y]),W=(0,l.useCallback)(()=>Array.from(n.current.keys()).forEach(z),[z]),re=(0,l.useCallback)(t=>Array.from(n.current.keys()).forEach(r=>s(r,t)),[s]);return(0,l.useMemo)(()=>({now:C,size:n.current.size,ids:Array.from(n.current.keys()),get:R,add:V,update:X,remove:Z,clear:_,start:H,pause:L,resume:F,reset:Y,restart:z,cancel:s,startAll:p,pauseAll:K,resumeAll:N,resetAll:I,restartAll:W,cancelAll:re}),[V,s,re,_,R,C,L,K,Z,Y,I,z,W,F,N,H,p,X])}function me(e){let o=new Set;e?.forEach(a=>{if(o.has(a.id))throw new Error(`Duplicate timer item id "${a.id}"`);o.add(a.id),a.schedules?.forEach(n=>j(n.everyMs,"schedule.everyMs"))})}function Se(e,o,a,n,y){return{scheduleId:e.id??o,scheduledAt:a,firedAt:n,nextRunAt:a+e.everyMs,overdueCount:y,effectiveEveryMs:e.everyMs}}0&&(module.exports={durationParts,useTimer,useTimerGroup});
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,142 +1,6 @@
1
- type TimerStatus = 'idle' | 'running' | 'paused' | 'ended' | 'cancelled';
2
- type DurationParts = {
3
- totalMilliseconds: number;
4
- totalSeconds: number;
5
- milliseconds: number;
6
- seconds: number;
7
- minutes: number;
8
- hours: number;
9
- days: number;
10
- };
11
- type TimerSnapshot = {
12
- status: TimerStatus;
13
- now: number;
14
- tick: number;
15
- startedAt: number | null;
16
- pausedAt: number | null;
17
- endedAt: number | null;
18
- cancelledAt: number | null;
19
- cancelReason: string | null;
20
- elapsedMilliseconds: number;
21
- isIdle: boolean;
22
- isRunning: boolean;
23
- isPaused: boolean;
24
- isEnded: boolean;
25
- isCancelled: boolean;
26
- };
27
- type TimerControls = {
28
- start(): void;
29
- pause(): void;
30
- resume(): void;
31
- reset(options?: {
32
- autoStart?: boolean;
33
- }): void;
34
- restart(): void;
35
- cancel(reason?: string): void;
36
- };
37
- type TimerEndPredicate = (snapshot: TimerSnapshot) => boolean;
38
- type TimerScheduleContext = {
39
- scheduleId: string;
40
- scheduledAt: number;
41
- firedAt: number;
42
- nextRunAt: number;
43
- overdueCount: number;
44
- effectiveEveryMs: number;
45
- };
46
- type TimerSchedule = {
47
- id?: string;
48
- everyMs: number;
49
- leading?: boolean;
50
- overlap?: 'skip' | 'allow';
51
- callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
52
- };
53
- type TimerDebug = boolean | TimerDebugLogger | {
54
- enabled?: boolean;
55
- logger?: TimerDebugLogger;
56
- includeTicks?: boolean;
57
- label?: string;
58
- };
59
- type TimerDebugLogger = (event: TimerDebugEvent) => void;
60
- type TimerDebugEvent = {
61
- 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
- scope: 'timer' | 'timer-group';
63
- label?: string;
64
- timerId?: string;
65
- scheduleId?: string;
66
- generation: number;
67
- tick: number;
68
- now: number;
69
- elapsedMilliseconds: number;
70
- status: TimerStatus;
71
- reason?: string;
72
- error?: unknown;
73
- scheduledAt?: number;
74
- firedAt?: number;
75
- nextRunAt?: number;
76
- overdueCount?: number;
77
- effectiveEveryMs?: number;
78
- };
79
- type UseTimerOptions = {
80
- autoStart?: boolean;
81
- updateIntervalMs?: number;
82
- endWhen?: TimerEndPredicate;
83
- onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
84
- schedules?: TimerSchedule[];
85
- debug?: TimerDebug;
86
- };
87
- type TimerGroupItemControls = {
88
- start(): void;
89
- pause(): void;
90
- resume(): void;
91
- reset(options?: {
92
- autoStart?: boolean;
93
- }): void;
94
- restart(): void;
95
- cancel(reason?: string): void;
96
- };
97
- type TimerGroupItem = {
98
- id: string;
99
- autoStart?: boolean;
100
- endWhen?: TimerEndPredicate;
101
- onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
102
- schedules?: TimerSchedule[];
103
- };
104
- type UseTimerGroupOptions = {
105
- updateIntervalMs?: number;
106
- items?: TimerGroupItem[];
107
- debug?: TimerDebug;
108
- };
109
- type TimerGroupResult = {
110
- now: number;
111
- size: number;
112
- ids: string[];
113
- get(id: string): TimerSnapshot | undefined;
114
- add(item: TimerGroupItem): void;
115
- update(id: string, item: Partial<Omit<TimerGroupItem, 'id'>>): void;
116
- remove(id: string): void;
117
- clear(): void;
118
- start(id: string): void;
119
- pause(id: string): void;
120
- resume(id: string): void;
121
- reset(id: string, options?: {
122
- autoStart?: boolean;
123
- }): void;
124
- restart(id: string): void;
125
- cancel(id: string, reason?: string): void;
126
- startAll(): void;
127
- pauseAll(): void;
128
- resumeAll(): void;
129
- resetAll(options?: {
130
- autoStart?: boolean;
131
- }): void;
132
- restartAll(): void;
133
- cancelAll(reason?: string): void;
134
- };
135
-
136
- declare function durationParts(milliseconds: number): DurationParts;
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';
137
3
 
138
4
  declare function useTimer(options?: UseTimerOptions): TimerSnapshot & TimerControls;
139
5
 
140
- declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
141
-
142
- export { type DurationParts, type TimerControls, type TimerDebug, type TimerDebugEvent, type TimerDebugLogger, type TimerEndPredicate, type TimerGroupItem, type TimerGroupItemControls, type TimerGroupResult, type TimerSchedule, type TimerScheduleContext, type TimerSnapshot, type TimerStatus, type UseTimerGroupOptions, type UseTimerOptions, durationParts, useTimer, useTimerGroup };
6
+ export { TimerControls, TimerSnapshot, UseTimerOptions, useTimer };
package/dist/index.d.ts CHANGED
@@ -1,142 +1,6 @@
1
- type TimerStatus = 'idle' | 'running' | 'paused' | 'ended' | 'cancelled';
2
- type DurationParts = {
3
- totalMilliseconds: number;
4
- totalSeconds: number;
5
- milliseconds: number;
6
- seconds: number;
7
- minutes: number;
8
- hours: number;
9
- days: number;
10
- };
11
- type TimerSnapshot = {
12
- status: TimerStatus;
13
- now: number;
14
- tick: number;
15
- startedAt: number | null;
16
- pausedAt: number | null;
17
- endedAt: number | null;
18
- cancelledAt: number | null;
19
- cancelReason: string | null;
20
- elapsedMilliseconds: number;
21
- isIdle: boolean;
22
- isRunning: boolean;
23
- isPaused: boolean;
24
- isEnded: boolean;
25
- isCancelled: boolean;
26
- };
27
- type TimerControls = {
28
- start(): void;
29
- pause(): void;
30
- resume(): void;
31
- reset(options?: {
32
- autoStart?: boolean;
33
- }): void;
34
- restart(): void;
35
- cancel(reason?: string): void;
36
- };
37
- type TimerEndPredicate = (snapshot: TimerSnapshot) => boolean;
38
- type TimerScheduleContext = {
39
- scheduleId: string;
40
- scheduledAt: number;
41
- firedAt: number;
42
- nextRunAt: number;
43
- overdueCount: number;
44
- effectiveEveryMs: number;
45
- };
46
- type TimerSchedule = {
47
- id?: string;
48
- everyMs: number;
49
- leading?: boolean;
50
- overlap?: 'skip' | 'allow';
51
- callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
52
- };
53
- type TimerDebug = boolean | TimerDebugLogger | {
54
- enabled?: boolean;
55
- logger?: TimerDebugLogger;
56
- includeTicks?: boolean;
57
- label?: string;
58
- };
59
- type TimerDebugLogger = (event: TimerDebugEvent) => void;
60
- type TimerDebugEvent = {
61
- 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
- scope: 'timer' | 'timer-group';
63
- label?: string;
64
- timerId?: string;
65
- scheduleId?: string;
66
- generation: number;
67
- tick: number;
68
- now: number;
69
- elapsedMilliseconds: number;
70
- status: TimerStatus;
71
- reason?: string;
72
- error?: unknown;
73
- scheduledAt?: number;
74
- firedAt?: number;
75
- nextRunAt?: number;
76
- overdueCount?: number;
77
- effectiveEveryMs?: number;
78
- };
79
- type UseTimerOptions = {
80
- autoStart?: boolean;
81
- updateIntervalMs?: number;
82
- endWhen?: TimerEndPredicate;
83
- onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
84
- schedules?: TimerSchedule[];
85
- debug?: TimerDebug;
86
- };
87
- type TimerGroupItemControls = {
88
- start(): void;
89
- pause(): void;
90
- resume(): void;
91
- reset(options?: {
92
- autoStart?: boolean;
93
- }): void;
94
- restart(): void;
95
- cancel(reason?: string): void;
96
- };
97
- type TimerGroupItem = {
98
- id: string;
99
- autoStart?: boolean;
100
- endWhen?: TimerEndPredicate;
101
- onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
102
- schedules?: TimerSchedule[];
103
- };
104
- type UseTimerGroupOptions = {
105
- updateIntervalMs?: number;
106
- items?: TimerGroupItem[];
107
- debug?: TimerDebug;
108
- };
109
- type TimerGroupResult = {
110
- now: number;
111
- size: number;
112
- ids: string[];
113
- get(id: string): TimerSnapshot | undefined;
114
- add(item: TimerGroupItem): void;
115
- update(id: string, item: Partial<Omit<TimerGroupItem, 'id'>>): void;
116
- remove(id: string): void;
117
- clear(): void;
118
- start(id: string): void;
119
- pause(id: string): void;
120
- resume(id: string): void;
121
- reset(id: string, options?: {
122
- autoStart?: boolean;
123
- }): void;
124
- restart(id: string): void;
125
- cancel(id: string, reason?: string): void;
126
- startAll(): void;
127
- pauseAll(): void;
128
- resumeAll(): void;
129
- resetAll(options?: {
130
- autoStart?: boolean;
131
- }): void;
132
- restartAll(): void;
133
- cancelAll(reason?: string): void;
134
- };
135
-
136
- declare function durationParts(milliseconds: number): DurationParts;
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';
137
3
 
138
4
  declare function useTimer(options?: UseTimerOptions): TimerSnapshot & TimerControls;
139
5
 
140
- declare function useTimerGroup(options?: UseTimerGroupOptions): TimerGroupResult;
141
-
142
- export { type DurationParts, type TimerControls, type TimerDebug, type TimerDebugEvent, type TimerDebugLogger, type TimerEndPredicate, type TimerGroupItem, type TimerGroupItemControls, type TimerGroupResult, type TimerSchedule, type TimerScheduleContext, type TimerSnapshot, type TimerStatus, type UseTimerGroupOptions, type UseTimerOptions, durationParts, useTimer, useTimerGroup };
6
+ export { TimerControls, TimerSnapshot, UseTimerOptions, useTimer };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- function he(e){let u=Math.max(0,Math.trunc(Number.isFinite(e)?e:0)),a=Math.floor(u/864e5),n=u%864e5,A=Math.floor(n/36e5),I=n%36e5,S=Math.floor(I/6e4),M=I%6e4,D=Math.floor(M/1e3);return{totalMilliseconds:u,totalSeconds:Math.floor(u/1e3),milliseconds:M%1e3,seconds:D,minutes:S,hours:A,days:a}}import{useCallback as G,useEffect as pe,useMemo as we,useReducer as Ae,useRef as j}from"react";function ye(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 C(e,u){let a=ye(e);!a.enabled||!a.logger||u.type==="timer:tick"&&!a.includeTicks||a.logger({...u,label:u.label??a.label})}function E(e,u){return{generation:u,tick:e.tick,now:e.now,elapsedMilliseconds:e.elapsedMilliseconds,status:e.status}}function d(){let e=Date.now(),u=typeof performance<"u"&&typeof performance.now=="function"?performance.now():e;return{wallNow:e,monotonicNow:u}}function q(e,u){if(!Number.isFinite(e)||e<=0)throw new RangeError(`${u} must be a finite number greater than 0`)}function oe(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 ue(e,u){return e.status!=="running"||e.activeStartedAtMonotonic===null?e.baseElapsedMilliseconds:Math.max(0,e.baseElapsedMilliseconds+u.monotonicNow-e.activeStartedAtMonotonic)}function g(e,u){let a=ue(e,u);return{status:e.status,now:u.wallNow,tick:e.tick,startedAt:e.startedAt,pausedAt:e.pausedAt,endedAt:e.endedAt,cancelledAt:e.cancelledAt,cancelReason:e.cancelReason,elapsedMilliseconds:a,isIdle:e.status==="idle",isRunning:e.status==="running",isPaused:e.status==="paused",isEnded:e.status==="ended",isCancelled:e.status==="cancelled"}}function B(e,u){return e.status!=="idle"?!1:(e.status="running",e.startedAt=u.wallNow,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.activeStartedAtMonotonic=u.monotonicNow,e.now=u.wallNow,!0)}function se(e,u){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=ue(e,u),e.activeStartedAtMonotonic=null,e.status="paused",e.pausedAt=u.wallNow,e.now=u.wallNow,!0)}function ae(e,u){return e.status!=="paused"?!1:(e.status="running",e.pausedAt=null,e.activeStartedAtMonotonic=u.monotonicNow,e.now=u.wallNow,!0)}function re(e,u,a={}){return e.generation+=1,e.tick=0,e.status=a.autoStart?"running":"idle",e.startedAt=a.autoStart?u.wallNow:null,e.pausedAt=null,e.endedAt=null,e.cancelledAt=null,e.cancelReason=null,e.baseElapsedMilliseconds=0,e.activeStartedAtMonotonic=a.autoStart?u.monotonicNow:null,e.now=u.wallNow,!0}function ie(e,u){return re(e,u,{autoStart:!0})}function le(e,u,a){return e.status==="ended"||e.status==="cancelled"?!1:(e.baseElapsedMilliseconds=ue(e,u),e.activeStartedAtMonotonic=null,e.status="cancelled",e.cancelledAt=u.wallNow,e.cancelReason=a??null,e.now=u.wallNow,!0)}function ce(e,u){return e.status!=="running"?!1:(e.baseElapsedMilliseconds=ue(e,u),e.activeStartedAtMonotonic=null,e.status="ended",e.endedAt=u.wallNow,e.now=u.wallNow,!0)}function de(e,u){return e.status!=="running"?!1:(e.tick+=1,e.now=u.wallNow,!0)}function Ie(e={}){let u=e.updateIntervalMs??1e3;q(u,"updateIntervalMs"),Me(e.schedules);let a=j(e);a.current=e;let n=j(null);n.current===null&&(n.current=oe(d()));let A=j(!1),I=j(null),S=j(new Map),M=j(null),[,D]=Ae(s=>s+1,0),l=G(()=>{I.current!==null&&(clearTimeout(I.current),I.current=null)},[]),U=G((s=d())=>g(n.current,s),[]),b=G((s,c,p={})=>{C(a.current.debug,{type:s,scope:"timer",...E(c,n.current.generation),...p})},[]),$=j(null),J=G(s=>{let c=n.current.generation;if(M.current!==c){M.current=c;try{a.current.onEnd?.(s,$.current)}catch(p){C(a.current.debug,{type:"callback:error",scope:"timer",...E(s,c),error:p})}}},[]),v=G((s,c,p,k,R,m)=>{if(p.pending&&(s.overlap??"skip")==="skip"){p.lastRunAt=m.scheduledAt,C(a.current.debug,{type:"schedule:skip",scope:"timer",reason:"overlap",...m,...E(k,R)});return}p.lastRunAt=m.scheduledAt,p.pending=!0,C(a.current.debug,{type:"schedule:start",scope:"timer",...m,...E(k,R)}),Promise.resolve().then(()=>s.callback(k,$.current,m)).then(()=>{C(a.current.debug,{type:"schedule:end",scope:"timer",...m,...E(k,R)})},K=>{C(a.current.debug,{type:"schedule:error",scope:"timer",error:K,...m,...E(k,R)})}).finally(()=>{n.current?.generation===R&&(p.pending=!1)})},[]),Q=G((s,c,p=!1)=>{let k=a.current.schedules??[],R=new Set;k.forEach((m,K)=>{let N=m.id??String(K);R.add(N);let w=S.current.get(N);if(w||(w={lastRunAt:null,pending:!1,leadingGeneration:null},S.current.set(N,w)),p&&m.leading&&w.leadingGeneration!==c){w.leadingGeneration=c,v(m,N,w,s,c,ge(m,N,s.now,s.now,0));return}w.lastRunAt===null&&(w.lastRunAt=n.current.startedAt??s.now);let W=Math.floor((s.now-w.lastRunAt)/m.everyMs);if(W>=1){let ne=w.lastRunAt+W*m.everyMs;v(m,N,w,s,c,ge(m,N,ne,s.now,W-1))}});for(let m of S.current.keys())R.has(m)||S.current.delete(m)},[v]),y=G((s=d(),c=!1)=>{let p=n.current;if(p.status!=="running")return;let k=g(p,s),R=p.generation;if(a.current.endWhen?.(k)){if(ce(p,s)){let m=g(p,s);b("timer:end",m),l(),J(m),D()}return}Q(k,R,c)},[J,l,b,Q]),V=G((s=d())=>{let c=a.current.updateIntervalMs??1e3,p=c;return n.current.status!=="running"?c:((a.current.schedules??[]).forEach((m,K)=>{let N=m.id??String(K),W=S.current.get(N)?.lastRunAt??s.wallNow;p=Math.min(p,Math.max(1,W+m.everyMs-s.wallNow))}),p)},[]),X=G(()=>{let s=d();if(!B(n.current,s))return;let c=g(n.current,s);b("timer:start",c),y(s,!0),D()},[b,y]),Z=G(()=>{let s=d();if(!se(n.current,s))return;l();let c=g(n.current,s);b("timer:pause",c),D()},[l,b]),_=G(()=>{let s=d();if(!ae(n.current,s))return;let c=g(n.current,s);b("timer:resume",c),y(s,!0),D()},[b,y]),ee=G((s={})=>{let c=d();l(),re(n.current,c,s),S.current.clear(),M.current=null;let p=g(n.current,c);b("timer:reset",p),s.autoStart&&y(c,!0),D()},[l,b,y]),H=G(()=>{let s=d();l(),ie(n.current,s),S.current.clear(),M.current=null;let c=g(n.current,s);b("timer:restart",c),y(s,!0),D()},[l,b,y]),L=G(s=>{let c=d();if(!le(n.current,c,s))return;l();let p=g(n.current,c);b("timer:cancel",p,{reason:s}),D()},[l,b]);$.current=we(()=>({start:X,pause:Z,resume:_,reset:ee,restart:H,cancel:L}),[L,Z,ee,H,_,X]),pe(()=>(A.current=!0,a.current.autoStart&&n.current.status==="idle"&&$.current.start(),()=>{A.current=!1,l()}),[l]);let F=U(),Y=n.current.generation,z=F.status;return pe(()=>{if(!A.current||z!=="running"){l();return}return l(),b("scheduler:start",U()),I.current=setTimeout(()=>{if(!A.current||n.current.generation!==Y||n.current.status!=="running")return;let s=d();de(n.current,s);let c=g(n.current,s);b("timer:tick",c),y(s),D()},V()),()=>{I.current!==null&&b("scheduler:stop",U()),l()}},[l,b,Y,V,U,y,F.tick,z]),{...F,...$.current}}function Me(e){e?.forEach(u=>q(u.everyMs,"schedule.everyMs"))}function ge(e,u,a,n,A){return{scheduleId:e.id??u,scheduledAt:a,firedAt:n,nextRunAt:a+e.everyMs,overdueCount:A,effectiveEveryMs:e.everyMs}}import{useCallback as f,useEffect as Se,useMemo as ve,useReducer as ke,useRef as me}from"react";function Re(e={}){let u=e.updateIntervalMs??1e3;q(u,"updateIntervalMs"),fe(e.items);let a=me(e);a.current=e;let n=me(new Map),A=me(!1),I=me(null),[,S]=ke(t=>t+1,0),M=f(()=>{I.current!==null&&(clearTimeout(I.current),I.current=null)},[]),D=f((t,r=d())=>g(t.state,r),[]),l=f((t,r,o,i={})=>{C(a.current.debug,{type:t,scope:"timer-group",timerId:r?.id,...E(o,r?.state.generation??0),...i})},[]),U=f(t=>({start:()=>H(t),pause:()=>L(t),resume:()=>F(t),reset:r=>Y(t,r),restart:()=>z(t),cancel:r=>s(t,r)}),[]),b=f((t,r)=>{let o=t.state.generation;if(t.endCalledGeneration!==o){t.endCalledGeneration=o;try{t.definition.onEnd?.(r,U(t.id))}catch(i){C(a.current.debug,{type:"callback:error",scope:"timer-group",timerId:t.id,error:i,...E(r,o)})}}},[U]),$=f((t,r,o,i,h,T,O)=>{if(i.pending&&(r.overlap??"skip")==="skip"){i.lastRunAt=O.scheduledAt,C(a.current.debug,{type:"schedule:skip",scope:"timer-group",timerId:t.id,reason:"overlap",...O,...E(h,T)});return}i.lastRunAt=O.scheduledAt,i.pending=!0,C(a.current.debug,{type:"schedule:start",scope:"timer-group",timerId:t.id,...O,...E(h,T)}),Promise.resolve().then(()=>r.callback(h,U(t.id),O)).then(()=>{C(a.current.debug,{type:"schedule:end",scope:"timer-group",timerId:t.id,...O,...E(h,T)})},x=>{C(a.current.debug,{type:"schedule:error",scope:"timer-group",timerId:t.id,error:x,...O,...E(h,T)})}).finally(()=>{n.current.get(t.id)?.state.generation===T&&(i.pending=!1)})},[U]),J=f((t,r,o=!1)=>{let i=t.definition.schedules??[],h=new Set;i.forEach((T,O)=>{let x=T.id??String(O);h.add(x);let P=t.schedules.get(x);if(P||(P={lastRunAt:null,pending:!1,leadingGeneration:null},t.schedules.set(x,P)),o&&T.leading&&P.leadingGeneration!==t.state.generation){P.leadingGeneration=t.state.generation,$(t,T,x,P,r,t.state.generation,Te(T,x,r.now,r.now,0));return}P.lastRunAt===null&&(P.lastRunAt=t.state.startedAt??r.now);let te=Math.floor((r.now-P.lastRunAt)/T.everyMs);if(te>=1){let be=P.lastRunAt+te*T.everyMs;$(t,T,x,P,r,t.state.generation,Te(T,x,be,r.now,te-1))}});for(let T of t.schedules.keys())h.has(T)||t.schedules.delete(T)},[$]),v=f((t,r=d(),o=!1)=>{if(t.state.status!=="running")return;let i=g(t.state,r);if(t.definition.endWhen?.(i)){if(ce(t.state,r)){let h=g(t.state,r);l("timer:end",t,h),b(t,h)}return}J(t,i,o)},[b,l,J]),Q=f((t=d())=>{let o=a.current.updateIntervalMs??1e3;for(let i of n.current.values()){if(i.state.status!=="running")continue;(i.definition.schedules??[]).forEach((T,O)=>{let x=T.id??String(O),te=i.schedules.get(x)?.lastRunAt??t.wallNow;o=Math.min(o,Math.max(1,te+T.everyMs-t.wallNow))})}return o},[]),y=f(t=>{let r=n.current.get(t.id);if(r)return r.definition=t,{item:r,added:!1};let o={id:t.id,state:oe(d()),definition:t,schedules:new Map,endCalledGeneration:null};return n.current.set(t.id,o),t.autoStart&&B(o.state,d()),{item:o,added:!0}},[]),V=f(()=>{let t=a.current.items??[],r=new Set,o=!1;t.forEach(i=>{r.add(i.id);let{item:h,added:T}=y(i);o=o||T,i.autoStart&&h.state.status==="idle"&&(o=B(h.state,d())||o)});for(let i of n.current.keys())r.has(i)||(n.current.delete(i),o=!0);return o},[y]);Se(()=>{V()&&S()},[V,e.items]);let X=f(t=>{if(fe([t]),n.current.has(t.id))throw new Error(`Timer item "${t.id}" already exists`);y(t),S()},[y]),Z=f((t,r)=>{let o=n.current.get(t);if(!o)return;let i={...o.definition,...r,id:t};fe([i]),o.definition=i,S()},[]),_=f(t=>{n.current.delete(t),S()},[]),ee=f(()=>{n.current.clear(),M(),S()},[M]),H=f(t=>{let r=n.current.get(t);if(!r)return;let o=d();B(r.state,o)&&(l("timer:start",r,g(r.state,o)),v(r,o,!0),S())},[l,v]),L=f(t=>{let r=n.current.get(t);if(!r)return;let o=d();se(r.state,o)&&(l("timer:pause",r,g(r.state,o)),S())},[l]),F=f(t=>{let r=n.current.get(t);if(!r)return;let o=d();ae(r.state,o)&&(l("timer:resume",r,g(r.state,o)),v(r,o,!0),S())},[l,v]),Y=f((t,r={})=>{let o=n.current.get(t);if(!o)return;let i=d();re(o.state,i,r),o.schedules.clear(),o.endCalledGeneration=null,l("timer:reset",o,g(o.state,i)),r.autoStart&&v(o,i,!0),S()},[l,v]),z=f(t=>{let r=n.current.get(t);if(!r)return;let o=d();ie(r.state,o),r.schedules.clear(),r.endCalledGeneration=null,l("timer:restart",r,g(r.state,o)),v(r,o,!0),S()},[l,v]),s=f((t,r)=>{let o=n.current.get(t);if(!o)return;let i=d();le(o.state,i,r)&&(l("timer:cancel",o,g(o.state,i),{reason:r}),S())},[l]),p=Array.from(n.current.keys()).map(t=>`${t}:${n.current.get(t).state.status}:${n.current.get(t).state.generation}:${n.current.get(t).state.tick}`).join("|");Se(()=>{A.current=!0;let t=Array.from(n.current.values()).filter(o=>o.state.status==="running");if(t.length===0){M();return}M();let r=t[0];return l("scheduler:start",r,g(r.state,d())),I.current=setTimeout(()=>{if(!A.current)return;let o=d();for(let i of n.current.values()){if(i.state.status!=="running")continue;de(i.state,o);let h=g(i.state,o);l("timer:tick",i,h),v(i,o)}S()},Q()),()=>{I.current!==null&&l("scheduler:stop",r,g(r.state,d())),M(),A.current=!1}},[p,M,l,Q,v]);let k=f(t=>{let r=n.current.get(t);if(r)return D(r)},[D]),R=d().wallNow,m=f(()=>Array.from(n.current.keys()).forEach(H),[H]),K=f(()=>Array.from(n.current.keys()).forEach(L),[L]),N=f(()=>Array.from(n.current.keys()).forEach(F),[F]),w=f(t=>Array.from(n.current.keys()).forEach(r=>Y(r,t)),[Y]),W=f(()=>Array.from(n.current.keys()).forEach(z),[z]),ne=f(t=>Array.from(n.current.keys()).forEach(r=>s(r,t)),[s]);return ve(()=>({now:R,size:n.current.size,ids:Array.from(n.current.keys()),get:k,add:X,update:Z,remove:_,clear:ee,start:H,pause:L,resume:F,reset:Y,restart:z,cancel:s,startAll:m,pauseAll:K,resumeAll:N,resetAll:w,restartAll:W,cancelAll:ne}),[X,s,ne,ee,k,R,L,K,_,Y,w,z,W,F,N,H,m,Z])}function fe(e){let u=new Set;e?.forEach(a=>{if(u.has(a.id))throw new Error(`Duplicate timer item id "${a.id}"`);u.add(a.id),a.schedules?.forEach(n=>q(n.everyMs,"schedule.everyMs"))})}function Te(e,u,a,n,A){return{scheduleId:e.id??u,scheduledAt:a,firedAt:n,nextRunAt:a+e.everyMs,overdueCount:A,effectiveEveryMs:e.everyMs}}export{he as durationParts,Ie as useTimer,Re as useTimerGroup};
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};
@@ -0,0 +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});
@@ -0,0 +1,6 @@
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';
3
+
4
+ declare function useScheduledTimer(options?: UseScheduledTimerOptions): TimerSnapshot & TimerControls;
5
+
6
+ export { UseScheduledTimerOptions, useScheduledTimer };
@@ -0,0 +1,6 @@
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';
3
+
4
+ declare function useScheduledTimer(options?: UseScheduledTimerOptions): TimerSnapshot & TimerControls;
5
+
6
+ export { UseScheduledTimerOptions, useScheduledTimer };
@@ -0,0 +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};
@@ -0,0 +1,138 @@
1
+ type TimerStatus = 'idle' | 'running' | 'paused' | 'ended' | 'cancelled';
2
+ type DurationParts = {
3
+ totalMilliseconds: number;
4
+ totalSeconds: number;
5
+ milliseconds: number;
6
+ seconds: number;
7
+ minutes: number;
8
+ hours: number;
9
+ days: number;
10
+ };
11
+ type TimerSnapshot = {
12
+ status: TimerStatus;
13
+ now: number;
14
+ tick: number;
15
+ startedAt: number | null;
16
+ pausedAt: number | null;
17
+ endedAt: number | null;
18
+ cancelledAt: number | null;
19
+ cancelReason: string | null;
20
+ elapsedMilliseconds: number;
21
+ isIdle: boolean;
22
+ isRunning: boolean;
23
+ isPaused: boolean;
24
+ isEnded: boolean;
25
+ isCancelled: boolean;
26
+ };
27
+ type TimerControls = {
28
+ start(): void;
29
+ pause(): void;
30
+ resume(): void;
31
+ reset(options?: {
32
+ autoStart?: boolean;
33
+ }): void;
34
+ restart(): void;
35
+ cancel(reason?: string): void;
36
+ };
37
+ type TimerEndPredicate = (snapshot: TimerSnapshot) => boolean;
38
+ type TimerScheduleContext = {
39
+ scheduleId: string;
40
+ scheduledAt: number;
41
+ firedAt: number;
42
+ nextRunAt: number;
43
+ overdueCount: number;
44
+ effectiveEveryMs: number;
45
+ };
46
+ type TimerSchedule = {
47
+ id?: string;
48
+ everyMs: number;
49
+ leading?: boolean;
50
+ overlap?: 'skip' | 'allow';
51
+ callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
52
+ };
53
+ type TimerDebug = boolean | TimerDebugLogger | {
54
+ enabled?: boolean;
55
+ logger?: TimerDebugLogger;
56
+ includeTicks?: boolean;
57
+ label?: string;
58
+ };
59
+ type TimerDebugLogger = (event: TimerDebugEvent) => void;
60
+ type TimerDebugEvent = {
61
+ 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
+ scope: 'timer' | 'timer-group';
63
+ label?: string;
64
+ timerId?: string;
65
+ scheduleId?: string;
66
+ generation: number;
67
+ tick: number;
68
+ now: number;
69
+ elapsedMilliseconds: number;
70
+ status: TimerStatus;
71
+ reason?: string;
72
+ error?: unknown;
73
+ scheduledAt?: number;
74
+ firedAt?: number;
75
+ nextRunAt?: number;
76
+ overdueCount?: number;
77
+ effectiveEveryMs?: number;
78
+ };
79
+ type UseTimerOptions = {
80
+ autoStart?: boolean;
81
+ updateIntervalMs?: number;
82
+ endWhen?: TimerEndPredicate;
83
+ onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
84
+ };
85
+ type UseScheduledTimerOptions = UseTimerOptions & {
86
+ 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;
98
+ };
99
+ type TimerGroupItem = {
100
+ id: string;
101
+ autoStart?: boolean;
102
+ endWhen?: TimerEndPredicate;
103
+ onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
104
+ schedules?: TimerSchedule[];
105
+ };
106
+ type UseTimerGroupOptions = {
107
+ updateIntervalMs?: number;
108
+ items?: TimerGroupItem[];
109
+ debug?: TimerDebug;
110
+ };
111
+ type TimerGroupResult = {
112
+ now: number;
113
+ size: number;
114
+ ids: string[];
115
+ get(id: string): TimerSnapshot | undefined;
116
+ add(item: TimerGroupItem): void;
117
+ update(id: string, item: Partial<Omit<TimerGroupItem, 'id'>>): void;
118
+ remove(id: string): void;
119
+ clear(): void;
120
+ start(id: string): void;
121
+ pause(id: string): void;
122
+ resume(id: string): void;
123
+ reset(id: string, options?: {
124
+ autoStart?: boolean;
125
+ }): void;
126
+ restart(id: string): void;
127
+ cancel(id: string, reason?: string): void;
128
+ startAll(): void;
129
+ pauseAll(): void;
130
+ resumeAll(): void;
131
+ resetAll(options?: {
132
+ autoStart?: boolean;
133
+ }): void;
134
+ restartAll(): void;
135
+ cancelAll(reason?: string): void;
136
+ };
137
+
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 };
@@ -0,0 +1,138 @@
1
+ type TimerStatus = 'idle' | 'running' | 'paused' | 'ended' | 'cancelled';
2
+ type DurationParts = {
3
+ totalMilliseconds: number;
4
+ totalSeconds: number;
5
+ milliseconds: number;
6
+ seconds: number;
7
+ minutes: number;
8
+ hours: number;
9
+ days: number;
10
+ };
11
+ type TimerSnapshot = {
12
+ status: TimerStatus;
13
+ now: number;
14
+ tick: number;
15
+ startedAt: number | null;
16
+ pausedAt: number | null;
17
+ endedAt: number | null;
18
+ cancelledAt: number | null;
19
+ cancelReason: string | null;
20
+ elapsedMilliseconds: number;
21
+ isIdle: boolean;
22
+ isRunning: boolean;
23
+ isPaused: boolean;
24
+ isEnded: boolean;
25
+ isCancelled: boolean;
26
+ };
27
+ type TimerControls = {
28
+ start(): void;
29
+ pause(): void;
30
+ resume(): void;
31
+ reset(options?: {
32
+ autoStart?: boolean;
33
+ }): void;
34
+ restart(): void;
35
+ cancel(reason?: string): void;
36
+ };
37
+ type TimerEndPredicate = (snapshot: TimerSnapshot) => boolean;
38
+ type TimerScheduleContext = {
39
+ scheduleId: string;
40
+ scheduledAt: number;
41
+ firedAt: number;
42
+ nextRunAt: number;
43
+ overdueCount: number;
44
+ effectiveEveryMs: number;
45
+ };
46
+ type TimerSchedule = {
47
+ id?: string;
48
+ everyMs: number;
49
+ leading?: boolean;
50
+ overlap?: 'skip' | 'allow';
51
+ callback: (snapshot: TimerSnapshot, controls: TimerControls, context: TimerScheduleContext) => void | Promise<void>;
52
+ };
53
+ type TimerDebug = boolean | TimerDebugLogger | {
54
+ enabled?: boolean;
55
+ logger?: TimerDebugLogger;
56
+ includeTicks?: boolean;
57
+ label?: string;
58
+ };
59
+ type TimerDebugLogger = (event: TimerDebugEvent) => void;
60
+ type TimerDebugEvent = {
61
+ 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
+ scope: 'timer' | 'timer-group';
63
+ label?: string;
64
+ timerId?: string;
65
+ scheduleId?: string;
66
+ generation: number;
67
+ tick: number;
68
+ now: number;
69
+ elapsedMilliseconds: number;
70
+ status: TimerStatus;
71
+ reason?: string;
72
+ error?: unknown;
73
+ scheduledAt?: number;
74
+ firedAt?: number;
75
+ nextRunAt?: number;
76
+ overdueCount?: number;
77
+ effectiveEveryMs?: number;
78
+ };
79
+ type UseTimerOptions = {
80
+ autoStart?: boolean;
81
+ updateIntervalMs?: number;
82
+ endWhen?: TimerEndPredicate;
83
+ onEnd?: (snapshot: TimerSnapshot, controls: TimerControls) => void | Promise<void>;
84
+ };
85
+ type UseScheduledTimerOptions = UseTimerOptions & {
86
+ 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;
98
+ };
99
+ type TimerGroupItem = {
100
+ id: string;
101
+ autoStart?: boolean;
102
+ endWhen?: TimerEndPredicate;
103
+ onEnd?: (snapshot: TimerSnapshot, controls: TimerGroupItemControls) => void | Promise<void>;
104
+ schedules?: TimerSchedule[];
105
+ };
106
+ type UseTimerGroupOptions = {
107
+ updateIntervalMs?: number;
108
+ items?: TimerGroupItem[];
109
+ debug?: TimerDebug;
110
+ };
111
+ type TimerGroupResult = {
112
+ now: number;
113
+ size: number;
114
+ ids: string[];
115
+ get(id: string): TimerSnapshot | undefined;
116
+ add(item: TimerGroupItem): void;
117
+ update(id: string, item: Partial<Omit<TimerGroupItem, 'id'>>): void;
118
+ remove(id: string): void;
119
+ clear(): void;
120
+ start(id: string): void;
121
+ pause(id: string): void;
122
+ resume(id: string): void;
123
+ reset(id: string, options?: {
124
+ autoStart?: boolean;
125
+ }): void;
126
+ restart(id: string): void;
127
+ cancel(id: string, reason?: string): void;
128
+ startAll(): void;
129
+ pauseAll(): void;
130
+ resumeAll(): void;
131
+ resetAll(options?: {
132
+ autoStart?: boolean;
133
+ }): void;
134
+ restartAll(): void;
135
+ cancelAll(reason?: string): void;
136
+ };
137
+
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crup/react-timer-hook",
3
- "version": "0.0.1-alpha.10",
3
+ "version": "0.0.1-alpha.11",
4
4
  "description": "React timer lifecycle hooks for countdowns, stopwatches, schedules, and many independent timers.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -10,6 +10,26 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js",
12
12
  "require": "./dist/index.cjs"
13
+ },
14
+ "./group": {
15
+ "types": "./dist/group.d.ts",
16
+ "import": "./dist/group.js",
17
+ "require": "./dist/group.cjs"
18
+ },
19
+ "./duration": {
20
+ "types": "./dist/duration.d.ts",
21
+ "import": "./dist/duration.js",
22
+ "require": "./dist/duration.cjs"
23
+ },
24
+ "./schedules": {
25
+ "types": "./dist/schedules.d.ts",
26
+ "import": "./dist/schedules.js",
27
+ "require": "./dist/schedules.cjs"
28
+ },
29
+ "./diagnostics": {
30
+ "types": "./dist/diagnostics.d.ts",
31
+ "import": "./dist/diagnostics.js",
32
+ "require": "./dist/diagnostics.cjs"
13
33
  }
14
34
  },
15
35
  "files": [