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