@oscarpalmer/atoms 0.151.0 → 0.152.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.
@@ -677,44 +677,40 @@ function unique(array, key) {
677
677
  if (!Array.isArray(array)) return [];
678
678
  return array.length > 1 ? findValues("unique", array, [key, void 0]).matched : array;
679
679
  }
680
- function getLimiter(callback, throttler, time) {
681
- const interval = typeof time === "number" && time > 0 ? time : 0;
682
- function step(now, parameters) {
683
- if (interval === 0 || now - timestamp >= interval) {
684
- if (throttler) timestamp = now;
685
- callback(...parameters);
686
- } else frame = requestAnimationFrame((next) => {
687
- step(next, parameters);
688
- });
680
+ function getInterval(value) {
681
+ return typeof value === "number" && value > 0 ? value : 0;
682
+ }
683
+ function getTimer(type, callback, time) {
684
+ const interval = getInterval(time);
685
+ function run(now) {
686
+ start ??= now;
687
+ if (interval === 0 || now - start >= interval - OFFSET) {
688
+ if (throttle) start = now;
689
+ callback(...args);
690
+ } else frame = requestAnimationFrame(run);
689
691
  }
692
+ const throttle = type === TIMER_THROTTLE;
693
+ let args;
690
694
  let frame;
691
- let timestamp;
692
- const limiter = (...parameters) => {
693
- limiter.cancel();
694
- frame = requestAnimationFrame((now) => {
695
- timestamp ??= now;
696
- step(now, parameters);
697
- });
695
+ let start;
696
+ const timer = (...parameters) => {
697
+ timer.cancel();
698
+ args = parameters;
699
+ frame = requestAnimationFrame(run);
698
700
  };
699
- limiter.cancel = () => {
700
- if (frame != null) {
701
- cancelAnimationFrame(frame);
702
- frame = void 0;
703
- }
701
+ timer.cancel = () => {
702
+ cancelAnimationFrame(frame);
704
703
  };
705
- return limiter;
704
+ return timer;
706
705
  }
706
+ const OFFSET = 5;
707
+ const TIMER_DEBOUNCE = "debounce";
708
+ const TIMER_THROTTLE = "throttle";
709
+ const TIMER_WAIT = "wait";
707
710
  /**
708
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
709
- *
710
- * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
711
- * @param callback Callback to debounce
712
- * @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
713
- * @returns Debounced callback with a `cancel` method
711
+ * A function that does nothing, which can be useful, I guess…
714
712
  */
715
- function debounce(callback, time) {
716
- return getLimiter(callback, false, time);
717
- }
713
+ function noop() {}
718
714
  /**
719
715
  * Is the number between a minimum and maximum value?
720
716
  * @param value Value to check
@@ -922,13 +918,24 @@ function memoize(callback, options) {
922
918
  }
923
919
  const DEFAULT_CACHE_SIZE = 1024;
924
920
  /**
921
+ * Debounce a function, ensuring it is only called after `time` milliseconds have passed
922
+ *
923
+ * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
924
+ * @param callback Callback to debounce
925
+ * @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
926
+ * @returns Debounced callback with a `cancel` method
927
+ */
928
+ function debounce(callback, time) {
929
+ return getTimer(TIMER_DEBOUNCE, callback, time);
930
+ }
931
+ /**
925
932
  * Throttle a function, ensuring it is only called once every `time` milliseconds
926
933
  * @param callback Callback to throttle
927
934
  * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
928
935
  * @returns Throttled callback with a `cancel` method
929
936
  */
930
937
  function throttle(callback, time) {
931
- return getLimiter(callback, true, time);
938
+ return getTimer(TIMER_THROTTLE, callback, time);
932
939
  }
933
940
  function _isResult(value, okValue) {
934
941
  if (!isPlainObject(value)) return false;
@@ -1029,10 +1036,6 @@ const MESSAGE_PIPE_ARRAY = "Pipe expected to receive an array of functions";
1029
1036
  const MESSAGE_PIPE_PROMISE = "Synchronous Pipe received a promise. Use `pipe.async` instead.";
1030
1037
  const assertFlowFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), MESSAGE_FLOW_ARRAY, TypeError);
1031
1038
  const assertPipeFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), MESSAGE_PIPE_ARRAY, TypeError);
1032
- /**
1033
- * A function that does nothing, which can be useful, I guess…
1034
- */
1035
- function noop() {}
1036
1039
  function equal(first, second, options) {
1037
1040
  return equalValue(first, second, getEqualOptions(options));
1038
1041
  }
@@ -3123,23 +3126,19 @@ async function toResult(value) {
3123
3126
  }
3124
3127
  async function getTimedPromise(promise, time, signal) {
3125
3128
  function abort() {
3126
- cancelAnimationFrame(frame);
3129
+ timer.cancel();
3127
3130
  rejector(signal.reason);
3128
3131
  }
3129
- function run(now) {
3130
- start ??= now;
3131
- if (time === 0 || now - start >= time - 5) settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
3132
- else frame = requestAnimationFrame(run);
3133
- }
3134
3132
  signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
3135
- let frame;
3133
+ const timer = getTimer(TIMER_WAIT, () => {
3134
+ settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
3135
+ }, time);
3136
3136
  let rejector;
3137
- let start;
3138
3137
  return Promise.race([promise, new Promise((_, reject) => {
3139
3138
  rejector = reject;
3140
- frame = requestAnimationFrame(run);
3139
+ timer();
3141
3140
  })]).then((value) => {
3142
- cancelAnimationFrame(frame);
3141
+ timer.cancel();
3143
3142
  signal?.removeEventListener(PROMISE_EVENT_NAME, abort);
3144
3143
  return value;
3145
3144
  });
@@ -3154,24 +3153,20 @@ function delay(options) {
3154
3153
  const { signal, time } = getPromiseOptions(options);
3155
3154
  if (signal?.aborted ?? false) return Promise.reject(signal.reason);
3156
3155
  function abort() {
3157
- cancelAnimationFrame(frame);
3156
+ timer.cancel();
3158
3157
  rejector(signal.reason);
3159
3158
  }
3160
- function run(now) {
3161
- start ??= now;
3162
- if (now - start >= time - 5) settlePromise(abort, resolver, void 0, signal);
3163
- else frame = requestAnimationFrame(run);
3164
- }
3159
+ const timer = getTimer(TIMER_WAIT, () => {
3160
+ settlePromise(abort, resolver, void 0, signal);
3161
+ }, time);
3165
3162
  signal?.addEventListener("abort", abort, PROMISE_ABORT_OPTIONS);
3166
- let frame;
3167
3163
  let rejector;
3168
3164
  let resolver;
3169
- let start;
3170
3165
  return new Promise((resolve, reject) => {
3171
3166
  rejector = reject;
3172
3167
  resolver = resolve;
3173
3168
  if (time === 0) settlePromise(abort, resolve, void 0, signal);
3174
- else frame = requestAnimationFrame(run);
3169
+ else timer();
3175
3170
  });
3176
3171
  }
3177
3172
  async function attemptPromise(value, options) {
@@ -0,0 +1,24 @@
1
+ import { noop } from "../internal/function/misc.js";
2
+ import { TIMER_DEBOUNCE, TIMER_THROTTLE, getTimer } from "../internal/function/timer.js";
3
+ import { memoize } from "./memoize.js";
4
+ /**
5
+ * Debounce a function, ensuring it is only called after `time` milliseconds have passed
6
+ *
7
+ * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
8
+ * @param callback Callback to debounce
9
+ * @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
10
+ * @returns Debounced callback with a `cancel` method
11
+ */
12
+ function debounce(callback, time) {
13
+ return getTimer(TIMER_DEBOUNCE, callback, time);
14
+ }
15
+ /**
16
+ * Throttle a function, ensuring it is only called once every `time` milliseconds
17
+ * @param callback Callback to throttle
18
+ * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
19
+ * @returns Throttled callback with a `cancel` method
20
+ */
21
+ function throttle(callback, time) {
22
+ return getTimer(TIMER_THROTTLE, callback, time);
23
+ }
24
+ export { debounce, memoize, noop, throttle };
package/dist/index.js CHANGED
@@ -36,10 +36,9 @@ import { rgbToHex, rgbToHsl, rgbToHsla } from "./color/space/rgb.js";
36
36
  import { getNormalizedHex, hexToHsl, hexToHsla, hexToRgb, hexToRgba } from "./color/space/hex.js";
37
37
  import { hslToHex, hslToRgb, hslToRgba } from "./color/space/hsl.js";
38
38
  import { getColor } from "./color/index.js";
39
- import { debounce } from "./function/debounce.js";
40
39
  import { SizedMap } from "./sized/map.js";
41
40
  import { memoize } from "./function/memoize.js";
42
- import { throttle } from "./function/throttle.js";
41
+ import { debounce, throttle } from "./function/index.js";
43
42
  import { isError, isOk, isResult } from "./internal/result.js";
44
43
  import { flow, pipe } from "./function/work.js";
45
44
  import { equal } from "./internal/value/equal.js";
@@ -0,0 +1,31 @@
1
+ function getInterval(value) {
2
+ return typeof value === "number" && value > 0 ? value : 0;
3
+ }
4
+ function getTimer(type, callback, time) {
5
+ const interval = getInterval(time);
6
+ function run(now) {
7
+ start ??= now;
8
+ if (interval === 0 || now - start >= interval - OFFSET) {
9
+ if (throttle) start = now;
10
+ callback(...args);
11
+ } else frame = requestAnimationFrame(run);
12
+ }
13
+ const throttle = type === TIMER_THROTTLE;
14
+ let args;
15
+ let frame;
16
+ let start;
17
+ const timer = (...parameters) => {
18
+ timer.cancel();
19
+ args = parameters;
20
+ frame = requestAnimationFrame(run);
21
+ };
22
+ timer.cancel = () => {
23
+ cancelAnimationFrame(frame);
24
+ };
25
+ return timer;
26
+ }
27
+ var OFFSET = 5;
28
+ const TIMER_DEBOUNCE = "debounce";
29
+ const TIMER_THROTTLE = "throttle";
30
+ const TIMER_WAIT = "wait";
31
+ export { TIMER_DEBOUNCE, TIMER_THROTTLE, TIMER_WAIT, getTimer };
@@ -1,3 +1,4 @@
1
+ import { TIMER_WAIT, getTimer } from "../internal/function/timer.js";
1
2
  import { PROMISE_ABORT_OPTIONS } from "./models.js";
2
3
  import { getPromiseOptions } from "./helpers.js";
3
4
  import { settlePromise } from "./misc.js";
@@ -5,24 +6,20 @@ function delay(options) {
5
6
  const { signal, time } = getPromiseOptions(options);
6
7
  if (signal?.aborted ?? false) return Promise.reject(signal.reason);
7
8
  function abort() {
8
- cancelAnimationFrame(frame);
9
+ timer.cancel();
9
10
  rejector(signal.reason);
10
11
  }
11
- function run(now) {
12
- start ??= now;
13
- if (now - start >= time - 5) settlePromise(abort, resolver, void 0, signal);
14
- else frame = requestAnimationFrame(run);
15
- }
12
+ const timer = getTimer(TIMER_WAIT, () => {
13
+ settlePromise(abort, resolver, void 0, signal);
14
+ }, time);
16
15
  signal?.addEventListener("abort", abort, PROMISE_ABORT_OPTIONS);
17
- let frame;
18
16
  let rejector;
19
17
  let resolver;
20
- let start;
21
18
  return new Promise((resolve, reject) => {
22
19
  rejector = reject;
23
20
  resolver = resolve;
24
21
  if (time === 0) settlePromise(abort, resolve, void 0, signal);
25
- else frame = requestAnimationFrame(run);
22
+ else timer();
26
23
  });
27
24
  }
28
25
  export { delay };
@@ -1,25 +1,22 @@
1
+ import { TIMER_WAIT, getTimer } from "../internal/function/timer.js";
1
2
  import { PROMISE_ABORT_OPTIONS, PROMISE_EVENT_NAME, PROMISE_MESSAGE_EXPECTATION_TIMED, PromiseTimeoutError } from "./models.js";
2
3
  import { getPromiseOptions } from "./helpers.js";
3
4
  import { settlePromise } from "./misc.js";
4
5
  async function getTimedPromise(promise, time, signal) {
5
6
  function abort() {
6
- cancelAnimationFrame(frame);
7
+ timer.cancel();
7
8
  rejector(signal.reason);
8
9
  }
9
- function run(now) {
10
- start ??= now;
11
- if (time === 0 || now - start >= time - 5) settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
12
- else frame = requestAnimationFrame(run);
13
- }
14
10
  signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
15
- let frame;
11
+ const timer = getTimer(TIMER_WAIT, () => {
12
+ settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
13
+ }, time);
16
14
  let rejector;
17
- let start;
18
15
  return Promise.race([promise, new Promise((_, reject) => {
19
16
  rejector = reject;
20
- frame = requestAnimationFrame(run);
17
+ timer();
21
18
  })]).then((value) => {
22
- cancelAnimationFrame(frame);
19
+ timer.cancel();
23
20
  signal?.removeEventListener(PROMISE_EVENT_NAME, abort);
24
21
  return value;
25
22
  });
package/package.json CHANGED
@@ -50,26 +50,10 @@
50
50
  "types": "./types/color/index.d.ts",
51
51
  "default": "./dist/color/index.js"
52
52
  },
53
- "./frame-rate": {
54
- "types": "./types/internal/frame-rate.d.ts",
55
- "default": "./dist/internal/frame-rate.js"
56
- },
57
- "./function/debounce": {
58
- "types": "./types/function/debounce.d.ts",
59
- "default": "./dist/function/debounce.js"
60
- },
61
- "./function/memoize": {
53
+ "./function": {
62
54
  "types": "./types/function/memoize.d.ts",
63
55
  "default": "./dist/function/memoize.js"
64
56
  },
65
- "./function/misc": {
66
- "types": "./types/function/misc.d.ts",
67
- "default": "./dist/function/misc.js"
68
- },
69
- "./function/throttle": {
70
- "types": "./types/function/throttle.d.ts",
71
- "default": "./dist/function/throttle.js"
72
- },
73
57
  "./function/work": {
74
58
  "types": "./types/function/work.d.ts",
75
59
  "default": "./dist/function/work.js"
@@ -192,5 +176,5 @@
192
176
  },
193
177
  "type": "module",
194
178
  "types": "./types/index.d.ts",
195
- "version": "0.151.0"
179
+ "version": "0.152.0"
196
180
  }
@@ -0,0 +1,41 @@
1
+ import {getTimer, TIMER_DEBOUNCE, TIMER_THROTTLE} from '../internal/function/timer';
2
+ import type {CancelableCallback, GenericCallback} from '../models';
3
+
4
+ // #region Functions
5
+
6
+ /**
7
+ * Debounce a function, ensuring it is only called after `time` milliseconds have passed
8
+ *
9
+ * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
10
+ * @param callback Callback to debounce
11
+ * @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
12
+ * @returns Debounced callback with a `cancel` method
13
+ */
14
+ export function debounce<Callback extends GenericCallback>(
15
+ callback: Callback,
16
+ time?: number,
17
+ ): CancelableCallback<Callback> {
18
+ return getTimer(TIMER_DEBOUNCE, callback, time);
19
+ }
20
+
21
+ /**
22
+ * Throttle a function, ensuring it is only called once every `time` milliseconds
23
+ * @param callback Callback to throttle
24
+ * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
25
+ * @returns Throttled callback with a `cancel` method
26
+ */
27
+ export function throttle<Callback extends GenericCallback>(
28
+ callback: Callback,
29
+ time?: number,
30
+ ): CancelableCallback<Callback> {
31
+ return getTimer(TIMER_THROTTLE, callback, time);
32
+ }
33
+
34
+ // #endregion
35
+
36
+ // #region Exports
37
+
38
+ export {noop} from '../internal/function/misc';
39
+ export {memoize, type Memoized, type MemoizedOptions} from './memoize';
40
+
41
+ // #endregion
package/src/index.ts CHANGED
@@ -4,9 +4,7 @@ export * from './array/to-map';
4
4
  export * from './array/to-record';
5
5
  export * from './array/unique';
6
6
 
7
- export * from './function/debounce';
8
- export * from './function/memoize';
9
- export * from './function/throttle';
7
+ export * from './function/index';
10
8
  export * from './function/work';
11
9
 
12
10
  export * from './internal/function/misc';
@@ -0,0 +1,68 @@
1
+ import type {CancelableCallback, GenericCallback} from '../../models';
2
+
3
+ // #region Types
4
+
5
+ type TimerType = 'debounce' | 'throttle' | 'wait';
6
+
7
+ // #endregion
8
+
9
+ // #region Functions
10
+
11
+ function getInterval(value: unknown): number {
12
+ return typeof value === 'number' && value > 0 ? value : 0;
13
+ }
14
+
15
+ export function getTimer<Callback extends GenericCallback>(
16
+ type: TimerType,
17
+ callback: Callback,
18
+ time?: number,
19
+ ): CancelableCallback<Callback> {
20
+ const interval = getInterval(time);
21
+
22
+ function run(now: DOMHighResTimeStamp): void {
23
+ start ??= now;
24
+
25
+ if (interval === 0 || now - start >= interval - OFFSET) {
26
+ if (throttle) {
27
+ start = now;
28
+ }
29
+
30
+ callback(...args);
31
+ } else {
32
+ frame = requestAnimationFrame(run);
33
+ }
34
+ }
35
+
36
+ const throttle = type === TIMER_THROTTLE;
37
+
38
+ let args: Parameters<Callback>;
39
+ let frame: DOMHighResTimeStamp | undefined;
40
+ let start: DOMHighResTimeStamp;
41
+
42
+ const timer = (...parameters: Parameters<Callback>): void => {
43
+ timer.cancel();
44
+
45
+ args = parameters;
46
+ frame = requestAnimationFrame(run);
47
+ };
48
+
49
+ timer.cancel = (): void => {
50
+ cancelAnimationFrame(frame!);
51
+ };
52
+
53
+ return timer as CancelableCallback<Callback>;
54
+ }
55
+
56
+ // #endregion
57
+
58
+ // #region Variables
59
+
60
+ const OFFSET = 5;
61
+
62
+ export const TIMER_DEBOUNCE: TimerType = 'debounce';
63
+
64
+ export const TIMER_THROTTLE: TimerType = 'throttle';
65
+
66
+ export const TIMER_WAIT: TimerType = 'wait';
67
+
68
+ // #endregion
@@ -1,3 +1,4 @@
1
+ import {getTimer, TIMER_WAIT} from '../internal/function/timer';
1
2
  import {getPromiseOptions} from './helpers';
2
3
  import {settlePromise} from './misc';
3
4
  import {PROMISE_ABORT_OPTIONS, type PromiseOptions} from './models';
@@ -26,27 +27,23 @@ export function delay(options?: unknown): Promise<void> {
26
27
  }
27
28
 
28
29
  function abort(): void {
29
- cancelAnimationFrame(frame);
30
+ timer.cancel();
30
31
 
31
32
  rejector(signal!.reason);
32
33
  }
33
34
 
34
- function run(now: DOMHighResTimeStamp): void {
35
- start ??= now;
36
-
37
- if (now - start >= time - 5) {
35
+ const timer = getTimer(
36
+ TIMER_WAIT,
37
+ () => {
38
38
  settlePromise(abort, resolver, undefined, signal);
39
- } else {
40
- frame = requestAnimationFrame(run);
41
- }
42
- }
39
+ },
40
+ time,
41
+ );
43
42
 
44
43
  signal?.addEventListener('abort', abort, PROMISE_ABORT_OPTIONS);
45
44
 
46
- let frame: DOMHighResTimeStamp;
47
45
  let rejector: (reason: unknown) => void;
48
46
  let resolver: () => void;
49
- let start: DOMHighResTimeStamp;
50
47
 
51
48
  return new Promise((resolve, reject) => {
52
49
  rejector = reject;
@@ -55,7 +52,7 @@ export function delay(options?: unknown): Promise<void> {
55
52
  if (time === 0) {
56
53
  settlePromise(abort, resolve, undefined, signal);
57
54
  } else {
58
- frame = requestAnimationFrame(run);
55
+ timer();
59
56
  }
60
57
  });
61
58
  }
@@ -1,3 +1,4 @@
1
+ import {getTimer, TIMER_WAIT} from '../internal/function/timer';
1
2
  import type {RequiredKeys} from '../models';
2
3
  import {getPromiseOptions} from './helpers';
3
4
  import {settlePromise} from './misc';
@@ -17,36 +18,32 @@ export async function getTimedPromise<Value>(
17
18
  signal?: AbortSignal,
18
19
  ): Promise<Value> {
19
20
  function abort(): void {
20
- cancelAnimationFrame(frame);
21
+ timer.cancel();
21
22
 
22
23
  rejector(signal!.reason);
23
24
  }
24
25
 
25
- function run(now: DOMHighResTimeStamp): void {
26
- start ??= now;
26
+ signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
27
27
 
28
- if (time === 0 || now - start >= time - 5) {
28
+ const timer = getTimer(
29
+ TIMER_WAIT,
30
+ () => {
29
31
  settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
30
- } else {
31
- frame = requestAnimationFrame(run);
32
- }
33
- }
34
-
35
- signal?.addEventListener(PROMISE_EVENT_NAME, abort, PROMISE_ABORT_OPTIONS);
32
+ },
33
+ time,
34
+ );
36
35
 
37
- let frame: DOMHighResTimeStamp;
38
36
  let rejector: (reason: unknown) => void;
39
- let start: DOMHighResTimeStamp;
40
37
 
41
38
  return Promise.race<Value>([
42
39
  promise,
43
40
  new Promise((_, reject) => {
44
41
  rejector = reject;
45
42
 
46
- frame = requestAnimationFrame(run);
43
+ timer();
47
44
  }),
48
45
  ]).then(value => {
49
- cancelAnimationFrame(frame);
46
+ timer.cancel();
50
47
 
51
48
  signal?.removeEventListener(PROMISE_EVENT_NAME, abort);
52
49
 
@@ -8,3 +8,12 @@ import type { CancelableCallback, GenericCallback } from '../models';
8
8
  * @returns Debounced callback with a `cancel` method
9
9
  */
10
10
  export declare function debounce<Callback extends GenericCallback>(callback: Callback, time?: number): CancelableCallback<Callback>;
11
+ /**
12
+ * Throttle a function, ensuring it is only called once every `time` milliseconds
13
+ * @param callback Callback to throttle
14
+ * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
15
+ * @returns Throttled callback with a `cancel` method
16
+ */
17
+ export declare function throttle<Callback extends GenericCallback>(callback: Callback, time?: number): CancelableCallback<Callback>;
18
+ export { noop } from '../internal/function/misc';
19
+ export { memoize, type Memoized, type MemoizedOptions } from './memoize';
package/types/index.d.ts CHANGED
@@ -3,9 +3,7 @@ export * from './array/misc';
3
3
  export * from './array/to-map';
4
4
  export * from './array/to-record';
5
5
  export * from './array/unique';
6
- export * from './function/debounce';
7
- export * from './function/memoize';
8
- export * from './function/throttle';
6
+ export * from './function/index';
9
7
  export * from './function/work';
10
8
  export * from './internal/function/misc';
11
9
  export * from './internal/string';
@@ -0,0 +1,7 @@
1
+ import type { CancelableCallback, GenericCallback } from '../../models';
2
+ type TimerType = 'debounce' | 'throttle' | 'wait';
3
+ export declare function getTimer<Callback extends GenericCallback>(type: TimerType, callback: Callback, time?: number): CancelableCallback<Callback>;
4
+ export declare const TIMER_DEBOUNCE: TimerType;
5
+ export declare const TIMER_THROTTLE: TimerType;
6
+ export declare const TIMER_WAIT: TimerType;
7
+ export {};
@@ -1,13 +0,0 @@
1
- import { getLimiter } from "../internal/function/limiter.js";
2
- /**
3
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
4
- *
5
- * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
6
- * @param callback Callback to debounce
7
- * @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
8
- * @returns Debounced callback with a `cancel` method
9
- */
10
- function debounce(callback, time) {
11
- return getLimiter(callback, false, time);
12
- }
13
- export { debounce };
@@ -1,2 +0,0 @@
1
- import { noop } from "../internal/function/misc.js";
2
- export { noop };
@@ -1,11 +0,0 @@
1
- import { getLimiter } from "../internal/function/limiter.js";
2
- /**
3
- * Throttle a function, ensuring it is only called once every `time` milliseconds
4
- * @param callback Callback to throttle
5
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
6
- * @returns Throttled callback with a `cancel` method
7
- */
8
- function throttle(callback, time) {
9
- return getLimiter(callback, true, time);
10
- }
11
- export { throttle };
@@ -1,28 +0,0 @@
1
- function getLimiter(callback, throttler, time) {
2
- const interval = typeof time === "number" && time > 0 ? time : 0;
3
- function step(now, parameters) {
4
- if (interval === 0 || now - timestamp >= interval) {
5
- if (throttler) timestamp = now;
6
- callback(...parameters);
7
- } else frame = requestAnimationFrame((next) => {
8
- step(next, parameters);
9
- });
10
- }
11
- let frame;
12
- let timestamp;
13
- const limiter = (...parameters) => {
14
- limiter.cancel();
15
- frame = requestAnimationFrame((now) => {
16
- timestamp ??= now;
17
- step(now, parameters);
18
- });
19
- };
20
- limiter.cancel = () => {
21
- if (frame != null) {
22
- cancelAnimationFrame(frame);
23
- frame = void 0;
24
- }
25
- };
26
- return limiter;
27
- }
28
- export { getLimiter };
@@ -1,21 +0,0 @@
1
- import {getLimiter} from '../internal/function/limiter';
2
- import type {CancelableCallback, GenericCallback} from '../models';
3
-
4
- // #region Functions
5
-
6
- /**
7
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
8
- *
9
- * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
10
- * @param callback Callback to debounce
11
- * @param time Time in milliseconds to wait before calling the callback _(defaults to match frame rate)_
12
- * @returns Debounced callback with a `cancel` method
13
- */
14
- export function debounce<Callback extends GenericCallback>(
15
- callback: Callback,
16
- time?: number,
17
- ): CancelableCallback<Callback> {
18
- return getLimiter(callback, false, time);
19
- }
20
-
21
- // #endregion
@@ -1 +0,0 @@
1
- export {noop} from '../internal/function/misc';
@@ -1,19 +0,0 @@
1
- import {getLimiter} from '../internal/function/limiter';
2
- import type {CancelableCallback, GenericCallback} from '../models';
3
-
4
- // #region Functions
5
-
6
- /**
7
- * Throttle a function, ensuring it is only called once every `time` milliseconds
8
- * @param callback Callback to throttle
9
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
10
- * @returns Throttled callback with a `cancel` method
11
- */
12
- export function throttle<Callback extends GenericCallback>(
13
- callback: Callback,
14
- time?: number,
15
- ): CancelableCallback<Callback> {
16
- return getLimiter(callback, true, time);
17
- }
18
-
19
- // #endregion
@@ -1,51 +0,0 @@
1
- import type {CancelableCallback} from '../../models';
2
- import type {GenericCallback} from '../../models';
3
-
4
- // #region Functions
5
-
6
- export function getLimiter<Callback extends GenericCallback>(
7
- callback: Callback,
8
- throttler: boolean,
9
- time?: number,
10
- ): CancelableCallback<Callback> {
11
- const interval = typeof time === 'number' && time > 0 ? time : 0;;
12
-
13
- function step(now: DOMHighResTimeStamp, parameters: Parameters<Callback>): void {
14
- if (interval === 0 || now - timestamp >= interval) {
15
- if (throttler) {
16
- timestamp = now;
17
- }
18
-
19
- callback(...parameters);
20
- } else {
21
- frame = requestAnimationFrame(next => {
22
- step(next, parameters);
23
- });
24
- }
25
- }
26
-
27
- let frame: DOMHighResTimeStamp | undefined;
28
- let timestamp: DOMHighResTimeStamp;
29
-
30
- const limiter = (...parameters: Parameters<Callback>): void => {
31
- limiter.cancel();
32
-
33
- frame = requestAnimationFrame(now => {
34
- timestamp ??= now;
35
-
36
- step(now, parameters);
37
- });
38
- };
39
-
40
- limiter.cancel = (): void => {
41
- if (frame != null) {
42
- cancelAnimationFrame(frame);
43
-
44
- frame = undefined;
45
- }
46
- };
47
-
48
- return limiter as CancelableCallback<Callback>;
49
- }
50
-
51
- // #endregion
@@ -1 +0,0 @@
1
- export { noop } from '../internal/function/misc';
@@ -1,8 +0,0 @@
1
- import type { CancelableCallback, GenericCallback } from '../models';
2
- /**
3
- * Throttle a function, ensuring it is only called once every `time` milliseconds
4
- * @param callback Callback to throttle
5
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to match frame rate)_
6
- * @returns Throttled callback with a `cancel` method
7
- */
8
- export declare function throttle<Callback extends GenericCallback>(callback: Callback, time?: number): CancelableCallback<Callback>;
@@ -1,3 +0,0 @@
1
- import type { CancelableCallback } from '../../models';
2
- import type { GenericCallback } from '../../models';
3
- export declare function getLimiter<Callback extends GenericCallback>(callback: Callback, throttler: boolean, time?: number): CancelableCallback<Callback>;