@reykjavik/webtools 0.2.6 → 0.2.8
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/CHANGELOG.md +17 -0
- package/README.md +194 -4
- package/async.d.ts +39 -0
- package/async.js +105 -1
- package/errorhandling.d.ts +11 -3
- package/errorhandling.js +2 -2
- package/esm/async.d.ts +39 -0
- package/esm/async.js +102 -0
- package/esm/errorhandling.d.ts +11 -3
- package/esm/errorhandling.js +2 -2
- package/esm/fixIcelandicLocale.js +4 -0
- package/esm/hooks.d.ts +36 -0
- package/esm/hooks.js +46 -0
- package/esm/http.d.ts +1 -0
- package/esm/http.js +1 -1
- package/esm/index.d.ts +1 -0
- package/fixIcelandicLocale.js +4 -0
- package/hooks.d.ts +36 -0
- package/hooks.js +51 -0
- package/http.d.ts +1 -0
- package/http.js +1 -1
- package/index.d.ts +1 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
- ... <!-- Add new lines here. -->
|
|
6
6
|
|
|
7
|
+
## 0.2.8
|
|
8
|
+
|
|
9
|
+
_2025-09-17_
|
|
10
|
+
|
|
11
|
+
- `@reykjavik/webtools/async`:
|
|
12
|
+
- feat: Add `debounce` and `throttle` helpers
|
|
13
|
+
- `@reykjavik/webtools/hooks` (new module):
|
|
14
|
+
- feat: Add `useDebounced` and `useThrottled` hooks
|
|
15
|
+
|
|
16
|
+
## 0.2.7
|
|
17
|
+
|
|
18
|
+
_2025-09-01_
|
|
19
|
+
|
|
20
|
+
- `@reykjavik/webtools/fixIcelandicLocale`:
|
|
21
|
+
- fix: Check for support of each Intl class separately
|
|
22
|
+
- docs: Improve JSDocs and README for `asError()` and `ErrorFromPayload`
|
|
23
|
+
|
|
7
24
|
## 0.2.6
|
|
8
25
|
|
|
9
26
|
_2025-06-20_
|
package/README.md
CHANGED
|
@@ -29,6 +29,11 @@ bun add @reykjavik/webtools
|
|
|
29
29
|
- [`@reykjavik/webtools/async`](#reykjavikwebtoolsasync)
|
|
30
30
|
- [`promiseAllObject`](#promiseallobject)
|
|
31
31
|
- [`maxWait`](#maxwait)
|
|
32
|
+
- [`debounce`](#debounce)
|
|
33
|
+
- [`throttle`](#throttle)
|
|
34
|
+
- [`@reykjavik/webtools/hoooks`](#reykjavikwebtoolshoooks)
|
|
35
|
+
- [`useDebounced`](#usedebounced)
|
|
36
|
+
- [`useThrottled`](#usethrottled)
|
|
32
37
|
- [`@reykjavik/webtools/errorhandling`](#reykjavikwebtoolserrorhandling)
|
|
33
38
|
- [`asError`](#aserror)
|
|
34
39
|
- [`Result` Singleton](#result-singleton)
|
|
@@ -369,6 +374,188 @@ console.log(posts?.reason); // undefined | unknown
|
|
|
369
374
|
|
|
370
375
|
---
|
|
371
376
|
|
|
377
|
+
### `debounce`
|
|
378
|
+
|
|
379
|
+
**Syntax:**
|
|
380
|
+
`debounce<A extends Array<unknown>>(func: (...args: A) => void, delay: number, immediate?: boolean): ((...args: A) => void) & { cancel: (finish?: boolean) => void; }`
|
|
381
|
+
|
|
382
|
+
Returns a debounced function that only runs after `delay` milliseconds of
|
|
383
|
+
quiet-time, and can optionally be made to run `immediate`ly on first call
|
|
384
|
+
before dbouncing subsequent calls.
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
import { debounce } from '@reykjavik/webtools/async';
|
|
388
|
+
|
|
389
|
+
// Basic usage:
|
|
390
|
+
const sayHello = debounce((namme: string) => {
|
|
391
|
+
console.log('Hello ' + name);
|
|
392
|
+
}, 200);
|
|
393
|
+
|
|
394
|
+
sayHello('Alice');
|
|
395
|
+
sayHello('Bob');
|
|
396
|
+
sayHello('Charlie');
|
|
397
|
+
sayHello('Dorothy');
|
|
398
|
+
// Only "Hello Dorothy" is logged, 200ms after the last call
|
|
399
|
+
|
|
400
|
+
// With `immediate` param set to true:
|
|
401
|
+
const sayHi = debounce(
|
|
402
|
+
(namme: string) => console.log('Hi ' + name),
|
|
403
|
+
200,
|
|
404
|
+
true
|
|
405
|
+
);
|
|
406
|
+
sayHi('Alice');
|
|
407
|
+
sayHi('Bob');
|
|
408
|
+
sayHi('Charlie');
|
|
409
|
+
sayHi('Dorothy');
|
|
410
|
+
// "Hi Alice" is logged immediately
|
|
411
|
+
// Then "Hi Dorothy" is logged, 200ms after the last call
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
The returned function has a nice `.cancel()` method, which can optionally
|
|
415
|
+
invoke the function before cancelling, if it had a debounce pending.
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
sayHello('Erica');
|
|
419
|
+
sayHello('Fiona');
|
|
420
|
+
sayHello.cancel();
|
|
421
|
+
// Nothing is logged because the debounce was cancelled
|
|
422
|
+
|
|
423
|
+
sayHello('George');
|
|
424
|
+
sayHello('Harold');
|
|
425
|
+
sayHello.cancel(true); // `finish` parmeter is true
|
|
426
|
+
// "Hello Harold" is logged immediately because it was pending
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
### `throttle`
|
|
432
|
+
|
|
433
|
+
**Syntax:**
|
|
434
|
+
`throttle<A extends Array<unknown>>(func: (...args: A) => void, delay: number, skipFirst?: boolean): ((...args: A) => void) & { finish: (cancel?: boolean) => void; }`
|
|
435
|
+
|
|
436
|
+
Returns a throttled function that never runs more often than every `delay`
|
|
437
|
+
milliseconds. It can optionally made to `skipFirst` invocation.
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import { throttle } from '@reykjavik/webtools/async';
|
|
441
|
+
|
|
442
|
+
// Basic usage:
|
|
443
|
+
const sayHello = throttle((name: string) => {
|
|
444
|
+
console.log('Hello ' + name);
|
|
445
|
+
}, 200);
|
|
446
|
+
|
|
447
|
+
sayHello('Alice');
|
|
448
|
+
sayHello('Bob');
|
|
449
|
+
sayHello('Charlie');
|
|
450
|
+
sayHello('Dorothy');
|
|
451
|
+
// Only "Hello Alice" is logged immediately. The other calls were throttled.
|
|
452
|
+
|
|
453
|
+
// With `skipFirst` param set to true:
|
|
454
|
+
const sayHi = throttle(
|
|
455
|
+
(name: string) => console.log('Hi ' + name),
|
|
456
|
+
200,
|
|
457
|
+
true
|
|
458
|
+
);
|
|
459
|
+
sayHi('Alice');
|
|
460
|
+
sayHi('Bob');
|
|
461
|
+
sayHi('Charlie');
|
|
462
|
+
sayHi('Dorothy');
|
|
463
|
+
// Nothing is logged. The first call was skipped, and the rest were throttled.
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
The returned function also has a nice `.finish()` method to reset the throttle
|
|
467
|
+
timer. By default it instantly invokes the function, if the last call was
|
|
468
|
+
throttled (skipped)-.
|
|
469
|
+
|
|
470
|
+
```ts
|
|
471
|
+
sayHello('Erica');
|
|
472
|
+
sayHello('Fiona');
|
|
473
|
+
sayHello.finish();
|
|
474
|
+
// "Hello Fiona" is logged immediately because it was pending
|
|
475
|
+
|
|
476
|
+
sayHello('George');
|
|
477
|
+
sayHello('Harold');
|
|
478
|
+
sayHello.finish(true); // `cancel` parmeter is true
|
|
479
|
+
// Nothing is logged because the pending call was cancelled
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## `@reykjavik/webtools/hoooks`
|
|
485
|
+
|
|
486
|
+
Some useful React hooks.
|
|
487
|
+
|
|
488
|
+
### `useDebounced`
|
|
489
|
+
|
|
490
|
+
**Syntax:**
|
|
491
|
+
`useDebounced<A extends Array<unknown>>(func: (...args: A) => void, delay: number, immediate?: boolean): ((...args: A) => void) & { cancel: (finish?: boolean) => void; }`
|
|
492
|
+
|
|
493
|
+
Returns a stable debounced function that invokes the supplied function after
|
|
494
|
+
the specified delay. When the component unmounts, any pending (debounced)
|
|
495
|
+
calls are automatically cancelled.
|
|
496
|
+
|
|
497
|
+
**NOTE:** The supplied callback does not need to be memoized. The debouncer
|
|
498
|
+
will always invoke the last supplied version.
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
import { useDebounced } from '@reykjavik/webtools/hoooks';
|
|
502
|
+
|
|
503
|
+
const MyComponent = () => {
|
|
504
|
+
const renderDate = new Date();
|
|
505
|
+
const debouncedSearch = useDebounced((query: string) => {
|
|
506
|
+
console.log('Searching for:', query, 'at', renderDate.toISOString());
|
|
507
|
+
}, 200);
|
|
508
|
+
return (
|
|
509
|
+
<input
|
|
510
|
+
type="text"
|
|
511
|
+
onChange={(e) => {
|
|
512
|
+
debouncedSearch(e.currentTarget.value);
|
|
513
|
+
}}
|
|
514
|
+
/>
|
|
515
|
+
);
|
|
516
|
+
};
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
See [`debounce`](#debounce) for more details about the parameters and the
|
|
520
|
+
returned debounced function's `.cancel()` method.
|
|
521
|
+
|
|
522
|
+
### `useThrottled`
|
|
523
|
+
|
|
524
|
+
**Syntax:**
|
|
525
|
+
`useThrottled<A extends Array<unknown>>(func: (...args: A) => void, delay: number, skipFirst?: boolean): ((...args: A) => void) & { finish: (cancel?: boolean) => void; }`
|
|
526
|
+
|
|
527
|
+
Returns a stable throttler function that throttles the supplied function.
|
|
528
|
+
|
|
529
|
+
**NOTE:** The supplied callback does not need to be memoized. The throttler
|
|
530
|
+
will always invoke the last supplied version.
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
import { useThrottled } from '@reykjavik/webtools/hoooks';
|
|
534
|
+
|
|
535
|
+
const MyComponent = () => {
|
|
536
|
+
const renderDate = new Date();
|
|
537
|
+
const throttledReportPosition = useThrottled((x: number, y: number) => {
|
|
538
|
+
console.log('Mouse position:', x, ',', y, 'at', renderDate.toISOString());
|
|
539
|
+
}, 200);
|
|
540
|
+
|
|
541
|
+
return (
|
|
542
|
+
<div
|
|
543
|
+
style={{ width: '300px', height: '300px', background: '#eee' }}
|
|
544
|
+
onMouseMove={(e) => {
|
|
545
|
+
throttledReportPosition(e.clientX, e.clientY);
|
|
546
|
+
}}
|
|
547
|
+
>
|
|
548
|
+
Move your mouse here.
|
|
549
|
+
</div>
|
|
550
|
+
);
|
|
551
|
+
};
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
See [`throttle`](#throttle) for more details about the parameters and the
|
|
555
|
+
returned throttled function's `.finish()` method.
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
372
559
|
## `@reykjavik/webtools/errorhandling`
|
|
373
560
|
|
|
374
561
|
A small set of lightweight tools for handling errors and promises in a safer,
|
|
@@ -386,7 +573,8 @@ Guarantees that a caught (`catch (e)`) value of `unknown` type, is indeed an
|
|
|
386
573
|
|
|
387
574
|
If the input is an `Error` instance, it is returned as-is. If the input is
|
|
388
575
|
something else it is wrapped in a new `ErrorFromPayload` instance, and the
|
|
389
|
-
original value is stored in as a `payload` property
|
|
576
|
+
original value is stored in as a `payload` property, and it's `.toString()` is
|
|
577
|
+
used for the `message` property.
|
|
390
578
|
|
|
391
579
|
```ts
|
|
392
580
|
import { asError, type ErrorFromPayload } from '@reykjavik/webtools/errorhandling';
|
|
@@ -395,21 +583,23 @@ const theError = new Error('Something went wrong');
|
|
|
395
583
|
try {
|
|
396
584
|
throw theError;
|
|
397
585
|
} catch (err) {
|
|
586
|
+
// theError is an instance of Error so it's returned as-is
|
|
398
587
|
const error = asError(theError);
|
|
399
588
|
console.error(error === theError); // true
|
|
400
|
-
console.error('
|
|
589
|
+
console.error('payload' in error); // false
|
|
401
590
|
}
|
|
402
591
|
|
|
403
|
-
const someObject = ['Something went wrong'];
|
|
592
|
+
const someObject = ['Oops', 'Something went wrong'];
|
|
404
593
|
try {
|
|
405
594
|
throw someObject;
|
|
406
595
|
} catch (err) {
|
|
596
|
+
// the thrown someObject is not an Error so an `ErrorFromPayload` is returned
|
|
407
597
|
const error = asError(someObject);
|
|
408
598
|
console.error(error === someObject); // false
|
|
409
|
-
console.error(error.message === someObject.join(',')); // false
|
|
410
599
|
console.error(error instanceOf ErrorFromPayload); // true
|
|
411
600
|
|
|
412
601
|
console.error(error.payload === someObject); // true
|
|
602
|
+
console.error(error.message === someObject.join(',')); // true
|
|
413
603
|
}
|
|
414
604
|
```
|
|
415
605
|
|
package/async.d.ts
CHANGED
|
@@ -31,4 +31,43 @@ export declare function maxWait<PromiseMap extends PlainObj>(timeout: number, pr
|
|
|
31
31
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#promiseallobject
|
|
32
32
|
*/
|
|
33
33
|
export declare const promiseAllObject: <T extends PlainObj>(promisesMap: T) => Promise<{ -readonly [K in keyof T]: Awaited<T[K]>; }>;
|
|
34
|
+
type Cancellable<A extends Array<unknown>> = ((...args: A) => void) & {
|
|
35
|
+
/**
|
|
36
|
+
* Cancels any pending invocation of the debounced function. \
|
|
37
|
+
* If `finish` is true and if a debounce is pending, the function is invoked
|
|
38
|
+
* before cancelling.
|
|
39
|
+
*/
|
|
40
|
+
cancel(finish?: boolean): void;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Returns a debounced function that only runs after `delay` milliseconds
|
|
44
|
+
* of quiet-time. \
|
|
45
|
+
* The returned function also has a nice `.cancel()` method.
|
|
46
|
+
*
|
|
47
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#debounce
|
|
48
|
+
*/
|
|
49
|
+
export declare const debounce: {
|
|
50
|
+
<A extends Array<unknown>>(func: (...args: A) => void, delay: number, immediate?: boolean): Cancellable<A>;
|
|
51
|
+
d(delay: number, immediate?: boolean): Cancellable<[fn: (...args: Array<any>) => void, ...args: any[]]>;
|
|
52
|
+
};
|
|
53
|
+
type Finishable<A extends Array<unknown>> = ((...args: A) => void) & {
|
|
54
|
+
/**
|
|
55
|
+
* Immediately invokes the function if there is a pending throttle and its last
|
|
56
|
+
* invoication was throttled (cancelled). \
|
|
57
|
+
* If `cancel` is true then only the timer is reset without invoking function.
|
|
58
|
+
*/
|
|
59
|
+
finish(cancel?: boolean): void;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Returns a throttled function that never runs more often than
|
|
63
|
+
* every `delay` milliseconds. \
|
|
64
|
+
* The returned function also has a nice `.finish()` method to reset the
|
|
65
|
+
* throttle timer
|
|
66
|
+
*
|
|
67
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#throttle
|
|
68
|
+
*/
|
|
69
|
+
export declare const throttle: {
|
|
70
|
+
<A extends Array<unknown>>(func: (...args: A) => void, delay: number, skipFirst?: boolean): Finishable<A>;
|
|
71
|
+
d(delay: number, skipFirst?: boolean): Finishable<[fn: (...args: Array<any>) => void, ...args: any[]]>;
|
|
72
|
+
};
|
|
34
73
|
export {};
|
package/async.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.promiseAllObject = exports.addLag = exports.sleep = void 0;
|
|
3
|
+
exports.throttle = exports.debounce = exports.promiseAllObject = exports.addLag = exports.sleep = void 0;
|
|
4
4
|
exports.maxWait = maxWait;
|
|
5
5
|
/**
|
|
6
6
|
* Simple sleep function. Returns a promise that resolves after `length`
|
|
@@ -79,3 +79,107 @@ const promiseAllObject = (promisesMap) => Promise.all(Object.values(promisesMap)
|
|
|
79
79
|
return resolvedMap;
|
|
80
80
|
});
|
|
81
81
|
exports.promiseAllObject = promiseAllObject;
|
|
82
|
+
/**
|
|
83
|
+
* Returns a debounced function that only runs after `delay` milliseconds
|
|
84
|
+
* of quiet-time. \
|
|
85
|
+
* The returned function also has a nice `.cancel()` method.
|
|
86
|
+
*
|
|
87
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#debounce
|
|
88
|
+
*/
|
|
89
|
+
/*#__NO_SIDE_EFFECTS__*/
|
|
90
|
+
const debounce = (
|
|
91
|
+
/** The function to debounce */
|
|
92
|
+
func,
|
|
93
|
+
/** The delay, in milliseconds, to wait before running the function */
|
|
94
|
+
delay,
|
|
95
|
+
/** Whether to run the function at the start of the delay instead of the end */
|
|
96
|
+
immediate) => {
|
|
97
|
+
let timeout;
|
|
98
|
+
let _args;
|
|
99
|
+
let _this;
|
|
100
|
+
const debouncedFn = function (...args) {
|
|
101
|
+
_args = args;
|
|
102
|
+
_this = this;
|
|
103
|
+
immediate && !timeout && func.apply(_this, _args);
|
|
104
|
+
timeout && clearTimeout(timeout);
|
|
105
|
+
timeout = setTimeout(() => {
|
|
106
|
+
debouncedFn.cancel(true);
|
|
107
|
+
}, delay);
|
|
108
|
+
};
|
|
109
|
+
debouncedFn.cancel = (finish) => {
|
|
110
|
+
timeout && clearTimeout(timeout);
|
|
111
|
+
finish && timeout && func.apply(_this, _args);
|
|
112
|
+
timeout = undefined;
|
|
113
|
+
};
|
|
114
|
+
return debouncedFn;
|
|
115
|
+
};
|
|
116
|
+
exports.debounce = debounce;
|
|
117
|
+
/**
|
|
118
|
+
* Sugar to produce a dynamic debounced function that accepts its contents/behavior at call time.
|
|
119
|
+
*
|
|
120
|
+
* Usage:
|
|
121
|
+
* ```ts
|
|
122
|
+
* const myDebouncer = debounce.d(500);
|
|
123
|
+
* myDebouncer(() => { alert('Hello world'); });
|
|
124
|
+
* myDebouncer(() => { alert('I mean: Howdy world!'); });
|
|
125
|
+
* myDebouncer((name) => { alert('Wazzap ' + name); }, 'world');
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* Not documented in README as its usefulness is still uncertain.
|
|
129
|
+
*/
|
|
130
|
+
exports.debounce.d = (delay, immediate) => (0, exports.debounce)(function (fn, ...args) {
|
|
131
|
+
fn.apply(this, args);
|
|
132
|
+
}, delay, immediate);
|
|
133
|
+
/**
|
|
134
|
+
* Returns a throttled function that never runs more often than
|
|
135
|
+
* every `delay` milliseconds. \
|
|
136
|
+
* The returned function also has a nice `.finish()` method to reset the
|
|
137
|
+
* throttle timer
|
|
138
|
+
*
|
|
139
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#throttle
|
|
140
|
+
*/
|
|
141
|
+
/*#__NO_SIDE_EFFECTS__*/
|
|
142
|
+
const throttle = (
|
|
143
|
+
/** The function to throttle */
|
|
144
|
+
func,
|
|
145
|
+
/** The delay, in milliseconds, to wait between invocations */
|
|
146
|
+
delay,
|
|
147
|
+
/** Whether to skip the first invocation instead of running it immediately */
|
|
148
|
+
skipFirst) => {
|
|
149
|
+
let timeout;
|
|
150
|
+
let throttled = 0;
|
|
151
|
+
let _args;
|
|
152
|
+
let _this;
|
|
153
|
+
const throttledFn = function (...args) {
|
|
154
|
+
_args = args;
|
|
155
|
+
_this = this;
|
|
156
|
+
if (!throttled) {
|
|
157
|
+
skipFirst ? throttled++ : func.apply(_this, _args);
|
|
158
|
+
timeout = setTimeout(throttledFn.finish, delay); // Go home TypeScript, you're drunk!
|
|
159
|
+
}
|
|
160
|
+
throttled++;
|
|
161
|
+
};
|
|
162
|
+
throttledFn.finish = (cancel) => {
|
|
163
|
+
timeout && clearTimeout(timeout);
|
|
164
|
+
!cancel && throttled && func.apply(_this, _args);
|
|
165
|
+
throttled = 0;
|
|
166
|
+
};
|
|
167
|
+
return throttledFn;
|
|
168
|
+
};
|
|
169
|
+
exports.throttle = throttle;
|
|
170
|
+
/**
|
|
171
|
+
* Sugar to produce a dynamic debounced function that accepts its contents/behavior at call time.
|
|
172
|
+
*
|
|
173
|
+
* Usage:
|
|
174
|
+
* ```ts
|
|
175
|
+
* const myThrottler = throttle.d(500);
|
|
176
|
+
* myThrottler(() => { alert('Hello world'); });
|
|
177
|
+
* myThrottler(() => { alert('I mean: Howdy world!'); });
|
|
178
|
+
* myThrottler((name) => { alert('Wazzap ' + name); }, 'world');
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* Not documented in README as its usefulness is still uncertain.
|
|
182
|
+
*/
|
|
183
|
+
exports.throttle.d = (delay, skipFirst) => (0, exports.throttle)(function (fn, ...args) {
|
|
184
|
+
fn.apply(this, args);
|
|
185
|
+
}, delay, skipFirst);
|
package/errorhandling.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Error subclass for thrown values that got
|
|
3
|
-
* Error, with the thrown value as the `payload` property.
|
|
2
|
+
* Error subclass for thrown NON-Error values that got turned into an actual
|
|
3
|
+
* Error, with the original thrown value as the `payload` property.
|
|
4
4
|
*
|
|
5
5
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#aserror
|
|
6
6
|
*/
|
|
7
7
|
export declare class ErrorFromPayload extends Error {
|
|
8
|
+
/**
|
|
9
|
+
* This payload property is only set if the original `throw` value was NOT
|
|
10
|
+
* `instanceof Error`.
|
|
11
|
+
*
|
|
12
|
+
* In such cases it contains the thrown value as is, and the `message`
|
|
13
|
+
* property of this `ErrorFromPayload` instance is set to the `.toString()`
|
|
14
|
+
* representation of the payload.
|
|
15
|
+
*/
|
|
8
16
|
payload?: unknown;
|
|
9
17
|
constructor(payload: unknown);
|
|
10
18
|
name: string;
|
|
@@ -50,7 +58,7 @@ export type ResultTupleObj<T, E extends Error = Error> = SuccessResult<T> | Fail
|
|
|
50
58
|
* `[error, results]` tuple with the `result` and `error` also attached as
|
|
51
59
|
* named properties.
|
|
52
60
|
*
|
|
53
|
-
* Works on both promises and
|
|
61
|
+
* Works on both promises and (synchronous) callback functions.
|
|
54
62
|
*
|
|
55
63
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#resultcatch
|
|
56
64
|
*/
|
package/errorhandling.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Result = exports.asError = exports.ErrorFromPayload = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* Error subclass for thrown values that got
|
|
6
|
-
* Error, with the thrown value as the `payload` property.
|
|
5
|
+
* Error subclass for thrown NON-Error values that got turned into an actual
|
|
6
|
+
* Error, with the original thrown value as the `payload` property.
|
|
7
7
|
*
|
|
8
8
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#aserror
|
|
9
9
|
*/
|
package/esm/async.d.ts
CHANGED
|
@@ -31,4 +31,43 @@ export declare function maxWait<PromiseMap extends PlainObj>(timeout: number, pr
|
|
|
31
31
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#promiseallobject
|
|
32
32
|
*/
|
|
33
33
|
export declare const promiseAllObject: <T extends PlainObj>(promisesMap: T) => Promise<{ -readonly [K in keyof T]: Awaited<T[K]>; }>;
|
|
34
|
+
type Cancellable<A extends Array<unknown>> = ((...args: A) => void) & {
|
|
35
|
+
/**
|
|
36
|
+
* Cancels any pending invocation of the debounced function. \
|
|
37
|
+
* If `finish` is true and if a debounce is pending, the function is invoked
|
|
38
|
+
* before cancelling.
|
|
39
|
+
*/
|
|
40
|
+
cancel(finish?: boolean): void;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Returns a debounced function that only runs after `delay` milliseconds
|
|
44
|
+
* of quiet-time. \
|
|
45
|
+
* The returned function also has a nice `.cancel()` method.
|
|
46
|
+
*
|
|
47
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#debounce
|
|
48
|
+
*/
|
|
49
|
+
export declare const debounce: {
|
|
50
|
+
<A extends Array<unknown>>(func: (...args: A) => void, delay: number, immediate?: boolean): Cancellable<A>;
|
|
51
|
+
d(delay: number, immediate?: boolean): Cancellable<[fn: (...args: Array<any>) => void, ...args: any[]]>;
|
|
52
|
+
};
|
|
53
|
+
type Finishable<A extends Array<unknown>> = ((...args: A) => void) & {
|
|
54
|
+
/**
|
|
55
|
+
* Immediately invokes the function if there is a pending throttle and its last
|
|
56
|
+
* invoication was throttled (cancelled). \
|
|
57
|
+
* If `cancel` is true then only the timer is reset without invoking function.
|
|
58
|
+
*/
|
|
59
|
+
finish(cancel?: boolean): void;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Returns a throttled function that never runs more often than
|
|
63
|
+
* every `delay` milliseconds. \
|
|
64
|
+
* The returned function also has a nice `.finish()` method to reset the
|
|
65
|
+
* throttle timer
|
|
66
|
+
*
|
|
67
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#throttle
|
|
68
|
+
*/
|
|
69
|
+
export declare const throttle: {
|
|
70
|
+
<A extends Array<unknown>>(func: (...args: A) => void, delay: number, skipFirst?: boolean): Finishable<A>;
|
|
71
|
+
d(delay: number, skipFirst?: boolean): Finishable<[fn: (...args: Array<any>) => void, ...args: any[]]>;
|
|
72
|
+
};
|
|
34
73
|
export {};
|
package/esm/async.js
CHANGED
|
@@ -72,3 +72,105 @@ export const promiseAllObject = (promisesMap) => Promise.all(Object.values(promi
|
|
|
72
72
|
}
|
|
73
73
|
return resolvedMap;
|
|
74
74
|
});
|
|
75
|
+
/**
|
|
76
|
+
* Returns a debounced function that only runs after `delay` milliseconds
|
|
77
|
+
* of quiet-time. \
|
|
78
|
+
* The returned function also has a nice `.cancel()` method.
|
|
79
|
+
*
|
|
80
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#debounce
|
|
81
|
+
*/
|
|
82
|
+
/*#__NO_SIDE_EFFECTS__*/
|
|
83
|
+
export const debounce = (
|
|
84
|
+
/** The function to debounce */
|
|
85
|
+
func,
|
|
86
|
+
/** The delay, in milliseconds, to wait before running the function */
|
|
87
|
+
delay,
|
|
88
|
+
/** Whether to run the function at the start of the delay instead of the end */
|
|
89
|
+
immediate) => {
|
|
90
|
+
let timeout;
|
|
91
|
+
let _args;
|
|
92
|
+
let _this;
|
|
93
|
+
const debouncedFn = function (...args) {
|
|
94
|
+
_args = args;
|
|
95
|
+
_this = this;
|
|
96
|
+
immediate && !timeout && func.apply(_this, _args);
|
|
97
|
+
timeout && clearTimeout(timeout);
|
|
98
|
+
timeout = setTimeout(() => {
|
|
99
|
+
debouncedFn.cancel(true);
|
|
100
|
+
}, delay);
|
|
101
|
+
};
|
|
102
|
+
debouncedFn.cancel = (finish) => {
|
|
103
|
+
timeout && clearTimeout(timeout);
|
|
104
|
+
finish && timeout && func.apply(_this, _args);
|
|
105
|
+
timeout = undefined;
|
|
106
|
+
};
|
|
107
|
+
return debouncedFn;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Sugar to produce a dynamic debounced function that accepts its contents/behavior at call time.
|
|
111
|
+
*
|
|
112
|
+
* Usage:
|
|
113
|
+
* ```ts
|
|
114
|
+
* const myDebouncer = debounce.d(500);
|
|
115
|
+
* myDebouncer(() => { alert('Hello world'); });
|
|
116
|
+
* myDebouncer(() => { alert('I mean: Howdy world!'); });
|
|
117
|
+
* myDebouncer((name) => { alert('Wazzap ' + name); }, 'world');
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* Not documented in README as its usefulness is still uncertain.
|
|
121
|
+
*/
|
|
122
|
+
debounce.d = (delay, immediate) => debounce(function (fn, ...args) {
|
|
123
|
+
fn.apply(this, args);
|
|
124
|
+
}, delay, immediate);
|
|
125
|
+
/**
|
|
126
|
+
* Returns a throttled function that never runs more often than
|
|
127
|
+
* every `delay` milliseconds. \
|
|
128
|
+
* The returned function also has a nice `.finish()` method to reset the
|
|
129
|
+
* throttle timer
|
|
130
|
+
*
|
|
131
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#throttle
|
|
132
|
+
*/
|
|
133
|
+
/*#__NO_SIDE_EFFECTS__*/
|
|
134
|
+
export const throttle = (
|
|
135
|
+
/** The function to throttle */
|
|
136
|
+
func,
|
|
137
|
+
/** The delay, in milliseconds, to wait between invocations */
|
|
138
|
+
delay,
|
|
139
|
+
/** Whether to skip the first invocation instead of running it immediately */
|
|
140
|
+
skipFirst) => {
|
|
141
|
+
let timeout;
|
|
142
|
+
let throttled = 0;
|
|
143
|
+
let _args;
|
|
144
|
+
let _this;
|
|
145
|
+
const throttledFn = function (...args) {
|
|
146
|
+
_args = args;
|
|
147
|
+
_this = this;
|
|
148
|
+
if (!throttled) {
|
|
149
|
+
skipFirst ? throttled++ : func.apply(_this, _args);
|
|
150
|
+
timeout = setTimeout(throttledFn.finish, delay); // Go home TypeScript, you're drunk!
|
|
151
|
+
}
|
|
152
|
+
throttled++;
|
|
153
|
+
};
|
|
154
|
+
throttledFn.finish = (cancel) => {
|
|
155
|
+
timeout && clearTimeout(timeout);
|
|
156
|
+
!cancel && throttled && func.apply(_this, _args);
|
|
157
|
+
throttled = 0;
|
|
158
|
+
};
|
|
159
|
+
return throttledFn;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Sugar to produce a dynamic debounced function that accepts its contents/behavior at call time.
|
|
163
|
+
*
|
|
164
|
+
* Usage:
|
|
165
|
+
* ```ts
|
|
166
|
+
* const myThrottler = throttle.d(500);
|
|
167
|
+
* myThrottler(() => { alert('Hello world'); });
|
|
168
|
+
* myThrottler(() => { alert('I mean: Howdy world!'); });
|
|
169
|
+
* myThrottler((name) => { alert('Wazzap ' + name); }, 'world');
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* Not documented in README as its usefulness is still uncertain.
|
|
173
|
+
*/
|
|
174
|
+
throttle.d = (delay, skipFirst) => throttle(function (fn, ...args) {
|
|
175
|
+
fn.apply(this, args);
|
|
176
|
+
}, delay, skipFirst);
|
package/esm/errorhandling.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Error subclass for thrown values that got
|
|
3
|
-
* Error, with the thrown value as the `payload` property.
|
|
2
|
+
* Error subclass for thrown NON-Error values that got turned into an actual
|
|
3
|
+
* Error, with the original thrown value as the `payload` property.
|
|
4
4
|
*
|
|
5
5
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#aserror
|
|
6
6
|
*/
|
|
7
7
|
export declare class ErrorFromPayload extends Error {
|
|
8
|
+
/**
|
|
9
|
+
* This payload property is only set if the original `throw` value was NOT
|
|
10
|
+
* `instanceof Error`.
|
|
11
|
+
*
|
|
12
|
+
* In such cases it contains the thrown value as is, and the `message`
|
|
13
|
+
* property of this `ErrorFromPayload` instance is set to the `.toString()`
|
|
14
|
+
* representation of the payload.
|
|
15
|
+
*/
|
|
8
16
|
payload?: unknown;
|
|
9
17
|
constructor(payload: unknown);
|
|
10
18
|
name: string;
|
|
@@ -50,7 +58,7 @@ export type ResultTupleObj<T, E extends Error = Error> = SuccessResult<T> | Fail
|
|
|
50
58
|
* `[error, results]` tuple with the `result` and `error` also attached as
|
|
51
59
|
* named properties.
|
|
52
60
|
*
|
|
53
|
-
* Works on both promises and
|
|
61
|
+
* Works on both promises and (synchronous) callback functions.
|
|
54
62
|
*
|
|
55
63
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#resultcatch
|
|
56
64
|
*/
|
package/esm/errorhandling.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Error subclass for thrown values that got
|
|
3
|
-
* Error, with the thrown value as the `payload` property.
|
|
2
|
+
* Error subclass for thrown NON-Error values that got turned into an actual
|
|
3
|
+
* Error, with the original thrown value as the `payload` property.
|
|
4
4
|
*
|
|
5
5
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#aserror
|
|
6
6
|
*/
|
|
@@ -7,8 +7,12 @@ import { _PatchedCollator, _PatchedDateTimeFormat, _patchedDateToLocaleDateStrin
|
|
|
7
7
|
if (!Intl.Collator.supportedLocalesOf(['is']).length) {
|
|
8
8
|
Intl.Collator = _PatchedCollator;
|
|
9
9
|
String.prototype.localeCompare = _patchedStringLocaleCompare;
|
|
10
|
+
}
|
|
11
|
+
if (!Intl.NumberFormat.supportedLocalesOf(['is']).length) {
|
|
10
12
|
Intl.NumberFormat = _PatchedNumberFormat;
|
|
11
13
|
Number.prototype.toLocaleString = _patchedNumberToLocaleString;
|
|
14
|
+
}
|
|
15
|
+
if (!Intl.DateTimeFormat.supportedLocalesOf(['is']).length) {
|
|
12
16
|
Intl.DateTimeFormat = _PatchedDateTimeFormat;
|
|
13
17
|
Date.prototype.toLocaleString = _patchedDateToLocaleString;
|
|
14
18
|
Date.prototype.toLocaleDateString = _patchedDateToLocaleDateString;
|
package/esm/hooks.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a stable debounced function that invokes the supplied function
|
|
3
|
+
* after the specified delay. \
|
|
4
|
+
* When the component unmounts, any pending (debounced) calls are automatically cancelled.
|
|
5
|
+
*
|
|
6
|
+
* **NOTE:** The supplied callback does not need to be memoized. The debouncer
|
|
7
|
+
* will always invoke the last supplied version.
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usedebounced
|
|
10
|
+
*/
|
|
11
|
+
export declare const useDebounced: <A extends Array<unknown>>(
|
|
12
|
+
/** The function to debounce */
|
|
13
|
+
func: (...args: A) => void,
|
|
14
|
+
/** The delay, in milliseconds, to wait before running the function */
|
|
15
|
+
delay: number,
|
|
16
|
+
/** Whether to run the function at the start of the delay instead of the end */
|
|
17
|
+
immediate?: boolean) => ((...args: A) => void) & {
|
|
18
|
+
cancel(finish?: boolean): void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Returns a stable throttler function that throttles the supplied function.
|
|
22
|
+
*
|
|
23
|
+
* **NOTE:** The supplied callback does not need to be memoized. The throttler
|
|
24
|
+
* will always invoke the last supplied version.
|
|
25
|
+
*
|
|
26
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usethrottled
|
|
27
|
+
*/
|
|
28
|
+
export declare const useThrottled: <A extends Array<unknown>>(
|
|
29
|
+
/** The function to throttle */
|
|
30
|
+
func: (...args: A) => void,
|
|
31
|
+
/** The delay, in milliseconds, to wait between invocations. */
|
|
32
|
+
delay: number,
|
|
33
|
+
/** Whether to skip the first invocation instead of running it immediately. */
|
|
34
|
+
skipFirst?: boolean) => ((...args: A) => void) & {
|
|
35
|
+
finish(cancel?: boolean): void;
|
|
36
|
+
};
|
package/esm/hooks.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { debounce, throttle } from './async.js';
|
|
3
|
+
/**
|
|
4
|
+
* Returns a stable debounced function that invokes the supplied function
|
|
5
|
+
* after the specified delay. \
|
|
6
|
+
* When the component unmounts, any pending (debounced) calls are automatically cancelled.
|
|
7
|
+
*
|
|
8
|
+
* **NOTE:** The supplied callback does not need to be memoized. The debouncer
|
|
9
|
+
* will always invoke the last supplied version.
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usedebounced
|
|
12
|
+
*/
|
|
13
|
+
export const useDebounced = (
|
|
14
|
+
/** The function to debounce */
|
|
15
|
+
func,
|
|
16
|
+
/** The delay, in milliseconds, to wait before running the function */
|
|
17
|
+
delay,
|
|
18
|
+
/** Whether to run the function at the start of the delay instead of the end */
|
|
19
|
+
immediate) => {
|
|
20
|
+
const fn = useRef();
|
|
21
|
+
fn.current = func;
|
|
22
|
+
const debouncedFunc = useMemo(() => debounce((...args) => fn.current(...args), delay, immediate), [delay, immediate]);
|
|
23
|
+
useEffect(() => debouncedFunc.cancel, [debouncedFunc]);
|
|
24
|
+
return debouncedFunc;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Returns a stable throttler function that throttles the supplied function.
|
|
28
|
+
*
|
|
29
|
+
* **NOTE:** The supplied callback does not need to be memoized. The throttler
|
|
30
|
+
* will always invoke the last supplied version.
|
|
31
|
+
*
|
|
32
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usethrottled
|
|
33
|
+
*/
|
|
34
|
+
export const useThrottled = (
|
|
35
|
+
/** The function to throttle */
|
|
36
|
+
func,
|
|
37
|
+
/** The delay, in milliseconds, to wait between invocations. */
|
|
38
|
+
delay,
|
|
39
|
+
/** Whether to skip the first invocation instead of running it immediately. */
|
|
40
|
+
skipFirst) => {
|
|
41
|
+
const fn = useRef();
|
|
42
|
+
fn.current = func;
|
|
43
|
+
const throttledFunc = useMemo(() => throttle((...args) => fn.current(...args), delay, skipFirst), [delay, skipFirst]);
|
|
44
|
+
// NOTE: We don't need to run throttled.finish() on unmount, as the default behavior is no-op.
|
|
45
|
+
return throttledFunc;
|
|
46
|
+
};
|
package/esm/http.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const HTTP_103_EarlyHints = 103;
|
|
|
11
11
|
export declare const HTTP_200_OK = 200;
|
|
12
12
|
/** The request succeeded, and a new resource was created as a result. This is typically the response sent after POST or PUT requests. */
|
|
13
13
|
export declare const HTTP_201_Created = 201;
|
|
14
|
+
/** The request has been received but not yet acted upon. Another process or server handles the request. */
|
|
14
15
|
export declare const HTTP_202_Accepted = 202;
|
|
15
16
|
/** The returned metadata is not necessarily complete. */
|
|
16
17
|
export declare const HTTP_203_NonAuthoritativeInformation = 203;
|
package/esm/http.js
CHANGED
|
@@ -12,7 +12,7 @@ export const HTTP_103_EarlyHints = 103;
|
|
|
12
12
|
export const HTTP_200_OK = 200;
|
|
13
13
|
/** The request succeeded, and a new resource was created as a result. This is typically the response sent after POST or PUT requests. */
|
|
14
14
|
export const HTTP_201_Created = 201;
|
|
15
|
-
|
|
15
|
+
/** The request has been received but not yet acted upon. Another process or server handles the request. */
|
|
16
16
|
export const HTTP_202_Accepted = 202;
|
|
17
17
|
/** The returned metadata is not necessarily complete. */
|
|
18
18
|
export const HTTP_203_NonAuthoritativeInformation = 203;
|
package/esm/index.d.ts
CHANGED
package/fixIcelandicLocale.js
CHANGED
|
@@ -9,8 +9,12 @@ const fixIcelandicLocale_privates_js_1 = require("./fixIcelandicLocale.privates.
|
|
|
9
9
|
if (!Intl.Collator.supportedLocalesOf(['is']).length) {
|
|
10
10
|
Intl.Collator = fixIcelandicLocale_privates_js_1._PatchedCollator;
|
|
11
11
|
String.prototype.localeCompare = fixIcelandicLocale_privates_js_1._patchedStringLocaleCompare;
|
|
12
|
+
}
|
|
13
|
+
if (!Intl.NumberFormat.supportedLocalesOf(['is']).length) {
|
|
12
14
|
Intl.NumberFormat = fixIcelandicLocale_privates_js_1._PatchedNumberFormat;
|
|
13
15
|
Number.prototype.toLocaleString = fixIcelandicLocale_privates_js_1._patchedNumberToLocaleString;
|
|
16
|
+
}
|
|
17
|
+
if (!Intl.DateTimeFormat.supportedLocalesOf(['is']).length) {
|
|
14
18
|
Intl.DateTimeFormat = fixIcelandicLocale_privates_js_1._PatchedDateTimeFormat;
|
|
15
19
|
Date.prototype.toLocaleString = fixIcelandicLocale_privates_js_1._patchedDateToLocaleString;
|
|
16
20
|
Date.prototype.toLocaleDateString = fixIcelandicLocale_privates_js_1._patchedDateToLocaleDateString;
|
package/hooks.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a stable debounced function that invokes the supplied function
|
|
3
|
+
* after the specified delay. \
|
|
4
|
+
* When the component unmounts, any pending (debounced) calls are automatically cancelled.
|
|
5
|
+
*
|
|
6
|
+
* **NOTE:** The supplied callback does not need to be memoized. The debouncer
|
|
7
|
+
* will always invoke the last supplied version.
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usedebounced
|
|
10
|
+
*/
|
|
11
|
+
export declare const useDebounced: <A extends Array<unknown>>(
|
|
12
|
+
/** The function to debounce */
|
|
13
|
+
func: (...args: A) => void,
|
|
14
|
+
/** The delay, in milliseconds, to wait before running the function */
|
|
15
|
+
delay: number,
|
|
16
|
+
/** Whether to run the function at the start of the delay instead of the end */
|
|
17
|
+
immediate?: boolean) => ((...args: A) => void) & {
|
|
18
|
+
cancel(finish?: boolean): void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Returns a stable throttler function that throttles the supplied function.
|
|
22
|
+
*
|
|
23
|
+
* **NOTE:** The supplied callback does not need to be memoized. The throttler
|
|
24
|
+
* will always invoke the last supplied version.
|
|
25
|
+
*
|
|
26
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usethrottled
|
|
27
|
+
*/
|
|
28
|
+
export declare const useThrottled: <A extends Array<unknown>>(
|
|
29
|
+
/** The function to throttle */
|
|
30
|
+
func: (...args: A) => void,
|
|
31
|
+
/** The delay, in milliseconds, to wait between invocations. */
|
|
32
|
+
delay: number,
|
|
33
|
+
/** Whether to skip the first invocation instead of running it immediately. */
|
|
34
|
+
skipFirst?: boolean) => ((...args: A) => void) & {
|
|
35
|
+
finish(cancel?: boolean): void;
|
|
36
|
+
};
|
package/hooks.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useThrottled = exports.useDebounced = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const async_js_1 = require("./async.js");
|
|
6
|
+
/**
|
|
7
|
+
* Returns a stable debounced function that invokes the supplied function
|
|
8
|
+
* after the specified delay. \
|
|
9
|
+
* When the component unmounts, any pending (debounced) calls are automatically cancelled.
|
|
10
|
+
*
|
|
11
|
+
* **NOTE:** The supplied callback does not need to be memoized. The debouncer
|
|
12
|
+
* will always invoke the last supplied version.
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usedebounced
|
|
15
|
+
*/
|
|
16
|
+
const useDebounced = (
|
|
17
|
+
/** The function to debounce */
|
|
18
|
+
func,
|
|
19
|
+
/** The delay, in milliseconds, to wait before running the function */
|
|
20
|
+
delay,
|
|
21
|
+
/** Whether to run the function at the start of the delay instead of the end */
|
|
22
|
+
immediate) => {
|
|
23
|
+
const fn = (0, react_1.useRef)();
|
|
24
|
+
fn.current = func;
|
|
25
|
+
const debouncedFunc = (0, react_1.useMemo)(() => (0, async_js_1.debounce)((...args) => fn.current(...args), delay, immediate), [delay, immediate]);
|
|
26
|
+
(0, react_1.useEffect)(() => debouncedFunc.cancel, [debouncedFunc]);
|
|
27
|
+
return debouncedFunc;
|
|
28
|
+
};
|
|
29
|
+
exports.useDebounced = useDebounced;
|
|
30
|
+
/**
|
|
31
|
+
* Returns a stable throttler function that throttles the supplied function.
|
|
32
|
+
*
|
|
33
|
+
* **NOTE:** The supplied callback does not need to be memoized. The throttler
|
|
34
|
+
* will always invoke the last supplied version.
|
|
35
|
+
*
|
|
36
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#usethrottled
|
|
37
|
+
*/
|
|
38
|
+
const useThrottled = (
|
|
39
|
+
/** The function to throttle */
|
|
40
|
+
func,
|
|
41
|
+
/** The delay, in milliseconds, to wait between invocations. */
|
|
42
|
+
delay,
|
|
43
|
+
/** Whether to skip the first invocation instead of running it immediately. */
|
|
44
|
+
skipFirst) => {
|
|
45
|
+
const fn = (0, react_1.useRef)();
|
|
46
|
+
fn.current = func;
|
|
47
|
+
const throttledFunc = (0, react_1.useMemo)(() => (0, async_js_1.throttle)((...args) => fn.current(...args), delay, skipFirst), [delay, skipFirst]);
|
|
48
|
+
// NOTE: We don't need to run throttled.finish() on unmount, as the default behavior is no-op.
|
|
49
|
+
return throttledFunc;
|
|
50
|
+
};
|
|
51
|
+
exports.useThrottled = useThrottled;
|
package/http.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const HTTP_103_EarlyHints = 103;
|
|
|
11
11
|
export declare const HTTP_200_OK = 200;
|
|
12
12
|
/** The request succeeded, and a new resource was created as a result. This is typically the response sent after POST or PUT requests. */
|
|
13
13
|
export declare const HTTP_201_Created = 201;
|
|
14
|
+
/** The request has been received but not yet acted upon. Another process or server handles the request. */
|
|
14
15
|
export declare const HTTP_202_Accepted = 202;
|
|
15
16
|
/** The returned metadata is not necessarily complete. */
|
|
16
17
|
export declare const HTTP_203_NonAuthoritativeInformation = 203;
|
package/http.js
CHANGED
|
@@ -16,7 +16,7 @@ exports.HTTP_103_EarlyHints = 103;
|
|
|
16
16
|
exports.HTTP_200_OK = 200;
|
|
17
17
|
/** The request succeeded, and a new resource was created as a result. This is typically the response sent after POST or PUT requests. */
|
|
18
18
|
exports.HTTP_201_Created = 201;
|
|
19
|
-
|
|
19
|
+
/** The request has been received but not yet acted upon. Another process or server handles the request. */
|
|
20
20
|
exports.HTTP_202_Accepted = 202;
|
|
21
21
|
/** The returned metadata is not necessarily complete. */
|
|
22
22
|
exports.HTTP_203_NonAuthoritativeInformation = 203;
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reykjavik/webtools",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Misc. JS/TS helpers used by Reykjavík City's web dev teams.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": "ssh://git@github.com:reykjavikcity/webtools.git",
|
|
@@ -44,6 +44,10 @@
|
|
|
44
44
|
"**/fixIcelandicLocale.js"
|
|
45
45
|
],
|
|
46
46
|
"exports": {
|
|
47
|
+
"./hooks": {
|
|
48
|
+
"import": "./esm/hooks.js",
|
|
49
|
+
"require": "./hooks.js"
|
|
50
|
+
},
|
|
47
51
|
".": {
|
|
48
52
|
"import": "./esm/index.js",
|
|
49
53
|
"require": "./index.js"
|