@oscarpalmer/timer 0.28.0 → 0.30.0

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.
Files changed (67) hide show
  1. package/dist/constants.cjs +32 -4
  2. package/dist/constants.js +26 -9
  3. package/dist/delay.cjs +24 -0
  4. package/dist/delay.js +20 -0
  5. package/dist/get.cjs +15 -0
  6. package/dist/get.js +10 -0
  7. package/dist/global.cjs +17 -2
  8. package/dist/global.js +15 -1
  9. package/dist/index.cjs +16 -44
  10. package/dist/index.js +6 -50
  11. package/dist/is.cjs +11 -8
  12. package/dist/is.js +8 -12
  13. package/dist/models.cjs +5 -2
  14. package/dist/models.js +2 -3
  15. package/dist/node_modules/@oscarpalmer/atoms/dist/function.cjs +8 -0
  16. package/dist/node_modules/@oscarpalmer/atoms/dist/function.js +4 -0
  17. package/dist/repeat.cjs +30 -0
  18. package/dist/repeat.js +26 -0
  19. package/dist/timer.cjs +59 -71
  20. package/dist/timer.full.js +472 -0
  21. package/dist/timer.js +56 -72
  22. package/dist/wait.cjs +30 -0
  23. package/dist/wait.js +26 -0
  24. package/dist/when.cjs +59 -44
  25. package/dist/when.js +55 -44
  26. package/dist/work.cjs +72 -0
  27. package/dist/work.js +68 -0
  28. package/package.json +49 -9
  29. package/src/constants.ts +51 -6
  30. package/src/delay.ts +25 -0
  31. package/src/get.ts +12 -0
  32. package/src/global.ts +16 -1
  33. package/src/index.ts +5 -48
  34. package/src/is.ts +6 -6
  35. package/src/models.ts +55 -47
  36. package/src/repeat.ts +32 -0
  37. package/src/timer.ts +67 -151
  38. package/src/wait.ts +31 -0
  39. package/src/when.ts +49 -24
  40. package/src/work.ts +129 -0
  41. package/types/constants.d.cts +49 -74
  42. package/types/constants.d.ts +15 -6
  43. package/types/delay.d.cts +8 -0
  44. package/types/delay.d.ts +4 -0
  45. package/types/get.d.cts +7 -0
  46. package/types/get.d.ts +3 -0
  47. package/types/index.d.cts +89 -94
  48. package/types/index.d.ts +5 -6
  49. package/types/is.d.cts +50 -69
  50. package/types/models.d.cts +61 -63
  51. package/types/models.d.ts +43 -40
  52. package/types/repeat.d.cts +98 -0
  53. package/types/repeat.d.ts +7 -0
  54. package/types/timer.d.cts +35 -97
  55. package/types/timer.d.ts +19 -52
  56. package/types/wait.d.cts +83 -0
  57. package/types/wait.d.ts +8 -0
  58. package/types/when.d.cts +65 -69
  59. package/types/when.d.ts +18 -5
  60. package/types/work.d.cts +78 -0
  61. package/types/work.d.ts +3 -0
  62. package/dist/functions.cjs +0 -99
  63. package/dist/functions.js +0 -99
  64. package/dist/timer.iife.js +0 -431
  65. package/src/functions.ts +0 -158
  66. package/types/functions.d.cts +0 -113
  67. package/types/functions.d.ts +0 -4
package/src/when.ts CHANGED
@@ -1,29 +1,46 @@
1
1
  import {noop} from '@oscarpalmer/atoms/function';
2
- import type {WhenOptions, WhenState} from './models';
3
- import {BasicTimer, timer} from './timer';
2
+ import {destroyedMessage, milliseconds, startedMessage} from './constants';
3
+ import {getValidNumber} from './get';
4
+ import {TimerTrace, type WhenOptions, type WhenState} from './models';
5
+ import {Timer} from './timer';
6
+ import {work} from './work';
4
7
 
