Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@reatom/timer

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@reatom/timer - npm Package Compare versions

Comparing version 3.3.0 to 3.4.0

12

build/index.d.ts
import { Action, AtomMut } from '@reatom/core';
export interface TimerAtom extends AtomMut<number> {
/** (delay - remains) / delay */
progressAtom: AtomMut<number>;
/** interval in ms */

@@ -8,9 +10,9 @@ intervalAtom: AtomMut<number> & {

/** start timer by passed interval */
startTimer: Action<[delayInSeconds: number], Promise<void>>;
startTimer: Action<[delay: number], Promise<void>>;
/** allow to pause timer */
pauseAtom: AtomMut<boolean>;
/** stop timer manually */
stopTimer: Action<[], void>;
/** track end of timer, do not call manually */
/** track end of timer. Do not call manually! */
endTimer: Action<[], void>;
/** track every interval tick, do not call manually */
tick: Action<[remains: number], number>;
}

@@ -20,2 +22,4 @@ export declare const reatomTimer: (options?: string | {

interval?: number;
delayMultiplier?: number;
progressPrecision?: number;
}) => TimerAtom;

@@ -1,2 +0,2 @@

var t=require("@reatom/core");function n(t,r,i){if(!t.s){if(i instanceof e){if(!i.s)return void(i.o=n.bind(null,t,r));1&r&&(r=i.s),i=i.v}if(i&&i.then)return void i.then(n.bind(null,t,r),n.bind(null,t,2));t.s=r,t.v=i;const o=t.o;o&&o(t)}}const e=/*#__PURE__*/function(){function t(){}return t.prototype.then=function(e,r){const i=new t,o=this.s;if(o){const t=1&o?e:r;if(t){try{n(i,1,t(this.v))}catch(t){n(i,2,t)}return i}return this}return this.o=function(t){try{const o=t.v;1&t.s?n(i,1,e?e(o):o):r?n(i,1,r(o)):n(i,2,o)}catch(t){n(i,2,t)}},i},t}();function r(t){return t instanceof e&&1&t.s}exports.reatomTimer=(i={})=>{const{name:o=t.__count("timerAtom"),interval:c=1e3}="string"==typeof i?{name:i}:i,s=t.atom(0,`${o}Atom`),u=t.atom(c,`${o}.intervalAtom`).pipe((a={setSeconds:(t,n)=>1e3*n},n=>Object.keys(a).reduce((n,e)=>(n[e]=t.action(function(t){return n(t,a[e](t.get(n),...[].slice.call(arguments,1)))},`${n.__reatom.name}._${e}`),n),n)));var a;const h=t.atom(0,`${o}._versionAtom`),f=t.action((t,n)=>n,`${o}.tick`),v=t.action((t,i)=>{const o=h(t,t=>t+1),c=1e3*i,a=c+Date.now();let v=c;return s(t,v),t.schedule(function(){try{let c;function i(n){if(c)return n;d(t)}const m=function(t,i,o){for(var c;;){var s=t();if(r(s)&&(s=s.v),!s)return u;if(s.then){c=0;break}var u=o();if(u&&u.then){if(!r(u)){c=1;break}u=u.s}}var a=new e,h=n.bind(null,a,2);return(0===c?s.then(v):1===c?u.then(f):(void 0).then(function(){(s=t())?s.then?s.then(v).then(void 0,h):v(s):n(a,1,u)})).then(void 0,h),a;function f(e){u=e;do{if(!(s=t())||r(s)&&!s.v)return void n(a,1,u);if(s.then)return void s.then(v).then(void 0,h);r(u=o())&&(u=u.v)}while(!u||!u.then);u.then(f).then(void 0,h)}function v(t){t?(u=o())&&u.then?u.then(f).then(void 0,h):f(u):n(a,1,u)}}(function(){return!c&&v>0},0,function(){return Promise.resolve(((t=0)=>new Promise(n=>setTimeout(n,t)))(Math.min(v,t.get(u)))).then(function(){o===t.get(h)?(v=s(t,a-Date.now()),f(t,v)):c=1})});return Promise.resolve(m&&m.then?m.then(i):i(m))}catch(l){return Promise.reject(l)}})},`${o}.startTimer`),m=t.action(t=>{h(t,t=>t+1),d(t)},`${o}.stopTimer`),d=t.action(t=>{s(t,0)},`${o}.endTimer`);return Object.assign(s,{endTimer:d,intervalAtom:u,startTimer:v,stopTimer:m,tick:f})};
var t=require("@reatom/core"),e=require("@reatom/primitives"),n=require("@reatom/hooks");const o=()=>{};function r(t,e,n){if(!t.s){if(n instanceof i){if(!n.s)return void(n.o=r.bind(null,t,e));1&e&&(e=n.s),n=n.v}if(n&&n.then)return void n.then(r.bind(null,t,e),r.bind(null,t,2));t.s=e,t.v=n;const o=t.o;o&&o(t)}}const i=/*#__PURE__*/function(){function t(){}return t.prototype.then=function(e,n){const o=new t,i=this.s;if(i){const t=1&i?e:n;if(t){try{r(o,1,t(this.v))}catch(t){r(o,2,t)}return o}return this}return this.o=function(t){try{const i=t.v;1&t.s?r(o,1,e?e(i):i):n?r(o,1,n(i)):r(o,2,i)}catch(t){r(o,2,t)}},o},t}();function s(t){return t instanceof i&&1&t.s}exports.reatomTimer=(u={})=>{const{name:c=t.__count("timerAtom"),interval:a=1e3,delayMultiplier:h=1e3,progressPrecision:m=2}="string"==typeof u?{name:u}:u,f=Math.pow(10,m),v=t.atom(0,`${c}Atom`),l=t.atom(0,`${c}.progressAtom`),d=t.atom(!1,`${c}.pauseAtom`),p=t.atom(a,`${c}.intervalAtom`).pipe(e.withReducers({setSeconds:(t,e)=>1e3*e})),w=t.atom(0,`${c}._versionAtom`),g=t.action((t,e)=>{e*=h;const u=w(t,t=>t+1),c=Date.now(),a=e+c;let m=e,g=Promise.resolve(),A=o;v(t,m),l(t,0),d(t,!1);const P=n.onUpdate(d,(t,e)=>t.schedule(()=>{if(e){const t=a-Date.now();g=new Promise(e=>{A=()=>{m=t,e()}})}else A()}));return t.schedule(function(){try{let o;function n(e){if(o)return e;b(t)}const c=function(t,e,n){for(var o;;){var u=t();if(s(u)&&(u=u.v),!u)return c;if(u.then){o=0;break}var c=n();if(c&&c.then){if(!s(c)){o=1;break}c=c.s}}var a=new i,h=r.bind(null,a,2);return(0===o?u.then(f):1===o?c.then(m):(void 0).then(function(){(u=t())?u.then?u.then(f).then(void 0,h):f(u):r(a,1,c)})).then(void 0,h),a;function m(e){c=e;do{if(!(u=t())||s(u)&&!u.v)return void r(a,1,c);if(u.then)return void u.then(f).then(void 0,h);s(c=n())&&(c=c.v)}while(!c||!c.then);c.then(m).then(void 0,h)}function f(t){t?(c=n())&&c.then?c.then(m).then(void 0,h):m(c):r(a,1,c)}}(function(){return!o&&m>0},0,function(){return Promise.resolve(((t=0)=>new Promise(e=>setTimeout(e,t)))(Math.min(m,t.get(p)))).then(function(){return Promise.resolve(g).then(function(){u===t.get(w)?t.get.bind(t)(()=>{const n=t.get(p);m=v(t,a-Date.now());const o=(e-m)/e;l(t,Math.round((o-o%(n/e))*f)/f)}):o=1})})});return Promise.resolve(c&&c.then?c.then(n):n(c))}catch(h){return Promise.reject(h)}}).finally(P)},`${c}.startTimer`),A=t.action(t=>{w(t,t=>t+1),b(t)},`${c}.stopTimer`),b=t.action(t=>{v(t,0)},`${c}.endTimer`);return Object.assign(v,{progressAtom:l,endTimer:b,intervalAtom:p,startTimer:g,stopTimer:A,pauseAtom:d})};
//# sourceMappingURL=index.js.map

@@ -1,2 +0,2 @@

import{action as t,__count as n,atom as e}from"@reatom/core";function r(t,n,e){if(!t.s){if(e instanceof i){if(!e.s)return void(e.o=r.bind(null,t,n));1&n&&(n=e.s),e=e.v}if(e&&e.then)return void e.then(r.bind(null,t,n),r.bind(null,t,2));t.s=n,t.v=e;const o=t.o;o&&o(t)}}const i=/*#__PURE__*/function(){function t(){}return t.prototype.then=function(n,e){const i=new t,o=this.s;if(o){const t=1&o?n:e;if(t){try{r(i,1,t(this.v))}catch(t){r(i,2,t)}return i}return this}return this.o=function(t){try{const o=t.v;1&t.s?r(i,1,n?n(o):o):e?r(i,1,e(o)):r(i,2,o)}catch(t){r(i,2,t)}},i},t}();function o(t){return t instanceof i&&1&t.s}const c=(c={})=>{const{name:s=n("timerAtom"),interval:u=1e3}="string"==typeof c?{name:c}:c,f=e(0,`${s}Atom`),h=e(u,`${s}.intervalAtom`).pipe((v={setSeconds:(t,n)=>1e3*n},n=>Object.keys(v).reduce((n,e)=>(n[e]=t(function(t){return n(t,v[e](t.get(n),...[].slice.call(arguments,1)))},`${n.__reatom.name}._${e}`),n),n)));var v;const a=e(0,`${s}._versionAtom`),m=t((t,n)=>n,`${s}.tick`),d=t((t,n)=>{const e=a(t,t=>t+1),c=1e3*n,s=c+Date.now();let u=c;return f(t,u),t.schedule(function(){try{let c;function n(n){if(c)return n;p(t)}const v=function(t,n,e){for(var c;;){var s=t();if(o(s)&&(s=s.v),!s)return u;if(s.then){c=0;break}var u=e();if(u&&u.then){if(!o(u)){c=1;break}u=u.s}}var f=new i,h=r.bind(null,f,2);return(0===c?s.then(a):1===c?u.then(v):(void 0).then(function(){(s=t())?s.then?s.then(a).then(void 0,h):a(s):r(f,1,u)})).then(void 0,h),f;function v(n){u=n;do{if(!(s=t())||o(s)&&!s.v)return void r(f,1,u);if(s.then)return void s.then(a).then(void 0,h);o(u=e())&&(u=u.v)}while(!u||!u.then);u.then(v).then(void 0,h)}function a(t){t?(u=e())&&u.then?u.then(v).then(void 0,h):v(u):r(f,1,u)}}(function(){return!c&&u>0},0,function(){return Promise.resolve(((t=0)=>new Promise(n=>setTimeout(n,t)))(Math.min(u,t.get(h)))).then(function(){e===t.get(a)?(u=f(t,s-Date.now()),m(t,u)):c=1})});return Promise.resolve(v&&v.then?v.then(n):n(v))}catch(d){return Promise.reject(d)}})},`${s}.startTimer`),l=t(t=>{a(t,t=>t+1),p(t)},`${s}.stopTimer`),p=t(t=>{f(t,0)},`${s}.endTimer`);return Object.assign(f,{endTimer:p,intervalAtom:h,startTimer:d,stopTimer:l,tick:m})};export{c as reatomTimer};
import{__count as t,atom as e,action as n}from"@reatom/core";import{withReducers as o}from"@reatom/primitives";import{onUpdate as r}from"@reatom/hooks";const i=()=>{};function s(t,e,n){if(!t.s){if(n instanceof u){if(!n.s)return void(n.o=s.bind(null,t,e));1&e&&(e=n.s),n=n.v}if(n&&n.then)return void n.then(s.bind(null,t,e),s.bind(null,t,2));t.s=e,t.v=n;const o=t.o;o&&o(t)}}const u=/*#__PURE__*/function(){function t(){}return t.prototype.then=function(e,n){const o=new t,r=this.s;if(r){const t=1&r?e:n;if(t){try{s(o,1,t(this.v))}catch(t){s(o,2,t)}return o}return this}return this.o=function(t){try{const r=t.v;1&t.s?s(o,1,e?e(r):r):n?s(o,1,n(r)):s(o,2,r)}catch(t){s(o,2,t)}},o},t}();function c(t){return t instanceof u&&1&t.s}const h=(h={})=>{const{name:f=t("timerAtom"),interval:m=1e3,delayMultiplier:a=1e3,progressPrecision:v=2}="string"==typeof h?{name:h}:h,l=Math.pow(10,v),d=e(0,`${f}Atom`),p=e(0,`${f}.progressAtom`),g=e(!1,`${f}.pauseAtom`),w=e(m,`${f}.intervalAtom`).pipe(o({setSeconds:(t,e)=>1e3*e})),A=e(0,`${f}._versionAtom`),b=n((t,e)=>{e*=a;const n=A(t,t=>t+1),o=Date.now(),h=e+o;let f=e,m=Promise.resolve(),v=i;d(t,f),p(t,0),g(t,!1);const b=r(g,(t,e)=>t.schedule(()=>{if(e){const t=h-Date.now();m=new Promise(e=>{v=()=>{f=t,e()}})}else v()}));return t.schedule(function(){try{let r;function o(e){if(r)return e;$(t)}const i=function(t,e,n){for(var o;;){var r=t();if(c(r)&&(r=r.v),!r)return i;if(r.then){o=0;break}var i=n();if(i&&i.then){if(!c(i)){o=1;break}i=i.s}}var h=new u,f=s.bind(null,h,2);return(0===o?r.then(a):1===o?i.then(m):(void 0).then(function(){(r=t())?r.then?r.then(a).then(void 0,f):a(r):s(h,1,i)})).then(void 0,f),h;function m(e){i=e;do{if(!(r=t())||c(r)&&!r.v)return void s(h,1,i);if(r.then)return void r.then(a).then(void 0,f);c(i=n())&&(i=i.v)}while(!i||!i.then);i.then(m).then(void 0,f)}function a(t){t?(i=n())&&i.then?i.then(m).then(void 0,f):m(i):s(h,1,i)}}(function(){return!r&&f>0},0,function(){return Promise.resolve(((t=0)=>new Promise(e=>setTimeout(e,t)))(Math.min(f,t.get(w)))).then(function(){return Promise.resolve(m).then(function(){n===t.get(A)?t.get.bind(t)(()=>{const n=t.get(w);f=d(t,h-Date.now());const o=(e-f)/e;p(t,Math.round((o-o%(n/e))*l)/l)}):r=1})})});return Promise.resolve(i&&i.then?i.then(o):o(i))}catch(a){return Promise.reject(a)}}).finally(b)},`${f}.startTimer`),P=n(t=>{A(t,t=>t+1),$(t)},`${f}.stopTimer`),$=n(t=>{d(t,0)},`${f}.endTimer`);return Object.assign(d,{progressAtom:p,endTimer:$,intervalAtom:w,startTimer:b,stopTimer:P,pauseAtom:g})};export{h as reatomTimer};
//# sourceMappingURL=index.module.js.map

@@ -1,2 +0,2 @@

!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@reatom/core")):"function"==typeof define&&define.amd?define(["exports","@reatom/core"],e):e((t||self).timer={},t.core)}(this,function(t,e){function n(t,e,i){if(!t.s){if(i instanceof o){if(!i.s)return void(i.o=n.bind(null,t,e));1&e&&(e=i.s),i=i.v}if(i&&i.then)return void i.then(n.bind(null,t,e),n.bind(null,t,2));t.s=e,t.v=i;const r=t.o;r&&r(t)}}const o=/*#__PURE__*/function(){function t(){}return t.prototype.then=function(e,o){const i=new t,r=this.s;if(r){const t=1&r?e:o;if(t){try{n(i,1,t(this.v))}catch(t){n(i,2,t)}return i}return this}return this.o=function(t){try{const r=t.v;1&t.s?n(i,1,e?e(r):r):o?n(i,1,o(r)):n(i,2,r)}catch(t){n(i,2,t)}},i},t}();function i(t){return t instanceof o&&1&t.s}t.reatomTimer=(t={})=>{const{name:r=e.__count("timerAtom"),interval:c=1e3}="string"==typeof t?{name:t}:t,s=e.atom(0,`${r}Atom`),u=e.atom(c,`${r}.intervalAtom`).pipe((f={setSeconds:(t,e)=>1e3*e},t=>Object.keys(f).reduce((t,n)=>(t[n]=e.action(function(e){return t(e,f[n](e.get(t),...[].slice.call(arguments,1)))},`${t.__reatom.name}._${n}`),t),t)));var f;const a=e.atom(0,`${r}._versionAtom`),h=e.action((t,e)=>e,`${r}.tick`),m=e.action((t,e)=>{const r=a(t,t=>t+1),c=1e3*e,f=c+Date.now();let m=c;return s(t,m),t.schedule(function(){try{let c;function e(e){if(c)return e;v(t)}const d=function(t,e,r){for(var c;;){var s=t();if(i(s)&&(s=s.v),!s)return u;if(s.then){c=0;break}var u=r();if(u&&u.then){if(!i(u)){c=1;break}u=u.s}}var f=new o,a=n.bind(null,f,2);return(0===c?s.then(m):1===c?u.then(h):(void 0).then(function(){(s=t())?s.then?s.then(m).then(void 0,a):m(s):n(f,1,u)})).then(void 0,a),f;function h(e){u=e;do{if(!(s=t())||i(s)&&!s.v)return void n(f,1,u);if(s.then)return void s.then(m).then(void 0,a);i(u=r())&&(u=u.v)}while(!u||!u.then);u.then(h).then(void 0,a)}function m(t){t?(u=r())&&u.then?u.then(h).then(void 0,a):h(u):n(f,1,u)}}(function(){return!c&&m>0},0,function(){return Promise.resolve(((t=0)=>new Promise(e=>setTimeout(e,t)))(Math.min(m,t.get(u)))).then(function(){r===t.get(a)?(m=s(t,f-Date.now()),h(t,m)):c=1})});return Promise.resolve(d&&d.then?d.then(e):e(d))}catch(l){return Promise.reject(l)}})},`${r}.startTimer`),d=e.action(t=>{a(t,t=>t+1),v(t)},`${r}.stopTimer`),v=e.action(t=>{s(t,0)},`${r}.endTimer`);return Object.assign(s,{endTimer:v,intervalAtom:u,startTimer:m,stopTimer:d,tick:h})}});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@reatom/core"),require("@reatom/primitives"),require("@reatom/hooks")):"function"==typeof define&&define.amd?define(["exports","@reatom/core","@reatom/primitives","@reatom/hooks"],t):t((e||self).timer={},e.core,e.primitives,e.hooks)}(this,function(e,t,n,o){const i=()=>{};function r(e,t,n){if(!e.s){if(n instanceof s){if(!n.s)return void(n.o=r.bind(null,e,t));1&t&&(t=n.s),n=n.v}if(n&&n.then)return void n.then(r.bind(null,e,t),r.bind(null,e,2));e.s=t,e.v=n;const o=e.o;o&&o(e)}}const s=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(t,n){const o=new e,i=this.s;if(i){const e=1&i?t:n;if(e){try{r(o,1,e(this.v))}catch(e){r(o,2,e)}return o}return this}return this.o=function(e){try{const i=e.v;1&e.s?r(o,1,t?t(i):i):n?r(o,1,n(i)):r(o,2,i)}catch(e){r(o,2,e)}},o},e}();function u(e){return e instanceof s&&1&e.s}e.reatomTimer=(e={})=>{const{name:c=t.__count("timerAtom"),interval:a=1e3,delayMultiplier:f=1e3,progressPrecision:m=2}="string"==typeof e?{name:e}:e,h=Math.pow(10,m),d=t.atom(0,`${c}Atom`),l=t.atom(0,`${c}.progressAtom`),v=t.atom(!1,`${c}.pauseAtom`),p=t.atom(a,`${c}.intervalAtom`).pipe(n.withReducers({setSeconds:(e,t)=>1e3*t})),b=t.atom(0,`${c}._versionAtom`),g=t.action((e,t)=>{t*=f;const n=b(e,e=>e+1),c=Date.now(),a=t+c;let m=t,g=Promise.resolve(),y=i;d(e,m),l(e,0),v(e,!1);const T=o.onUpdate(v,(e,t)=>e.schedule(()=>{if(t){const e=a-Date.now();g=new Promise(t=>{y=()=>{m=e,t()}})}else y()}));return e.schedule(function(){try{let i;function o(t){if(i)return t;w(e)}const c=function(e,t,n){for(var o;;){var i=e();if(u(i)&&(i=i.v),!i)return c;if(i.then){o=0;break}var c=n();if(c&&c.then){if(!u(c)){o=1;break}c=c.s}}var a=new s,f=r.bind(null,a,2);return(0===o?i.then(h):1===o?c.then(m):(void 0).then(function(){(i=e())?i.then?i.then(h).then(void 0,f):h(i):r(a,1,c)})).then(void 0,f),a;function m(t){c=t;do{if(!(i=e())||u(i)&&!i.v)return void r(a,1,c);if(i.then)return void i.then(h).then(void 0,f);u(c=n())&&(c=c.v)}while(!c||!c.then);c.then(m).then(void 0,f)}function h(e){e?(c=n())&&c.then?c.then(m).then(void 0,f):m(c):r(a,1,c)}}(function(){return!i&&m>0},0,function(){return Promise.resolve(((e=0)=>new Promise(t=>setTimeout(t,e)))(Math.min(m,e.get(p)))).then(function(){return Promise.resolve(g).then(function(){n===e.get(b)?e.get.bind(e)(()=>{const n=e.get(p);m=d(e,a-Date.now());const o=(t-m)/t;l(e,Math.round((o-o%(n/t))*h)/h)}):i=1})})});return Promise.resolve(c&&c.then?c.then(o):o(c))}catch(f){return Promise.reject(f)}}).finally(T)},`${c}.startTimer`),y=t.action(e=>{b(e,e=>e+1),w(e)},`${c}.stopTimer`),w=t.action(e=>{d(e,0)},`${c}.endTimer`);return Object.assign(d,{progressAtom:l,endTimer:w,intervalAtom:p,startTimer:g,stopTimer:y,pauseAtom:v})}});
//# sourceMappingURL=index.umd.js.map
{
"name": "@reatom/timer",
"version": "3.3.0",
"version": "3.4.0",
"private": false,

@@ -26,3 +26,5 @@ "sideEffects": false,

"dependencies": {
"@reatom/core": ">=3.1.23"
"@reatom/core": "^3.1.23",
"@reatom/hooks": "^3.1.2",
"@reatom/primitives": "^3.1.3"
},

@@ -29,0 +31,0 @@ "author": "artalar",

@@ -6,7 +6,17 @@ Simple timer model to manage some countdown.

const timer = reatomTimer({ interval: 1000 })
// all options are not required
const pomodoroAtom = reatomTimer({
name: 'pomodoroAtom',
interval: 1000, // tick each second
delayMultiplier: 1000, // allow to pass seconds to startTimer
progressPrecision: 2, // progress will be rounded to 2 digits after dot
})
```
Example: https://stackblitz.com/edit/reatom-timer-pomodoro?file=src%2FApp.tsx
```ts
export interface TimerAtom extends AtomMut<number> {
/** (delay - remains) / delay */
progressAtom: AtomMut<number>
/** interval in ms */

@@ -17,10 +27,10 @@ intervalAtom: AtomMut<number> & {

/** start timer by passed interval */
startTimer: Action<[delayInSeconds: number], Promise<void>>
startTimer: Action<[delay: number], Promise<void>>
/** allow to pause timer */
pauseAtom: AtomMut<boolean>
/** stop timer manually */
stopTimer: Action<[], void>
/** track end of timer, do not call manually */
/** track end of timer. Do not call manually! */
endTimer: Action<[], void>
/** track every interval tick, do not call manually */
tick: Action<[remains: number], number>
}
```
import { test } from 'uvu'
import * as assert from 'uvu/assert'
import { createCtx } from '@reatom/core'
import { getDuration } from '@reatom/testing'
import { createTestCtx, getDuration } from '@reatom/testing'
import { sleep } from '@reatom/utils'

@@ -10,10 +9,10 @@

test(`base API`, async () => {
const timerModel = reatomTimer(`test`)
const ctx = createCtx()
const timerAtom = reatomTimer(`test`)
const ctx = createTestCtx()
timerModel.intervalAtom.setSeconds(ctx, 0.001)
timerAtom.intervalAtom.setSeconds(ctx, 0.001)
var target = 50
var duration = await getDuration(() =>
timerModel.startTimer(ctx, target / 1000),
timerAtom.startTimer(ctx, target / 1000),
)

@@ -25,4 +24,4 @@

var [duration] = await Promise.all([
getDuration(() => timerModel.startTimer(ctx, target / 1000)),
sleep(target / 2).then(() => timerModel.stopTimer(ctx)),
getDuration(() => timerAtom.startTimer(ctx, target / 1000)),
sleep(target / 2).then(() => timerAtom.stopTimer(ctx)),
])

@@ -33,2 +32,51 @@ assert.ok(duration >= target / 2 && duration < target)

test('progressAtom', async () => {
const timerAtom = reatomTimer({ delayMultiplier: 1 })
const ctx = createTestCtx()
timerAtom.intervalAtom(ctx, 10)
const track = ctx.subscribeTrack(timerAtom.progressAtom)
track.calls.length = 0
await timerAtom.startTimer(ctx, 60)
assert.equal(
track.calls.map(({ i }) => i[0]),
[0.17, 0.33, 0.5, 0.67, 0.83, 1],
)
;`👍` //?
})
test('pauseAtom', async () => {
const timerAtom = reatomTimer({ delayMultiplier: 1 })
const ctx = createTestCtx()
timerAtom.intervalAtom(ctx, 10)
const track = ctx.subscribeTrack(timerAtom.progressAtom)
track.calls.length = 0
timerAtom.startTimer(ctx, 60)
await sleep(25)
assert.equal(
track.calls.map(({ i }) => i[0]),
[0.17, 0.33],
)
timerAtom.pauseAtom(ctx, true)
await sleep(20)
assert.equal(
track.calls.map(({ i }) => i[0]),
[0.17, 0.33],
)
timerAtom.pauseAtom(ctx, false)
await sleep(25)
assert.equal(
track.calls.map(({ i }) => i[0]),
[0.17, 0.33, 0.67, 0.83, 1],
)
;`👍` //?
})
test.run()
import { Action, action, atom, AtomMut, __count } from '@reatom/core'
import { withReducers } from '@reatom/primitives'
import { sleep } from '@reatom/utils'
import { noop, sleep } from '@reatom/utils'
import { getRootCause, onUpdate } from '@reatom/hooks'
export interface TimerAtom extends AtomMut<number> {
/** (delay - remains) / delay */
progressAtom: AtomMut<number>
/** interval in ms */

@@ -11,18 +14,37 @@ intervalAtom: AtomMut<number> & {

/** start timer by passed interval */
startTimer: Action<[delayInSeconds: number], Promise<void>>
startTimer: Action<[delay: number], Promise<void>>
/** allow to pause timer */
pauseAtom: AtomMut<boolean>
/** stop timer manually */
stopTimer: Action<[], void>
/** track end of timer, do not call manually */
/** track end of timer. Do not call manually! */
endTimer: Action<[], void>
/** track every interval tick, do not call manually */
tick: Action<[remains: number], number>
}
export const reatomTimer = (
options: string | { name?: string; interval?: number } = {},
options:
| string
| {
name?: string
interval?: number
delayMultiplier?: number
progressPrecision?: number
} = {},
): TimerAtom => {
const { name = __count('timerAtom'), interval = 1000 } =
typeof options === 'string' ? { name: options } : options
const {
name = __count('timerAtom'),
interval = 1000,
delayMultiplier = 1000,
progressPrecision = 2,
} = typeof options === 'string' ? { name: options } : options
const progressMultiplier = Math.pow(10, progressPrecision)
const timerAtom = atom(0, `${name}Atom`)
const progressAtom: TimerAtom['progressAtom'] = atom(
0,
`${name}.progressAtom`,
)
const pauseAtom: TimerAtom['pauseAtom'] = atom(false, `${name}.pauseAtom`)
const intervalAtom: TimerAtom['intervalAtom'] = atom(

@@ -39,25 +61,56 @@ interval,

const tick: TimerAtom['tick'] = action(
(ctx, remains) => remains,
`${name}.tick`,
)
const startTimer: TimerAtom['startTimer'] = action((ctx, delay: number) => {
delay *= delayMultiplier
const version = _versionAtom(ctx, (s) => s + 1)
const start = Date.now()
const target = delay + start
let remains = delay
let pause = Promise.resolve()
let resolvePause = noop
const startTimer: TimerAtom['startTimer'] = action(
(ctx, delayInSeconds: number) => {
const version = _versionAtom(ctx, (s) => s + 1)
const delay = delayInSeconds * 1000
const start = Date.now()
const target = delay + start
let remains = delay
timerAtom(ctx, remains)
timerAtom(ctx, remains)
progressAtom(ctx, 0)
return ctx.schedule(async () => {
pauseAtom(ctx, false)
const cleanupPause = onUpdate(pauseAtom, (pauseCtx, value) =>
// TODO: circles?
// getRootCause(ctx.cause) === getRootCause(pauseCtx.cause) &&
pauseCtx.schedule(() => {
if (value) {
const nextRemains = target - Date.now()
pause = new Promise((resolve) => {
resolvePause = () => {
remains = nextRemains
resolve()
}
})
} else {
resolvePause()
}
}),
)
return ctx
.schedule(async () => {
while (remains > 0) {
await sleep(Math.min(remains, ctx.get(intervalAtom)))
await pause
if (version !== ctx.get(_versionAtom)) return
remains = timerAtom(ctx, target - Date.now())
tick(ctx, remains)
const batch = ctx.get.bind(ctx)
batch(() => {
const interval = ctx.get(intervalAtom)
remains = timerAtom(ctx, target - Date.now())
const progress = (delay - remains) / delay
const roundPart = progress % (interval / delay)
progressAtom(
ctx,
Math.round((progress - roundPart) * progressMultiplier) /
progressMultiplier,
)
})
}

@@ -67,5 +120,4 @@

})
},
`${name}.startTimer`,
)
.finally(cleanupPause)
}, `${name}.startTimer`)

@@ -82,2 +134,3 @@ const stopTimer: TimerAtom['stopTimer'] = action((ctx) => {

return Object.assign(timerAtom, {
progressAtom,
endTimer,

@@ -87,4 +140,4 @@ intervalAtom,

stopTimer,
tick,
pauseAtom,
})
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc