@oscarpalmer/atoms 0.46.0 → 0.47.1

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/dist/js/index.js CHANGED
@@ -875,6 +875,12 @@ var timer = function(type, callback, partial) {
875
875
  active: false
876
876
  };
877
877
  const instance = Object.create({
878
+ continue() {
879
+ return work2("continue", this, state, options, isRepeated2);
880
+ },
881
+ pause() {
882
+ return work2("pause", this, state, options, isRepeated2);
883
+ },
878
884
  restart() {
879
885
  return work2("restart", this, state, options, isRepeated2);
880
886
  },
@@ -925,6 +931,12 @@ function when(condition, options) {
925
931
  rejecter = reject;
926
932
  });
927
933
  const instance = Object.create({
934
+ continue() {
935
+ repeated.continue();
936
+ },
937
+ pause() {
938
+ repeated.pause();
939
+ },
928
940
  stop() {
929
941
  if (repeated.active) {
930
942
  repeated.stop();
@@ -951,29 +963,37 @@ function when(condition, options) {
951
963
  return instance;
952
964
  }
953
965
  var work2 = function(type, timer2, state, options, isRepeated2) {
954
- if (type === "start" && state.active || type === "stop" && !state.active) {
966
+ if (["continue", "start"].includes(type) && state.active || ["pause", "stop"].includes(type) && !state.active) {
955
967
  return timer2;
956
968
  }
957
969
  const { count, interval, timeout } = options;
958
- if (typeof state.frame === "number") {
970
+ if (["pause", "stop"].includes(type)) {
971
+ activeTimers.delete(timer2);
959
972
  cancelAnimationFrame(state.frame);
960
973
  options.afterCallback?.(false);
961
- }
962
- if (type === "stop") {
963
- activeTimers.delete(timer2);
964
974
  state.active = false;
965
975
  state.frame = undefined;
976
+ if (type === "stop") {
977
+ state.elapsed = undefined;
978
+ state.index = undefined;
979
+ }
966
980
  return timer2;
967
981
  }
968
982
  state.active = true;
969
983
  const canTimeout = timeout > 0 && timeout < Number.POSITIVE_INFINITY;
970
- const total = count === Number.POSITIVE_INFINITY ? timeout : count * (interval > 0 ? interval : 17);
984
+ const elapsed = type === "continue" ? +(state.elapsed ?? 0) : 0;
985
+ let index = type === "continue" ? +(state.index ?? 0) : 0;
986
+ state.elapsed = elapsed;
987
+ state.index = index;
988
+ const total = (count === Number.POSITIVE_INFINITY ? Number.POSITIVE_INFINITY : (count - index) * (interval > 0 ? interval : 62.5)) - elapsed;
971
989
  let current;
972
990
  let start;
973
- let index = 0;
974
991
  function finish(finished, error) {
992
+ activeTimers.delete(timer2);
975
993
  state.active = false;
994
+ state.elapsed = undefined;
976
995
  state.frame = undefined;
996
+ state.index = undefined;
977
997
  if (error) {
978
998
  options.errorCallback?.();
979
999
  }
@@ -985,15 +1005,17 @@ var work2 = function(type, timer2, state, options, isRepeated2) {
985
1005
  }
986
1006
  current ??= timestamp;
987
1007
  start ??= timestamp;
988
- const elapsed = timestamp - current;
989
- const finished = elapsed >= total;
990
- if (finished || elapsed - 2 < interval && interval < elapsed + 2) {
1008
+ const time2 = timestamp - current;
1009
+ state.elapsed = elapsed + (current - start);
1010
+ const finished = time2 - elapsed >= total;
1011
+ if (finished || time2 - 2 < interval && interval < time2 + 2) {
991
1012
  if (state.active) {
992
1013
  state.callback(isRepeated2 ? index : undefined);
993
1014
  }
994
1015
  index += 1;
1016
+ state.index = index;
995
1017
  switch (true) {
996
- case (canTimeout && !finished && timestamp - start >= timeout):
1018
+ case (canTimeout && !finished && timestamp - start >= timeout - elapsed):
997
1019
  finish(false, true);
998
1020
  return;
999
1021
  case (!finished && index < count):
@@ -1016,11 +1038,11 @@ document.addEventListener("visibilitychange", () => {
1016
1038
  if (document.hidden) {
1017
1039
  for (const timer2 of activeTimers) {
1018
1040
  hiddenTimers.add(timer2);
1019
- timer2.stop();
1041
+ timer2.pause();
1020
1042
  }
1021
1043
  } else {
1022
1044
  for (const timer2 of hiddenTimers) {
1023
- timer2.start();
1045
+ timer2.continue();
1024
1046
  }
1025
1047
  hiddenTimers.clear();
1026
1048
  }
package/dist/js/timer.js CHANGED
@@ -34,6 +34,12 @@ var timer = function(type, callback, partial) {
34
34
  active: false
35
35
  };
36
36
  const instance = Object.create({
37
+ continue() {
38
+ return work("continue", this, state, options, isRepeated2);
39
+ },
40
+ pause() {
41
+ return work("pause", this, state, options, isRepeated2);
42
+ },
37
43
  restart() {
38
44
  return work("restart", this, state, options, isRepeated2);
39
45
  },
@@ -84,6 +90,12 @@ function when(condition, options) {
84
90
  rejecter = reject;
85
91
  });
86
92
  const instance = Object.create({
93
+ continue() {
94
+ repeated.continue();
95
+ },
96
+ pause() {
97
+ repeated.pause();
98
+ },
87
99
  stop() {
88
100
  if (repeated.active) {
89
101
  repeated.stop();
@@ -110,29 +122,37 @@ function when(condition, options) {
110
122
  return instance;
111
123
  }
112
124
  var work = function(type, timer2, state, options, isRepeated2) {
113
- if (type === "start" && state.active || type === "stop" && !state.active) {
125
+ if (["continue", "start"].includes(type) && state.active || ["pause", "stop"].includes(type) && !state.active) {
114
126
  return timer2;
115
127
  }
116
128
  const { count, interval, timeout } = options;
117
- if (typeof state.frame === "number") {
129
+ if (["pause", "stop"].includes(type)) {
130
+ activeTimers.delete(timer2);
118
131
  cancelAnimationFrame(state.frame);
119
132
  options.afterCallback?.(false);
120
- }
121
- if (type === "stop") {
122
- activeTimers.delete(timer2);
123
133
  state.active = false;
124
134
  state.frame = undefined;
135
+ if (type === "stop") {
136
+ state.elapsed = undefined;
137
+ state.index = undefined;
138
+ }
125
139
  return timer2;
126
140
  }
127
141
  state.active = true;
128
142
  const canTimeout = timeout > 0 && timeout < Number.POSITIVE_INFINITY;
129
- const total = count === Number.POSITIVE_INFINITY ? timeout : count * (interval > 0 ? interval : 17);
143
+ const elapsed = type === "continue" ? +(state.elapsed ?? 0) : 0;
144
+ let index = type === "continue" ? +(state.index ?? 0) : 0;
145
+ state.elapsed = elapsed;
146
+ state.index = index;
147
+ const total = (count === Number.POSITIVE_INFINITY ? Number.POSITIVE_INFINITY : (count - index) * (interval > 0 ? interval : 62.5)) - elapsed;
130
148
  let current;
131
149
  let start;
132
- let index = 0;
133
150
  function finish(finished, error) {
151
+ activeTimers.delete(timer2);
134
152
  state.active = false;
153
+ state.elapsed = undefined;
135
154
  state.frame = undefined;
155
+ state.index = undefined;
136
156
  if (error) {
137
157
  options.errorCallback?.();
138
158
  }
@@ -144,15 +164,17 @@ var work = function(type, timer2, state, options, isRepeated2) {
144
164
  }
145
165
  current ??= timestamp;
146
166
  start ??= timestamp;
147
- const elapsed = timestamp - current;
148
- const finished = elapsed >= total;
149
- if (finished || elapsed - 2 < interval && interval < elapsed + 2) {
167
+ const time = timestamp - current;
168
+ state.elapsed = elapsed + (current - start);
169
+ const finished = time - elapsed >= total;
170
+ if (finished || time - 2 < interval && interval < time + 2) {
150
171
  if (state.active) {
151
172
  state.callback(isRepeated2 ? index : undefined);
152
173
  }
153
174
  index += 1;
175
+ state.index = index;
154
176
  switch (true) {
155
- case (canTimeout && !finished && timestamp - start >= timeout):
177
+ case (canTimeout && !finished && timestamp - start >= timeout - elapsed):
156
178
  finish(false, true);
157
179
  return;
158
180
  case (!finished && index < count):
@@ -175,11 +197,11 @@ document.addEventListener("visibilitychange", () => {
175
197
  if (document.hidden) {
176
198
  for (const timer2 of activeTimers) {
177
199
  hiddenTimers.add(timer2);
178
- timer2.stop();
200
+ timer2.pause();
179
201
  }
180
202
  } else {
181
203
  for (const timer2 of hiddenTimers) {
182
- timer2.start();
204
+ timer2.continue();
183
205
  }
184
206
  hiddenTimers.clear();
185
207
  }
package/dist/js/timer.mjs CHANGED
@@ -34,6 +34,12 @@ var timer = function(type, callback, partial) {
34
34
  active: false
35
35
  };
36
36
  const instance = Object.create({
37
+ continue() {
38
+ return work("continue", this, state, options, isRepeated2);
39
+ },
40
+ pause() {
41
+ return work("pause", this, state, options, isRepeated2);
42
+ },
37
43
  restart() {
38
44
  return work("restart", this, state, options, isRepeated2);
39
45
  },
@@ -84,6 +90,12 @@ function when(condition, options) {
84
90
  rejecter = reject;
85
91
  });
86
92
  const instance = Object.create({
93
+ continue() {
94
+ repeated.continue();
95
+ },
96
+ pause() {
97
+ repeated.pause();
98
+ },
87
99
  stop() {
88
100
  if (repeated.active) {
89
101
  repeated.stop();
@@ -110,29 +122,37 @@ function when(condition, options) {
110
122
  return instance;
111
123
  }
112
124
  var work = function(type, timer2, state, options, isRepeated2) {
113
- if (type === "start" && state.active || type === "stop" && !state.active) {
125
+ if (["continue", "start"].includes(type) && state.active || ["pause", "stop"].includes(type) && !state.active) {
114
126
  return timer2;
115
127
  }
116
128
  const { count, interval, timeout } = options;
117
- if (typeof state.frame === "number") {
129
+ if (["pause", "stop"].includes(type)) {
130
+ activeTimers.delete(timer2);
118
131
  cancelAnimationFrame(state.frame);
119
132
  options.afterCallback?.(false);
120
- }
121
- if (type === "stop") {
122
- activeTimers.delete(timer2);
123
133
  state.active = false;
124
134
  state.frame = undefined;
135
+ if (type === "stop") {
136
+ state.elapsed = undefined;
137
+ state.index = undefined;
138
+ }
125
139
  return timer2;
126
140
  }
127
141
  state.active = true;
128
142
  const canTimeout = timeout > 0 && timeout < Number.POSITIVE_INFINITY;
129
- const total = count === Number.POSITIVE_INFINITY ? timeout : count * (interval > 0 ? interval : 17);
143
+ const elapsed = type === "continue" ? +(state.elapsed ?? 0) : 0;
144
+ let index = type === "continue" ? +(state.index ?? 0) : 0;
145
+ state.elapsed = elapsed;
146
+ state.index = index;
147
+ const total = (count === Number.POSITIVE_INFINITY ? Number.POSITIVE_INFINITY : (count - index) * (interval > 0 ? interval : 62.5)) - elapsed;
130
148
  let current;
131
149
  let start;
132
- let index = 0;
133
150
  function finish(finished, error) {
151
+ activeTimers.delete(timer2);
134
152
  state.active = false;
153
+ state.elapsed = undefined;
135
154
  state.frame = undefined;
155
+ state.index = undefined;
136
156
  if (error) {
137
157
  options.errorCallback?.();
138
158
  }
@@ -144,15 +164,17 @@ var work = function(type, timer2, state, options, isRepeated2) {
144
164
  }
145
165
  current ??= timestamp;
146
166
  start ??= timestamp;
147
- const elapsed = timestamp - current;
148
- const finished = elapsed >= total;
149
- if (finished || elapsed - 2 < interval && interval < elapsed + 2) {
167
+ const time = timestamp - current;
168
+ state.elapsed = elapsed + (current - start);
169
+ const finished = time - elapsed >= total;
170
+ if (finished || time - 2 < interval && interval < time + 2) {
150
171
  if (state.active) {
151
172
  state.callback(isRepeated2 ? index : undefined);
152
173
  }
153
174
  index += 1;
175
+ state.index = index;
154
176
  switch (true) {
155
- case (canTimeout && !finished && timestamp - start >= timeout):
177
+ case (canTimeout && !finished && timestamp - start >= timeout - elapsed):
156
178
  finish(false, true);
157
179
  return;
158
180
  case (!finished && index < count):
@@ -175,11 +197,11 @@ document.addEventListener("visibilitychange", () => {
175
197
  if (document.hidden) {
176
198
  for (const timer2 of activeTimers) {
177
199
  hiddenTimers.add(timer2);
178
- timer2.stop();
200
+ timer2.pause();
179
201
  }
180
202
  } else {
181
203
  for (const timer2 of hiddenTimers) {
182
- timer2.start();
204
+ timer2.continue();
183
205
  }
184
206
  hiddenTimers.clear();
185
207
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "description": "Sweet little atomic goodies…",
10
10
  "devDependencies": {
11
11
  "@biomejs/biome": "^1.7",
12
- "@happy-dom/global-registrator": "^14.11",
12
+ "@happy-dom/global-registrator": "^14.12",
13
13
  "bun": "^1.1",
14
14
  "sass": "^1.77",
15
15
  "typescript": "^5.4"
@@ -105,11 +105,7 @@
105
105
  },
106
106
  "./package.json": "./package.json"
107
107
  },
108
- "files": [
109
- "dist",
110
- "src",
111
- "types"
112
- ],
108
+ "files": ["dist", "src", "types"],
113
109
  "keywords": [],
114
110
  "license": "MIT",
115
111
  "main": "./dist/js/index.js",
@@ -131,5 +127,5 @@
131
127
  },
132
128
  "type": "module",
133
129
  "types": "./types/index.d.ts",
134
- "version": "0.46.0"
130
+ "version": "0.47.1"
135
131
  }
package/src/js/timer.ts CHANGED
@@ -24,6 +24,13 @@ type BaseOptions = {
24
24
  timeout: number;
25
25
  };
26
26
 
27
+ type BaseTimer = {
28
+ /**
29
+ * Is the timer running?
30
+ */
31
+ get active(): boolean;
32
+ };
33
+
27
34
  type OptionsWithCount = {
28
35
  /**
29
36
  * How many times the timer should repeat
@@ -50,7 +57,10 @@ type RepeatOptions = {
50
57
  type State = {
51
58
  active: boolean;
52
59
  callback: AnyCallback;
60
+ count?: number;
61
+ elapsed?: number;
53
62
  frame?: number;
63
+ index?: number;
54
64
  };
55
65
 
56
66
  /**
@@ -58,22 +68,26 @@ type State = {
58
68
  */
59
69
  export type Timer = {
60
70
  /**
61
- * Is the timer running?
71
+ * Continues the timer _(if it was paused)_
62
72
  */
63
- get active(): boolean;
73
+ continue(): Timer;
74
+ /**
75
+ * Pauses the timer _(if it was running)_
76
+ */
77
+ pause(): Timer;
64
78
  /**
65
- * Restarts the timer
79
+ * Restarts the timer _(if it was running)_
66
80
  */
67
81
  restart(): Timer;
68
82
  /**
69
- * Starts the timer
83
+ * Starts the timer _(if it was stopped)_
70
84
  */
71
85
  start(): Timer;
72
86
  /**
73
- * Stops the timer
87
+ * Stops the timer _(if it was running)_
74
88
  */
75
89
  stop(): Timer;
76
- };
90
+ } & BaseTimer;
77
91
 
78
92
  type TimerOptions = {} & RepeatOptions;
79
93
 
@@ -81,13 +95,17 @@ type WaitOptions = {} & BaseOptions & OptionsWithError;
81
95
 
82
96
  export type When = {
83
97
  /**
84
- * Is the timer running?
98
+ * Continues the timer _(if it was paused)_
85
99
  */
86
- get active(): boolean;
100
+ continue(): Timer;
87
101
  /**
88
- * Stops the timer
102
+ * Pauses the timer _(if it was running)_
89
103
  */
90
- stop(): void;
104
+ pause(): Timer;
105
+ /**
106
+ * Stops the timer _(if it was running)_
107
+ */
108
+ stop(): Timer;
91
109
  /**
92
110
  * Starts the timer and returns a promise that resolves when the condition is met
93
111
  */
@@ -95,11 +113,11 @@ export type When = {
95
113
  resolve?: (() => void) | null,
96
114
  reject?: (() => void) | null,
97
115
  ): Promise<void>;
98
- };
116
+ } & BaseTimer;
99
117
 
100
118
  type WhenOptions = {} & OptionsWithCount;
101
119
 
102
- type WorkType = 'restart' | 'start' | 'stop';
120
+ type WorkType = 'continue' | 'pause' | 'restart' | 'start' | 'stop';
103
121
 
104
122
  const activeTimers = new Set<Timer>();
105
123
  const hiddenTimers = new Set<Timer>();
@@ -183,6 +201,12 @@ function timer(
183
201
  };
184
202
 
185
203
  const instance = Object.create({
204
+ continue() {
205
+ return work('continue', this as Timer, state, options, isRepeated);
206
+ },
207
+ pause() {
208
+ return work('pause', this as Timer, state, options, isRepeated);
209
+ },
186
210
  restart() {
187
211
  return work('restart', this as Timer, state, options, isRepeated);
188
212
  },
@@ -280,6 +304,12 @@ export function when(
280
304
  });
281
305
 
282
306
  const instance = Object.create({
307
+ continue() {
308
+ repeated.continue();
309
+ },
310
+ pause() {
311
+ repeated.pause();
312
+ },
283
313
  stop() {
284
314
  if (repeated.active) {
285
315
  repeated.stop();
@@ -319,46 +349,57 @@ function work(
319
349
  isRepeated: boolean,
320
350
  ): Timer {
321
351
  if (
322
- (type === 'start' && state.active) ||
323
- (type === 'stop' && !state.active)
352
+ (['continue', 'start'].includes(type) && state.active) ||
353
+ (['pause', 'stop'].includes(type) && !state.active)
324
354
  ) {
325
355
  return timer;
326
356
  }
327
357
 
328
358
  const {count, interval, timeout} = options;
329
359
 
330
- if (typeof state.frame === 'number') {
331
- cancelAnimationFrame(state.frame);
360
+ if (['pause', 'stop'].includes(type)) {
361
+ activeTimers.delete(timer);
332
362
 
333
- options.afterCallback?.(false);
334
- }
363
+ cancelAnimationFrame(state.frame as never);
335
364
 
336
- if (type === 'stop') {
337
- activeTimers.delete(timer);
365
+ options.afterCallback?.(false);
338
366
 
339
367
  state.active = false;
340
368
  state.frame = undefined;
341
369
 
370
+ if (type === 'stop') {
371
+ state.elapsed = undefined;
372
+ state.index = undefined;
373
+ }
374
+
342
375
  return timer;
343
376
  }
344
377
 
345
378
  state.active = true;
346
379
 
347
380
  const canTimeout = timeout > 0 && timeout < Number.POSITIVE_INFINITY;
381
+ const elapsed = type === 'continue' ? +(state.elapsed ?? 0) : 0;
382
+
383
+ let index = type === 'continue' ? +(state.index ?? 0) : 0;
384
+
385
+ state.elapsed = elapsed;
386
+ state.index = index;
348
387
 
349
388
  const total =
350
- count === Number.POSITIVE_INFINITY
351
- ? timeout
352
- : count * (interval > 0 ? interval : 17);
389
+ (count === Number.POSITIVE_INFINITY
390
+ ? Number.POSITIVE_INFINITY
391
+ : (count - index) * (interval > 0 ? interval : 1000 / 16)) - elapsed;
353
392
 
354
393
  let current: DOMHighResTimeStamp | null;
355
394
  let start: DOMHighResTimeStamp | null;
356
395
 
357
- let index = 0;
358
-
359
396
  function finish(finished: boolean, error: boolean) {
397
+ activeTimers.delete(timer);
398
+
360
399
  state.active = false;
400
+ state.elapsed = undefined;
361
401
  state.frame = undefined;
402
+ state.index = undefined;
362
403
 
363
404
  if (error) {
364
405
  options.errorCallback?.();
@@ -375,18 +416,23 @@ function work(
375
416
  current ??= timestamp;
376
417
  start ??= timestamp;
377
418
 
378
- const elapsed = timestamp - current;
379
- const finished = elapsed >= total;
419
+ const time = timestamp - current;
420
+
421
+ state.elapsed = elapsed + (current - start);
380
422
 
381
- if (finished || (elapsed - 2 < interval && interval < elapsed + 2)) {
423
+ const finished = time - elapsed >= total;
424
+
425
+ if (finished || (time - 2 < interval && interval < time + 2)) {
382
426
  if (state.active) {
383
427
  state.callback((isRepeated ? index : undefined) as never);
384
428
  }
385
429
 
386
430
  index += 1;
387
431
 
432
+ state.index = index;
433
+
388
434
  switch (true) {
389
- case canTimeout && !finished && timestamp - start >= timeout:
435
+ case canTimeout && !finished && timestamp - start >= timeout - elapsed:
390
436
  finish(false, true);
391
437
  return;
392
438
 
@@ -414,11 +460,11 @@ document.addEventListener('visibilitychange', () => {
414
460
  if (document.hidden) {
415
461
  for (const timer of activeTimers) {
416
462
  hiddenTimers.add(timer);
417
- timer.stop();
463
+ timer.pause();
418
464
  }
419
465
  } else {
420
466
  for (const timer of hiddenTimers) {
421
- timer.start();
467
+ timer.continue();
422
468
  }
423
469
 
424
470
  hiddenTimers.clear();
package/types/timer.d.ts CHANGED
@@ -17,6 +17,12 @@ type BaseOptions = {
17
17
  */
18
18
  timeout: number;
19
19
  };
20
+ type BaseTimer = {
21
+ /**
22
+ * Is the timer running?
23
+ */
24
+ get active(): boolean;
25
+ };
20
26
  type OptionsWithCount = {
21
27
  /**
22
28
  * How many times the timer should repeat
@@ -41,37 +47,45 @@ type RepeatOptions = {
41
47
  */
42
48
  export type Timer = {
43
49
  /**
44
- * Is the timer running?
50
+ * Continues the timer _(if it was paused)_
45
51
  */
46
- get active(): boolean;
52
+ continue(): Timer;
53
+ /**
54
+ * Pauses the timer _(if it was running)_
55
+ */
56
+ pause(): Timer;
47
57
  /**
48
- * Restarts the timer
58
+ * Restarts the timer _(if it was running)_
49
59
  */
50
60
  restart(): Timer;
51
61
  /**
52
- * Starts the timer
62
+ * Starts the timer _(if it was stopped)_
53
63
  */
54
64
  start(): Timer;
55
65
  /**
56
- * Stops the timer
66
+ * Stops the timer _(if it was running)_
57
67
  */
58
68
  stop(): Timer;
59
- };
69
+ } & BaseTimer;
60
70
  type WaitOptions = {} & BaseOptions & OptionsWithError;
61
71
  export type When = {
62
72
  /**
63
- * Is the timer running?
73
+ * Continues the timer _(if it was paused)_
64
74
  */
65
- get active(): boolean;
75
+ continue(): Timer;
66
76
  /**
67
- * Stops the timer
77
+ * Pauses the timer _(if it was running)_
68
78
  */
69
- stop(): void;
79
+ pause(): Timer;
80
+ /**
81
+ * Stops the timer _(if it was running)_
82
+ */
83
+ stop(): Timer;
70
84
  /**
71
85
  * Starts the timer and returns a promise that resolves when the condition is met
72
86
  */
73
87
  then(resolve?: (() => void) | null, reject?: (() => void) | null): Promise<void>;
74
- };
88
+ } & BaseTimer;
75
89
  type WhenOptions = {} & OptionsWithCount;
76
90
  /**
77
91
  * Is the value a repeating timer?