5
- const destroyedMessage = 'Timer has already been destroyed';
6
- const startedMessage = 'Timer has already been started';
8
+ class When {
9
+ private readonly $timer = 'when';
10
+ private readonly state: WhenState;
7
11
 
8
- export class When extends BasicTimer<WhenState> {
12
+ /**
13
+ * Is the timer active?
14
+ */
9
15
  get active() {
10
16
  return this.state.timer?.active ?? false;
11
17
  }
12
18
 
19
+ /**
20
+ * Is the timer destroyed?
21
+ */
13
22
  get destroyed() {
14
23
  return this.state.timer == null;
15
24
  }
16
25
 
26
+ /**
27
+ * Is the timer paused?
28
+ */
17
29
  get paused() {
18
30
  return this.state.timer?.paused ?? false;
19
31
  }
20
32
 
21
- get trace() {
22
- return this.state.timer?.trace;
33
+ /**
34
+ * Get the timer's origin _(if debugging is enabled)_
35
+ */
36
+ get trace(): string | undefined {
37
+ return globalThis._oscarpalmer_timer_debug ?? false
38
+ ? this.state.timer?.trace
39
+ : undefined;
23
40
  }
24
41
 
25
42
  constructor(state: WhenState) {
26
- super('when', state);
43
+ this.state = state;
27
44
  }
28
45
 
29
46
  /**
@@ -88,29 +105,35 @@ export class When extends BasicTimer<WhenState> {
88
105
  }
89
106
 
90
107
  /**
91
- * - Creates a promise that resolves when a condition is met
92
- * - If the condition is never met in a timely manner, the promise will reject
108
+ * Create a conditional timer
93
109
  */
94
110
  export function when(
95
111
  condition: () => boolean,
96
112
  options?: Partial<WhenOptions>,
97
113
  ): When {
114
+ let called = false;
98
115
  let result = false;
99
116
 
100
117
  const state: WhenState = {
101
118
  started: false,
102
- timer: timer(
103
- 'repeat',
104
- () => {
105
- if (condition()) {
106
- result = true;
107
-
108
- state.timer.stop();
109
- }
119
+ timer: new Timer(
120
+ 'when',
121
+ work,
122
+ {
123
+ callback() {
124
+ if (condition()) {
125
+ result = true;
126
+
127
+ state.timer.stop();
128
+ }
129
+ },
130
+ trace: new TimerTrace().stack,
110
131
  },
111
132
  {
112
- afterCallback() {
113
- if (!state.timer.paused) {
133
+ onAfter() {
134
+ if (!(state.timer?.paused ?? false) && !called) {
135
+ called = true;
136
+
114
137
  if (result) {
115
138
  state.resolver?.();
116
139
  } else {
@@ -120,14 +143,14 @@ export function when(
120
143
  instance.destroy();
121
144
  }
122
145
  },
123
- errorCallback() {
146
+ onError() {
124
147
  state.rejecter?.();
125
148
 
126
149
  instance.destroy();
127
150
  },
128
- count: options?.count,
129
- interval: options?.interval,
130
- timeout: options?.timeout,
151
+ count: getValidNumber(options?.count),
152
+ interval: getValidNumber(options?.interval, milliseconds),
153
+ timeout: getValidNumber(options?.timeout),
131
154
  },
132
155
  false,
133
156
  ),
@@ -144,3 +167,5 @@ export function when(
144
167
 
145
168
  return instance;
146
169
  }
170
+
171
+ export type {When};
package/src/work.ts ADDED
@@ -0,0 +1,129 @@
1
+ import {
2
+ activeTimers,
3
+ beginTypes,
4
+ endOrRestartTypes,
5
+ endTypes,
6
+ milliseconds,
7
+ pauseTypes,
8
+ } from './constants';
9
+ import type {
10
+ TimerOptions,
11
+ TimerState,
12
+ WorkHandlerTimer,
13
+ WorkHandlerType,
14
+ } from './models';
15
+ import type {Timer} from './timer';
16
+
17
+ function finish(
18
+ timer: WorkHandlerTimer,
19
+ state: TimerState,
20
+ options: TimerOptions,
21
+ success: boolean,
22
+ ): void {
23
+ activeTimers.delete(timer.instance);
24
+
25
+ state.active = false;
26
+ state.elapsed = 0;
27
+ state.frame = undefined;
28
+
29
+ if (timer.type === 'wait') {
30
+ state.callback();
31
+ } else {
32
+ options.onAfter?.(success);
33
+ }
34
+ }
35
+
36
+ export function work(
37
+ type: WorkHandlerType,
38
+ timer: WorkHandlerTimer,
39
+ state: TimerState,
40
+ options: TimerOptions,
41
+ ): Timer {
42
+ if (
43
+ (state.destroyed && type !== 'stop') ||
44
+ (state.active ? beginTypes.has(type) : endTypes.has(type))
45
+ ) {
46
+ return timer.instance;
47
+ }
48
+
49
+ const pausable = pauseTypes.has(type);
50
+
51
+ state.elapsed = pausable ? state.elapsed : 0;
52
+ state.index = pausable ? state.index : 0;
53
+ state.total = pausable ? state.total : 0;
54
+
55
+ if (endOrRestartTypes.has(type)) {
56
+ activeTimers.delete(timer.instance);
57
+
58
+ cancelAnimationFrame(state.frame as never);
59
+
60
+ if (type === 'stop') {
61
+ options.onAfter?.(false);
62
+ }
63
+
64
+ state.active = false;
65
+ state.frame = undefined;
66
+ state.paused = type === 'pause';
67
+
68
+ return type === 'restart'
69
+ ? work('start', timer, state, options)
70
+ : timer.instance;
71
+ }
72
+
73
+ state.active = true;
74
+ state.paused = false;
75
+
76
+ let start: DOMHighResTimeStamp | undefined;
77
+
78
+ function step(now: DOMHighResTimeStamp): void {
79
+ if (!state.active) {
80
+ return;
81
+ }
82
+
83
+ start ??= now;
84
+
85
+ const difference = now - start;
86
+
87
+ state.elapsed += difference;
88
+ state.total += difference;
89
+
90
+ if (options.timeout > 0 && state.total >= options.timeout) {
91
+ options.onError?.();
92
+
93
+ finish(timer, state, options, false);
94
+
95
+ return;
96
+ }
97
+
98
+ if (
99
+ options.interval === milliseconds ||
100
+ state.elapsed >= options.interval - 5
101
+ ) {
102
+ if (options.count > -1) {
103
+ (state.callback as (index: number) => void)(state.index);
104
+ }
105
+
106
+ start = now;
107
+
108
+ state.elapsed = 0;
109
+ state.index += 1;
110
+
111
+ if (
112
+ options.count === -1 ||
113
+ (options.count > 0 && state.index >= options.count)
114
+ ) {
115
+ finish(timer, state, options, true);
116
+
117
+ return;
118
+ }
119
+ }
120
+
121
+ state.frame = requestAnimationFrame(step);
122
+ }
123
+
124
+ activeTimers.add(timer.instance);
125
+
126
+ state.frame = requestAnimationFrame(step);
127
+
128
+ return timer.instance;
129
+ }
@@ -1,112 +1,78 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
- declare abstract class BasicTimer<State> {
4
- protected readonly $timer: string;
5
- protected readonly state: State;
6
- constructor(type: "repeat" | "wait" | "when", state: State);
3
+ declare class Timer {
4
+ #private;
5
+ protected readonly worker: WorkHandler;
6
+ protected readonly options: TimerOptions;
7
+ private readonly $timer;
8
+ protected readonly state: TimerState;
7
9
  /**
8
- * Is the timer running?
10
+ * Is the timer active?
9
11
  */
10
- abstract readonly active: boolean;
12
+ get active(): boolean;
11
13
  /**
12
14
  * Is the timer destroyed?
13
15
  */
14
- abstract readonly destroyed: boolean;
16
+ get destroyed(): boolean;
15
17
  /**
16
18
  * Is the timer paused?
17
19
  */
18
- abstract readonly paused: boolean;
20
+ get paused(): boolean;
19
21
  /**
20
- * Gets the traced location of the timer
22
+ * Get the timer's origin _(if debugging is enabled)_
21
23
  */
22
- abstract readonly trace: string | undefined;
23
- }
24
- declare class Timer extends BasicTimer<TimerState> {
25
- private readonly options;
26
- get active(): boolean;
27
- get destroyed(): boolean;
28
- get paused(): boolean;
29
24
  get trace(): string | undefined;
30
- constructor(type: "repeat" | "wait", state: TimerState, options: TimerOptions);
25
+ constructor(type: TimerType, worker: WorkHandler, state: Pick<TimerState, "callback" | "trace">, options: TimerOptions, start: boolean);
31
26
  /**
32
- * Continues the timer _(if it was paused)_
27
+ * Continue running the timer _(if it's paused)_
33
28
  */
34
29
  continue(): Timer;
35
30
  /**
36
- * Destroys the timer _(after stopping it, if it was running)_
31
+ * Destroy the timer
37
32
  */
38
33
  destroy(): void;
39
34
  /**
40
- * Pauses the timer _(if it was running)_
35
+ * Pause the timer _(if it's running)_
41
36
  */
42
37
  pause(): Timer;
43
38
  /**
44
- * Restarts the timer _(if it was running)_
39
+ * Restart the timer _(or start it, if it's not running)_
45
40
  */
46
41
  restart(): Timer;
47
42
  /**
48
- * Starts the timer _(if it was stopped)_
43
+ * Start the timer _(if it's not running)_
49
44
  */
50
45
  start(): Timer;
51
46
  /**
52
- * Stops the timer _(if it was running)_
47
+ * Stop the timer _(if it's running)_
53
48
  */
54
49
  stop(): Timer;
55
50
  }
56
- /**
57
- * Callback that runs after the timer has finished (or is stopped)
58
- * - `finished` is `true` if the timer was allowed to finish, and `false` if it was stopped
59
- */
60
- export type AfterCallback = (finished: boolean) => void;
61
- export type AnyCallback = (() => void) | IndexedCallback;
62
- /**
63
- * Callback that runs for each iteration of the timer
64
- */
65
- export type IndexedCallback = (index: number) => void;
66
- export type BaseOptions = {
67
- /**
68
- * Interval between each callback
69
- */
51
+ export type TimerOptions = {
52
+ onAfter: ((finished: boolean) => void) | undefined;
53
+ onError: (() => void) | undefined;
54
+ count: number;
70
55
  interval: number;
71
- /**
72
- * Maximum amount of time the timer may run for
73
- */
74
56
  timeout: number;
75
57
  };
76
- export type OptionsWithCount = {
77
- /**
78
- * How many times the timer should repeat
79
- */
80
- count: number;
81
- } & BaseOptions;
82
- export type OptionsWithError = {
83
- /**
84
- * Callback to run when an error occurs _(usually a timeout)_
85
- */
86
- errorCallback?: () => void;
87
- };
88
- export type RepeatOptions = {
89
- /**
90
- * Callback to run after the timer has finished (or is stopped)
91
- * - `finished` is `true` if the timer was allowed to finish, and `false` if it was stopped
92
- */
93
- afterCallback?: AfterCallback;
94
- } & OptionsWithCount & OptionsWithError;
95
- export type TimerOptions = {} & RepeatOptions;
96
58
  export type TimerState = {
97
59
  active: boolean;
98
- callback: AnyCallback;
60
+ callback: () => void;
99
61
  destroyed: boolean;
100
- count?: number;
101
- elapsed?: number;
102
- frame?: number;
103
- index?: number;
104
- isRepeated: boolean;
105
- minimum: number;
62
+ elapsed: number;
63
+ frame: number | undefined;
64
+ index: number;
106
65
  paused: boolean;
107
- trace?: string;
66
+ total: number;
67
+ trace: string | undefined;
108
68
  };
109
- export type WorkType = "continue" | "pause" | "restart" | "start" | "stop";
69
+ export type TimerType = "repeat" | "wait" | "when";
70
+ export type WorkHandler = (type: WorkHandlerType, timer: WorkHandlerTimer, state: TimerState, options: TimerOptions) => Timer;
71
+ export type WorkHandlerTimer = {
72
+ instance: Timer;
73
+ type: TimerType;
74
+ };
75
+ export type WorkHandlerType = "continue" | "pause" | "restart" | "start" | "stop";
110
76
  /**
111
77
  * A set of all active timers
112
78
  */
@@ -114,22 +80,31 @@ export declare const activeTimers: Set<Timer>;
114
80
  /**
115
81
  * A set of types that allow work to begin
116
82
  */
117
- export declare const beginTypes: Set<WorkType>;
83
+ export declare const beginTypes: Set<WorkHandlerType>;
84
+ /**
85
+ * Message to show when a when-timer is destroyed
86
+ */
87
+ export declare const destroyedMessage = "Timer has already been destroyed";
118
88
  /**
119
89
  * A set of types that allow work to end
120
90
  */
121
- export declare const endTypes: Set<WorkType>;
91
+ export declare const endTypes: Set<WorkHandlerType>;
122
92
  /**
123
93
  * A set of types that allow work to end or restart
124
94
  */
125
- export declare const endOrRestartTypes: Set<WorkType>;
95
+ export declare const endOrRestartTypes: Set<WorkHandlerType>;
126
96
  /**
127
97
  * A set of timers that were paused due to the document being hidden
128
98
  */
129
99
  export declare const hiddenTimers: Set<Timer>;
100
+ export declare const pauseTypes: Set<WorkHandlerType>;
101
+ /**
102
+ * Message to show when a when-timer is started
103
+ */
104
+ export declare const startedMessage = "Timer has already been started";
130
105
  /**
131
- * Milliseconds in a frame, probably ;-)
106
+ * A calculated average of the refresh rate of the display _(in milliseconds)_
132
107
  */
133
- export declare const milliseconds: number;
108
+ export declare let milliseconds: number;
134
109
 
135
110
  export {};
@@ -1,4 +1,4 @@
1
- import type { WorkType } from './models';
1
+ import type { WorkHandlerType } from './models';
2
2
  import type { Timer } from './timer';
3
3
  /**
4
4
  * A set of all active timers
@@ -7,20 +7,29 @@ export declare const activeTimers: Set<Timer>;
7
7
  /**
8
8
  * A set of types that allow work to begin
9
9
  */
10
- export declare const beginTypes: Set<WorkType>;
10
+ export declare const beginTypes: Set<WorkHandlerType>;
11
+ /**
12
+ * Message to show when a when-timer is destroyed
13
+ */
14
+ export declare const destroyedMessage = "Timer has already been destroyed";
11
15
  /**
12
16
  * A set of types that allow work to end
13
17
  */
14
- export declare const endTypes: Set<WorkType>;
18
+ export declare const endTypes: Set<WorkHandlerType>;
15
19
  /**
16
20
  * A set of types that allow work to end or restart
17
21
  */
18
- export declare const endOrRestartTypes: Set<WorkType>;
22
+ export declare const endOrRestartTypes: Set<WorkHandlerType>;
19
23
  /**
20
24
  * A set of timers that were paused due to the document being hidden
21
25
  */
22
26
  export declare const hiddenTimers: Set<Timer>;
27
+ export declare const pauseTypes: Set<WorkHandlerType>;
28
+ /**
29
+ * Message to show when a when-timer is started
30
+ */
31
+ export declare const startedMessage = "Timer has already been started";
23
32
  /**
24
- * Milliseconds in a frame, probably ;-)
33
+ * A calculated average of the refresh rate of the display _(in milliseconds)_
25
34
  */
26
- export declare const milliseconds: number;
35
+ export declare let milliseconds: number;
@@ -0,0 +1,8 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ /**
4
+ * Create a delayed promise that resolves after a certain amount of time _(in milliseconds; defaults to screen refresh rate)_
5
+ */
6
+ export declare function delay(time?: number): Promise<void>;
7
+
8
+ export {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Create a delayed promise that resolves after a certain amount of time _(in milliseconds; defaults to screen refresh rate)_
3
+ */
4
+ export declare function delay(time?: number): Promise<void>;
@@ -0,0 +1,7 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ export type GenericCallback = (...args: any[]) => any;
4
+ export declare function getCallback(value: unknown): GenericCallback;
5
+ export declare function getValidNumber(value: unknown, defaultValue?: number): number;
6
+
7
+ export {};
package/types/get.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { GenericCallback } from '@oscarpalmer/atoms/models';
2
+ export declare function getCallback(value: unknown): GenericCallback;
3
+ export declare function getValidNumber(value: unknown, defaultValue?: number): number;