@reykjavik/webtools 0.2.7 → 0.2.9
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 +204 -14
- package/async.d.ts +39 -0
- package/async.js +105 -1
- package/esm/async.d.ts +39 -0
- package/esm/async.js +102 -0
- package/esm/hooks.d.ts +36 -0
- package/esm/hooks.js +46 -0
- package/esm/index.d.ts +1 -0
- package/esm/vanillaExtract.d.ts +4 -1
- package/esm/vanillaExtract.js +4 -0
- package/hooks.d.ts +36 -0
- package/hooks.js +51 -0
- package/index.d.ts +1 -0
- package/package.json +5 -1
- package/vanillaExtract.d.ts +4 -1
- package/vanillaExtract.js +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
- ... <!-- Add new lines here. -->
|
|
6
6
|
|
|
7
|
+
## 0.2.9
|
|
8
|
+
|
|
9
|
+
_2025-09-30_
|
|
10
|
+
|
|
11
|
+
- `@reykjavik/webtools/next/vanillaExtract`:
|
|
12
|
+
- feat: Make `vanillaVars` return a type-safe `setVars()` helper to avoid
|
|
13
|
+
offending VSCode's CSS syntax parser too much.
|
|
14
|
+
|
|
15
|
+
## 0.2.8
|
|
16
|
+
|
|
17
|
+
_2025-09-17_
|
|
18
|
+
|
|
19
|
+
- `@reykjavik/webtools/async`:
|
|
20
|
+
- feat: Add `debounce` and `throttle` helpers
|
|
21
|
+
- `@reykjavik/webtools/hooks` (new module):
|
|
22
|
+
- feat: Add `useDebounced` and `useThrottled` hooks
|
|
23
|
+
|
|
7
24
|
## 0.2.7
|
|
8
25
|
|
|
9
26
|
_2025-09-01_
|
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,
|
|
@@ -660,9 +847,11 @@ editor), but there's a brief summary:
|
|
|
660
847
|
`scriptUrl` prop).
|
|
661
848
|
- `scriptUrl?: string` — The full SiteImprove analytics script URL.
|
|
662
849
|
(alternative to `accountId` prop).
|
|
663
|
-
- `hasConsented?: boolean` — Manual GDPR 'analytics' consent flag.
|
|
664
|
-
opt-out, but defers to
|
|
665
|
-
they are available.
|
|
850
|
+
- `hasConsented?: boolean` — Manual GDPR 'analytics' consent flag. A `false`
|
|
851
|
+
value allows hard opt-out, but defers to
|
|
852
|
+
[`CookieHubProvider` values](#usecookiehubconsent) if they are available.
|
|
853
|
+
Defaults to `undefined` which means "ask CookieHub if available, otherwise
|
|
854
|
+
no".
|
|
666
855
|
- `onLoad?: (e: unknown) => void` — Fires when the script has loaded.
|
|
667
856
|
- `onError?: (e: unknown) => void` — Fires if loading the script failed.
|
|
668
857
|
|
|
@@ -999,21 +1188,21 @@ import {
|
|
|
999
1188
|
vanillaGlobal,
|
|
1000
1189
|
} from '@reykjavik/webtools/vanillaExtract';
|
|
1001
1190
|
|
|
1002
|
-
|
|
1191
|
+
const { varPrimaryColor, varSecondaryColor, setVars } = vanillaVars(
|
|
1003
1192
|
'primaryColor',
|
|
1004
1193
|
'secondaryColor'
|
|
1005
1194
|
);
|
|
1006
1195
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
}
|
|
1016
|
-
`);
|
|
1196
|
+
export { varPrimaryColor, varSecondaryColor };
|
|
1197
|
+
|
|
1198
|
+
export const wrapper = vanillaClass(`
|
|
1199
|
+
${setVars({
|
|
1200
|
+
primaryColor: '#ff0000',
|
|
1201
|
+
secondaryColor: '#00ff00',
|
|
1202
|
+
})}
|
|
1203
|
+
background-color: var(${varPrimaryColor});
|
|
1204
|
+
color: var(${varSecondaryColor});
|
|
1205
|
+
`);
|
|
1017
1206
|
```
|
|
1018
1207
|
|
|
1019
1208
|
…and then in your component:
|
|
@@ -1026,6 +1215,7 @@ import * as cl from './someFile.css.ts';
|
|
|
1026
1215
|
export function MyComponent() {
|
|
1027
1216
|
return (
|
|
1028
1217
|
<div
|
|
1218
|
+
className={cl.wrapper}
|
|
1029
1219
|
style={{
|
|
1030
1220
|
[cl.varPrimaryColor]: 'yellow',
|
|
1031
1221
|
[cl.varSecondaryColor]: 'blue',
|
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/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/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/index.d.ts
CHANGED
package/esm/vanillaExtract.d.ts
CHANGED
|
@@ -37,5 +37,8 @@ export declare function vanillaClass(debugId: string, css: string | ClassNameCal
|
|
|
37
37
|
*
|
|
38
38
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#vanillacvars
|
|
39
39
|
*/
|
|
40
|
-
export declare const vanillaVars: <T extends string>(...varNames: Array<T>) => Record<`var${Capitalize<T>}`, string
|
|
40
|
+
export declare const vanillaVars: <T extends string>(...varNames: Array<T>) => Record<`var${Capitalize<T>}`, string> & {
|
|
41
|
+
/** Allows initializing all or some of the variables in CSS, without offending VSCode's CSS syntax parser too much. */
|
|
42
|
+
setVars: (vars: Partial<Record<T, unknown>>) => string;
|
|
43
|
+
};
|
|
41
44
|
export {};
|
package/esm/vanillaExtract.js
CHANGED
|
@@ -36,8 +36,12 @@ export function vanillaClass(cssOrDebugId, css) {
|
|
|
36
36
|
export const vanillaVars = (...varNames) => {
|
|
37
37
|
const id = vanillaClass(``);
|
|
38
38
|
const vars = {};
|
|
39
|
+
vars.setVars = (vars) => Object.entries(vars)
|
|
40
|
+
.map(([name, value]) => `--${id}--${name}: ${value || ''};`)
|
|
41
|
+
.join('\n');
|
|
39
42
|
for (const name of varNames) {
|
|
40
43
|
vars[`var${capitalize(name)}`] = `--${id}--${name}`;
|
|
41
44
|
}
|
|
42
45
|
return vars;
|
|
43
46
|
};
|
|
47
|
+
const { varColor, varBg, setVars } = vanillaVars('color', 'bg');
|
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/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.9",
|
|
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"
|
package/vanillaExtract.d.ts
CHANGED
|
@@ -37,5 +37,8 @@ export declare function vanillaClass(debugId: string, css: string | ClassNameCal
|
|
|
37
37
|
*
|
|
38
38
|
* @see https://github.com/reykjavikcity/webtools/blob/v0.2/README.md#vanillacvars
|
|
39
39
|
*/
|
|
40
|
-
export declare const vanillaVars: <T extends string>(...varNames: Array<T>) => Record<`var${Capitalize<T>}`, string
|
|
40
|
+
export declare const vanillaVars: <T extends string>(...varNames: Array<T>) => Record<`var${Capitalize<T>}`, string> & {
|
|
41
|
+
/** Allows initializing all or some of the variables in CSS, without offending VSCode's CSS syntax parser too much. */
|
|
42
|
+
setVars: (vars: Partial<Record<T, unknown>>) => string;
|
|
43
|
+
};
|
|
41
44
|
export {};
|
package/vanillaExtract.js
CHANGED
|
@@ -42,9 +42,13 @@ function vanillaClass(cssOrDebugId, css) {
|
|
|
42
42
|
const vanillaVars = (...varNames) => {
|
|
43
43
|
const id = vanillaClass(``);
|
|
44
44
|
const vars = {};
|
|
45
|
+
vars.setVars = (vars) => Object.entries(vars)
|
|
46
|
+
.map(([name, value]) => `--${id}--${name}: ${value || ''};`)
|
|
47
|
+
.join('\n');
|
|
45
48
|
for (const name of varNames) {
|
|
46
49
|
vars[`var${(0, hanna_utils_1.capitalize)(name)}`] = `--${id}--${name}`;
|
|
47
50
|
}
|
|
48
51
|
return vars;
|
|
49
52
|
};
|
|
50
53
|
exports.vanillaVars = vanillaVars;
|
|
54
|
+
const { varColor, varBg, setVars } = (0, exports.vanillaVars)('color', 'bg');
|