@sv443-network/userutils 0.3.0 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @sv443-network/userutils
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 231a79c: Refactored code and documentation and added new functions:
8
+ - mapRange() to map a number from one range to the same spot in another range
9
+ - randRange() to generate a random number between a min and max boundary
10
+ - randomItem() to return a random item from an array
11
+ - randomItemIndex() to return a tuple of a random item and its index from an array
12
+ - takeRandomItem() to return a random item from an array and mutate it to remove the item
13
+ - randomizeArray() to return a copy of the array with its items in a random order
14
+
15
+ ### Patch Changes
16
+
17
+ - 7edf837: decrease npm bundle size
18
+
3
19
  ## 0.3.0
4
20
 
5
21
  ### Minor Changes
package/README.md CHANGED
@@ -1,28 +1,41 @@
1
+ <div style="text-align: center;" align="center">
2
+
1
3
  ## UserUtils
2
4
  Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more.
3
- Contains builtin TypeScript declarations.
5
+ Contains builtin TypeScript declarations. Webpack compatible and supports ESM and CJS.
4
6
 
7
+ </div>
5
8
  <br>
6
9
 
7
10
  ## Table of Contents:
8
11
  - [Installation](#installation)
9
12
  - [Features](#features)
10
- - [onSelector()](#onselector) - call a listener once a selector is found in the DOM
11
- - [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
12
- - [getSelectorMap()](#getselectormap) - returns all currently registered selectors, listeners and options
13
- - [autoPlural()](#autoplural) - automatically pluralize a string
14
- - [clamp()](#clamp) - clamp a number between a min and max value
15
- - [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time
16
- - [debounce()](#debounce) - call a function only once, after a given amount of time
17
- - [getUnsafeWindow()](#getunsafewindow) - get the unsafeWindow object or fall back to the regular window object
18
- - [insertAfter()](#insertafter) - insert an element as a sibling after another element
19
- - [addParent()](#addparent) - add a parent element around another element
20
- - [addGlobalStyle()](#addglobalstyle) - add a global style to the page
21
- - [preloadImages()](#preloadimages) - preload images into the browser cache for faster loading later on
22
- - [fetchAdvanced()](#fetchadvanced) - wrapper around the fetch API with a timeout option
23
- - [openInNewTab()](#openinnewtab) - open a link in a new tab
24
- - [interceptEvent()](#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
25
- - [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
13
+ - [DOM:](#dom)
14
+ - [onSelector()](#onselector) - call a listener once a selector is found in the DOM
15
+ - [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
16
+ - [getSelectorMap()](#getselectormap) - returns all currently registered selectors, listeners and options
17
+ - [getUnsafeWindow()](#getunsafewindow) - get the unsafeWindow object or fall back to the regular window object
18
+ - [insertAfter()](#insertafter) - insert an element as a sibling after another element
19
+ - [addParent()](#addparent) - add a parent element around another element
20
+ - [addGlobalStyle()](#addglobalstyle) - add a global style to the page
21
+ - [preloadImages()](#preloadimages) - preload images into the browser cache for faster loading later on
22
+ - [openInNewTab()](#openinnewtab) - open a link in a new tab
23
+ - [interceptEvent()](#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
24
+ - [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
25
+ - [Math:](#math)
26
+ - [clamp()](#clamp) - clamp a number between a min and max value
27
+ - [mapRange()](#maprange) - map a number from one range to the same spot in another range
28
+ - [randRange()](#randrange) - generate a random number between a min and max boundary
29
+ - [Misc:](#misc)
30
+ - [autoPlural()](#autoplural) - automatically pluralize a string
31
+ - [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time
32
+ - [debounce()](#debounce) - call a function only once, after a given amount of time
33
+ - [fetchAdvanced()](#fetchadvanced) - wrapper around the fetch API with a timeout option
34
+ - [Arrays:](#arrays)
35
+ - [randomItem()](#randomitem) - returns a random item from an array
36
+ - [randomItemIndex()](#randomitemindex) - returns a tuple of a random item and its index from an array
37
+ - [takeRandomItem()](#takerandomitem) - returns a random item from an array and mutates it to remove the item
38
+ - [randomizeArray()](#randomizearray) - returns a copy of the array with its items in a random order
26
39
  - [License](#license)
27
40
 
28
41
  <br><br>
@@ -55,6 +68,8 @@ If you like using this library, please consider [supporting development](https:/
55
68
 
56
69
  ## Features:
57
70
 
71
+ ## DOM:
72
+
58
73
  ### onSelector()
59
74
  Usage:
60
75
  ```ts
@@ -181,86 +196,6 @@ const selectorMap = getSelectorMap();
181
196
 
182
197
  <br>
183
198
 
184
- ### autoPlural()
185
- Usage: `autoPlural(str: string, num: number | Array | NodeList): string`
186
-
187
- Automatically pluralizes a string if the given number is not 1.
188
- If an array or NodeList is passed, the length of it will be used.
189
-
190
- <details><summary><b>Example - click to view</b></summary>
191
-
192
- ```ts
193
- autoPlural("apple", 0); // "apples"
194
- autoPlural("apple", 1); // "apple"
195
- autoPlural("apple", 2); // "apples"
196
-
197
- autoPlural("apple", [1]); // "apple"
198
- autoPlural("apple", [1, 2]); // "apples"
199
-
200
- const items = [1, 2, 3, 4, "foo", "bar"];
201
- console.log(`Found ${items.length} ${autoPlural("item", items)}`); // "Found 6 items"
202
- ```
203
-
204
- </details>
205
-
206
- <br>
207
-
208
- ### clamp()
209
- Usage: `clamp(num: number, min: number, max: number): number`
210
-
211
- Clamps a number between a min and max value.
212
-
213
- <details><summary><b>Example - click to view</b></summary>
214
-
215
- ```ts
216
- clamp(5, 0, 10); // 5
217
- clamp(-1, 0, 10); // 0
218
- clamp(7, 0, 10); // 7
219
- clamp(Infinity, 0, 10); // 10
220
- ```
221
-
222
- </details>
223
-
224
- <br>
225
-
226
- ### pauseFor()
227
- Usage: `pauseFor(ms: number): Promise<void>`
228
-
229
- Pauses async execution for a given amount of time.
230
-
231
- <details><summary><b>Example - click to view</b></summary>
232
-
233
- ```ts
234
- async function run() {
235
- console.log("Hello");
236
- await pauseFor(3000); // waits for 3 seconds
237
- console.log("World");
238
- }
239
- ```
240
-
241
- </details>
242
-
243
- <br>
244
-
245
- ### debounce()
246
- Usage: `debounce(func: Function, timeout?: number): Function`
247
-
248
- Debounces a function, meaning that it will only be called once after a given amount of time.
249
- This is very useful for functions that are called repeatedly, like event listeners, to remove extraneous calls.
250
- The timeout will default to 300ms if left undefined.
251
-
252
- <details><summary><b>Example - click to view</b></summary>
253
-
254
- ```ts
255
- window.addEventListener("resize", debounce((event) => {
256
- console.log("Window was resized:", event);
257
- }, 500)); // 500ms timeout
258
- ```
259
-
260
- </details>
261
-
262
- <br>
263
-
264
199
  ### getUnsafeWindow()
265
200
  Usage: `getUnsafeWindow(): Window`
266
201
 
@@ -375,6 +310,191 @@ preloadImages([
375
310
 
376
311
  <br>
377
312
 
313
+ ### openInNewTab()
314
+ Usage: `openInNewTab(url: string): void`
315
+
316
+ Creates an invisible anchor with a `_blank` target and clicks it.
317
+ Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
318
+ This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
319
+
320
+ ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
321
+
322
+ <details><summary><b>Example - click to view</b></summary>
323
+
324
+ ```ts
325
+ document.querySelector("#my-button").addEventListener("click", () => {
326
+ openInNewTab("https://example.org/");
327
+ });
328
+ ```
329
+
330
+ </details>
331
+
332
+ <br>
333
+
334
+ ### interceptEvent()
335
+ Usage: `interceptEvent(eventObject: EventTarget, eventName: string, predicate: () => boolean): void`
336
+
337
+ Intercepts all events dispatched on the `eventObject` and prevents the listeners from being called as long as the predicate function returns a truthy value.
338
+ Calling this function will set the `Error.stackTraceLimit` to 1000 (if it's not already higher) to ensure the stack trace is preserved.
339
+
340
+ ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
341
+
342
+ <details><summary><b>Example - click to view</b></summary>
343
+
344
+ ```ts
345
+ interceptEvent(document.body, "click", () => {
346
+ return true; // prevent all click events on the body element
347
+ });
348
+ ```
349
+
350
+ </details>
351
+
352
+ <br>
353
+
354
+ ### interceptWindowEvent()
355
+ Usage: `interceptWindowEvent(eventName: string, predicate: () => boolean): void`
356
+
357
+ Intercepts all events dispatched on the `window` object and prevents the listeners from being called as long as the predicate function returns a truthy value.
358
+ This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).
359
+
360
+ ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
361
+
362
+ <details><summary><b>Example - click to view</b></summary>
363
+
364
+ ```ts
365
+ interceptWindowEvent("beforeunload", () => {
366
+ return true; // prevent the pesky "Are you sure you want to leave this page?" popup
367
+ });
368
+ ```
369
+
370
+ </details>
371
+
372
+ <br><br>
373
+
374
+ ## Math:
375
+
376
+ ### clamp()
377
+ Usage: `clamp(num: number, min: number, max: number): number`
378
+
379
+ Clamps a number between a min and max value.
380
+
381
+ <details><summary><b>Example - click to view</b></summary>
382
+
383
+ ```ts
384
+ clamp(5, 0, 10); // 5
385
+ clamp(-1, 0, 10); // 0
386
+ clamp(7, 0, 10); // 7
387
+ clamp(Infinity, 0, 10); // 10
388
+ ```
389
+
390
+ </details>
391
+
392
+ <br>
393
+
394
+ ### mapRange()
395
+ Usage: `mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number`
396
+
397
+ Maps a number from one range to the spot it would be in another range.
398
+
399
+ <details><summary><b>Example - click to view</b></summary>
400
+
401
+ ```ts
402
+ mapRange(5, 0, 10, 0, 100); // 50
403
+ mapRange(5, 0, 10, 0, 50); // 25
404
+ // to calculate a percentage from arbitrary values, use 0 and 100 as the second range:
405
+ mapRange(4, 0, 13, 0, 100); // 30.76923076923077
406
+ ```
407
+
408
+ </details>
409
+
410
+ <br>
411
+
412
+ ### randRange()
413
+ Usages:
414
+ ```ts
415
+ randRange(min: number, max: number): number
416
+ randRange(max: number): number
417
+ ```
418
+
419
+ Returns a random number between `min` and `max` (inclusive).
420
+ If only one argument is passed, it will be used as the `max` value and `min` will be set to 0.
421
+
422
+ <details><summary><b>Example - click to view</b></summary>
423
+
424
+ ```ts
425
+ randRange(0, 10); // 4
426
+ randRange(10, 20); // 17
427
+ randRange(10); // 7
428
+ ```
429
+
430
+ </details>
431
+
432
+ <br><br>
433
+
434
+ ## Misc:
435
+
436
+ ### autoPlural()
437
+ Usage: `autoPlural(str: string, num: number | Array | NodeList): string`
438
+
439
+ Automatically pluralizes a string if the given number is not 1.
440
+ If an array or NodeList is passed, the length of it will be used.
441
+
442
+ <details><summary><b>Example - click to view</b></summary>
443
+
444
+ ```ts
445
+ autoPlural("apple", 0); // "apples"
446
+ autoPlural("apple", 1); // "apple"
447
+ autoPlural("apple", 2); // "apples"
448
+
449
+ autoPlural("apple", [1]); // "apple"
450
+ autoPlural("apple", [1, 2]); // "apples"
451
+
452
+ const items = [1, 2, 3, 4, "foo", "bar"];
453
+ console.log(`Found ${items.length} ${autoPlural("item", items)}`); // "Found 6 items"
454
+ ```
455
+
456
+ </details>
457
+
458
+ <br>
459
+
460
+ ### pauseFor()
461
+ Usage: `pauseFor(ms: number): Promise<void>`
462
+
463
+ Pauses async execution for a given amount of time.
464
+
465
+ <details><summary><b>Example - click to view</b></summary>
466
+
467
+ ```ts
468
+ async function run() {
469
+ console.log("Hello");
470
+ await pauseFor(3000); // waits for 3 seconds
471
+ console.log("World");
472
+ }
473
+ ```
474
+
475
+ </details>
476
+
477
+ <br>
478
+
479
+ ### debounce()
480
+ Usage: `debounce(func: Function, timeout?: number): Function`
481
+
482
+ Debounces a function, meaning that it will only be called once after a given amount of time.
483
+ This is very useful for functions that are called repeatedly, like event listeners, to remove extraneous calls.
484
+ The timeout will default to 300ms if left undefined.
485
+
486
+ <details><summary><b>Example - click to view</b></summary>
487
+
488
+ ```ts
489
+ window.addEventListener("resize", debounce((event) => {
490
+ console.log("Window was resized:", event);
491
+ }, 500)); // 500ms timeout
492
+ ```
493
+
494
+ </details>
495
+
496
+ <br>
497
+
378
498
  ### fetchAdvanced()
379
499
  Usage:
380
500
  ```ts
@@ -403,67 +523,82 @@ fetchAdvanced("https://api.example.org/data", {
403
523
 
404
524
  </details>
405
525
 
406
- <br>
526
+ <br><br>
407
527
 
408
- ### openInNewTab()
409
- Usage: `openInNewTab(url: string): void`
410
-
411
- Creates an invisible anchor with a `_blank` target and clicks it.
412
- Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
413
- This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
528
+ ## Arrays:
529
+
530
+ ### randomItem()
531
+ Usage: `randomItem(array: Array): any`
414
532
 
415
- ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
533
+ Returns a random item from an array.
534
+ Returns undefined if the array is empty.
416
535
 
417
536
  <details><summary><b>Example - click to view</b></summary>
418
537
 
419
538
  ```ts
420
- document.querySelector("#my-button").addEventListener("click", () => {
421
- openInNewTab("https://example.org/");
422
- });
539
+ randomItem(["foo", "bar", "baz"]); // "bar"
540
+ randomItem([ ]); // undefined
423
541
  ```
424
542
 
425
543
  </details>
426
544
 
427
545
  <br>
428
546
 
429
- ### interceptEvent()
430
- Usage: `interceptEvent(eventObject: EventTarget, eventName: string, predicate: () => boolean): void`
547
+ ### randomItemIndex()
548
+ Usage: `randomItemIndex(array: Array): [item: any, index: number]`
431
549
 
432
- Intercepts all events dispatched on the `eventObject` and prevents the listeners from being called as long as the predicate function returns a truthy value.
433
- Calling this function will set the `Error.stackTraceLimit` to 1000 (if it's not already higher) to ensure the stack trace is preserved.
434
-
435
- ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
550
+ Returns a tuple of a random item and its index from an array.
551
+ If the array is empty, it will return undefined for both values.
436
552
 
437
553
  <details><summary><b>Example - click to view</b></summary>
438
554
 
439
555
  ```ts
440
- interceptEvent(document.body, "click", () => {
441
- return true; // prevent all click events on the body element
442
- });
556
+ randomItemIndex(["foo", "bar", "baz"]); // ["bar", 1]
557
+ randomItemIndex([ ]); // [undefined, undefined]
558
+ // using array destructuring:
559
+ const [item, index] = randomItemIndex(["foo", "bar", "baz"]);
560
+ // or if you only want the index:
561
+ const [, index] = randomItemIndex(["foo", "bar", "baz"]);
443
562
  ```
444
563
 
445
564
  </details>
446
565
 
447
566
  <br>
448
567
 
449
- ### interceptWindowEvent()
450
- Usage: `interceptWindowEvent(eventName: string, predicate: () => boolean): void`
568
+ ### takeRandomItem()
569
+ Usage: `takeRandomItem(array: Array): any`
451
570
 
452
- Intercepts all events dispatched on the `window` object and prevents the listeners from being called as long as the predicate function returns a truthy value.
453
- This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).
571
+ Returns a random item from an array and mutates the array by removing the item.
572
+ Returns undefined if the array is empty.
454
573
 
455
- ⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
574
+ <details><summary><b>Example - click to view</b></summary>
575
+
576
+ ```ts
577
+ const arr = ["foo", "bar", "baz"];
578
+ takeRandomItem(arr); // "bar"
579
+ console.log(arr); // ["foo", "baz"]
580
+ ```
581
+
582
+ </details>
583
+
584
+ <br>
585
+
586
+ ### randomizeArray()
587
+ Usage: `randomizeArray(array: Array): Array`
588
+
589
+ Returns a copy of the array with its items in a random order.
590
+ If the array is empty, the originally passed array will be returned.
456
591
 
457
592
  <details><summary><b>Example - click to view</b></summary>
458
593
 
459
594
  ```ts
460
- interceptWindowEvent("beforeunload", () => {
461
- return true; // prevent the pesky "Are you sure you want to leave this page?" popup
462
- });
595
+ randomizeArray([1, 2, 3, 4, 5, 6]); // [3, 1, 5, 2, 4, 6]
463
596
  ```
464
597
 
465
598
  </details>
466
599
 
600
+ <br>
601
+
467
602
 
468
603
  <br><br>
469
604
 
package/dist/index.d.mts CHANGED
@@ -1,46 +1,3 @@
1
- type InitOnSelectorOpts = {
2
- /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
3
- attributes?: boolean;
4
- /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
5
- characterData?: boolean;
6
- };
7
- type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
8
- type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
9
- /** Whether to use `querySelectorAll()` instead - default is false */
10
- all?: false;
11
- /** Gets called whenever the selector was found in the DOM */
12
- listener: (element: TElem) => void;
13
- };
14
- type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
15
- /** Whether to use `querySelectorAll()` instead - default is false */
16
- all: true;
17
- /** Gets called whenever the selector was found in the DOM */
18
- listener: (elements: NodeListOf<TElem>) => void;
19
- };
20
- type SelectorOptsBase = {
21
- /** Whether to call the listener continuously instead of once - default is false */
22
- continuous?: boolean;
23
- };
24
- type FetchAdvancedOpts = RequestInit & Partial<{
25
- /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
26
- timeout: number;
27
- }>;
28
-
29
- /**
30
- * Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
31
- * @param word A word in singular form, to auto-convert to plural
32
- * @param num If this is an array or NodeList, the amount of items is used
33
- */
34
- declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
35
- /** Ensures the passed `value` always stays between `min` and `max` */
36
- declare function clamp(value: number, min: number, max: number): number;
37
- /** Pauses async execution for the specified time in ms */
38
- declare function pauseFor(time: number): Promise<unknown>;
39
- /**
40
- * Calls the passed `func` after the specified `timeout` in ms.
41
- * Any subsequent calls to this function will reset the timer and discard previous calls.
42
- */
43
- declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
44
1
  /**
45
2
  * Returns `unsafeWindow` if the `@grant unsafeWindow` is given, otherwise falls back to the regular `window`
46
3
  */
@@ -67,8 +24,6 @@ declare function addGlobalStyle(style: string): void;
67
24
  * @returns Returns an array of `PromiseSettledResult` - each resolved result will contain the loaded image element, while each rejected result will contain an `ErrorEvent`
68
25
  */
69
26
  declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<PromiseSettledResult<unknown>[]>;
70
- /** Calls the fetch API with special options like a timeout */
71
- declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
72
27
  /**
73
28
  * Creates an invisible anchor with a `_blank` target and clicks it.
74
29
  * Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
@@ -89,6 +44,62 @@ declare function interceptEvent<TEvtObj extends EventTarget>(eventObject: TEvtOb
89
44
  */
90
45
  declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate: () => boolean): void;
91
46
 
47
+ /** Ensures the passed `value` always stays between `min` and `max` */
48
+ declare function clamp(value: number, min: number, max: number): number;
49
+ /**
50
+ * Transforms the value parameter from the numerical range `range_1_min-range_1_max` to the numerical range `range_2_min-range_2_max`
51
+ * For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
52
+ */
53
+ declare function mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number;
54
+ /** Returns a random number between `min` and `max` (inclusive) */
55
+ declare function randRange(min: number, max: number): number;
56
+ /** Returns a random number between 0 and `max` (inclusive) */
57
+ declare function randRange(max: number): number;
58
+
59
+ type InitOnSelectorOpts = {
60
+ /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
61
+ attributes?: boolean;
62
+ /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
63
+ characterData?: boolean;
64
+ };
65
+ type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
66
+ type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
67
+ /** Whether to use `querySelectorAll()` instead - default is false */
68
+ all?: false;
69
+ /** Gets called whenever the selector was found in the DOM */
70
+ listener: (element: TElem) => void;
71
+ };
72
+ type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
73
+ /** Whether to use `querySelectorAll()` instead - default is false */
74
+ all: true;
75
+ /** Gets called whenever the selector was found in the DOM */
76
+ listener: (elements: NodeListOf<TElem>) => void;
77
+ };
78
+ type SelectorOptsBase = {
79
+ /** Whether to call the listener continuously instead of once - default is false */
80
+ continuous?: boolean;
81
+ };
82
+ type FetchAdvancedOpts = RequestInit & Partial<{
83
+ /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
84
+ timeout: number;
85
+ }>;
86
+
87
+ /**
88
+ * Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
89
+ * @param word A word in singular form, to auto-convert to plural
90
+ * @param num If this is an array or NodeList, the amount of items is used
91
+ */
92
+ declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
93
+ /** Pauses async execution for the specified time in ms */
94
+ declare function pauseFor(time: number): Promise<unknown>;
95
+ /**
96
+ * Calls the passed `func` after the specified `timeout` in ms.
97
+ * Any subsequent calls to this function will reset the timer and discard previous calls.
98
+ */
99
+ declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
100
+ /** Calls the fetch API with special options like a timeout */
101
+ declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
102
+
92
103
  /**
93
104
  * Calls the `listener` as soon as the `selector` exists in the DOM.
94
105
  * Listeners are deleted when they are called once, unless `options.continuous` is set.
@@ -111,4 +122,4 @@ declare function initOnSelector(opts?: InitOnSelectorOpts): void;
111
122
  /** Returns all currently registered selectors, as a map of selector strings to their associated options */
112
123
  declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
113
124
 
114
- export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
125
+ export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, removeOnSelector };
package/dist/index.d.ts CHANGED
@@ -1,46 +1,3 @@
1
- type InitOnSelectorOpts = {
2
- /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
3
- attributes?: boolean;
4
- /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
5
- characterData?: boolean;
6
- };
7
- type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
8
- type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
9
- /** Whether to use `querySelectorAll()` instead - default is false */
10
- all?: false;
11
- /** Gets called whenever the selector was found in the DOM */
12
- listener: (element: TElem) => void;
13
- };
14
- type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
15
- /** Whether to use `querySelectorAll()` instead - default is false */
16
- all: true;
17
- /** Gets called whenever the selector was found in the DOM */
18
- listener: (elements: NodeListOf<TElem>) => void;
19
- };
20
- type SelectorOptsBase = {
21
- /** Whether to call the listener continuously instead of once - default is false */
22
- continuous?: boolean;
23
- };
24
- type FetchAdvancedOpts = RequestInit & Partial<{
25
- /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
26
- timeout: number;
27
- }>;
28
-
29
- /**
30
- * Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
31
- * @param word A word in singular form, to auto-convert to plural
32
- * @param num If this is an array or NodeList, the amount of items is used
33
- */
34
- declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
35
- /** Ensures the passed `value` always stays between `min` and `max` */
36
- declare function clamp(value: number, min: number, max: number): number;
37
- /** Pauses async execution for the specified time in ms */
38
- declare function pauseFor(time: number): Promise<unknown>;
39
- /**
40
- * Calls the passed `func` after the specified `timeout` in ms.
41
- * Any subsequent calls to this function will reset the timer and discard previous calls.
42
- */
43
- declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
44
1
  /**
45
2
  * Returns `unsafeWindow` if the `@grant unsafeWindow` is given, otherwise falls back to the regular `window`
46
3
  */
@@ -67,8 +24,6 @@ declare function addGlobalStyle(style: string): void;
67
24
  * @returns Returns an array of `PromiseSettledResult` - each resolved result will contain the loaded image element, while each rejected result will contain an `ErrorEvent`
68
25
  */
69
26
  declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<PromiseSettledResult<unknown>[]>;
70
- /** Calls the fetch API with special options like a timeout */
71
- declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
72
27
  /**
73
28
  * Creates an invisible anchor with a `_blank` target and clicks it.
74
29
  * Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
@@ -89,6 +44,62 @@ declare function interceptEvent<TEvtObj extends EventTarget>(eventObject: TEvtOb
89
44
  */
90
45
  declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate: () => boolean): void;
91
46
 
47
+ /** Ensures the passed `value` always stays between `min` and `max` */
48
+ declare function clamp(value: number, min: number, max: number): number;
49
+ /**
50
+ * Transforms the value parameter from the numerical range `range_1_min-range_1_max` to the numerical range `range_2_min-range_2_max`
51
+ * For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
52
+ */
53
+ declare function mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number;
54
+ /** Returns a random number between `min` and `max` (inclusive) */
55
+ declare function randRange(min: number, max: number): number;
56
+ /** Returns a random number between 0 and `max` (inclusive) */
57
+ declare function randRange(max: number): number;
58
+
59
+ type InitOnSelectorOpts = {
60
+ /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
61
+ attributes?: boolean;
62
+ /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
63
+ characterData?: boolean;
64
+ };
65
+ type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
66
+ type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
67
+ /** Whether to use `querySelectorAll()` instead - default is false */
68
+ all?: false;
69
+ /** Gets called whenever the selector was found in the DOM */
70
+ listener: (element: TElem) => void;
71
+ };
72
+ type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
73
+ /** Whether to use `querySelectorAll()` instead - default is false */
74
+ all: true;
75
+ /** Gets called whenever the selector was found in the DOM */
76
+ listener: (elements: NodeListOf<TElem>) => void;
77
+ };
78
+ type SelectorOptsBase = {
79
+ /** Whether to call the listener continuously instead of once - default is false */
80
+ continuous?: boolean;
81
+ };
82
+ type FetchAdvancedOpts = RequestInit & Partial<{
83
+ /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
84
+ timeout: number;
85
+ }>;
86
+
87
+ /**
88
+ * Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
89
+ * @param word A word in singular form, to auto-convert to plural
90
+ * @param num If this is an array or NodeList, the amount of items is used
91
+ */
92
+ declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
93
+ /** Pauses async execution for the specified time in ms */
94
+ declare function pauseFor(time: number): Promise<unknown>;
95
+ /**
96
+ * Calls the passed `func` after the specified `timeout` in ms.
97
+ * Any subsequent calls to this function will reset the timer and discard previous calls.
98
+ */
99
+ declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
100
+ /** Calls the fetch API with special options like a timeout */
101
+ declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
102
+
92
103
  /**
93
104
  * Calls the `listener` as soon as the `selector` exists in the DOM.
94
105
  * Listeners are deleted when they are called once, unless `options.continuous` is set.
@@ -111,4 +122,4 @@ declare function initOnSelector(opts?: InitOnSelectorOpts): void;
111
122
  /** Returns all currently registered selectors, as a map of selector strings to their associated options */
112
123
  declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
113
124
 
114
- export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
125
+ export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, removeOnSelector };
package/dist/index.js CHANGED
@@ -1,21 +1,23 @@
1
1
  'use strict';
2
2
 
3
- var b=Object.defineProperty,y=Object.defineProperties;var g=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&f(t,n,e[n]);if(m)for(var n of m(e))x.call(e,n)&&f(t,n,e[n]);return t},d=(t,e)=>y(t,g(e));var E=(t,e,n)=>new Promise((r,o)=>{var s=a=>{try{l(n.next(a));}catch(p){o(p);}},i=a=>{try{l(n.throw(a));}catch(p){o(p);}},l=a=>a.done?r(a.value):Promise.resolve(a.value).then(s,i);l((n=n.apply(t,e)).next());});function w(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function M(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function h(){try{return unsafeWindow}catch(t){return window}}function _(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function k(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function H(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function I(t,e=!1){let n=t.map(r=>new Promise((o,s)=>{let i=new Image;i.src=r,i.addEventListener("load",()=>o(i)),i.addEventListener("error",l=>e&&s(l));}));return Promise.allSettled(n)}function j(n){return E(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,s=setTimeout(()=>o.abort(),r),i=yield fetch(t,d(u({},e),{signal:o.signal}));return clearTimeout(s),i})}function C(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function O(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function N(t,e){return O(h(),t,e)}var c=new Map;function W(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),T(t,n);}function $(t){return c.delete(t)}function T(t,e){let n=[];if(e.forEach((r,o)=>{try{let s=r.all?document.querySelectorAll(t):document.querySelector(t);s&&(r.listener(s),r.continuous||n.push(o));}catch(s){console.error(`Couldn't call listener for selector '${t}'`,s);}}),n.length>0){let r=e.filter((o,s)=>!n.includes(s));r.length===0?c.delete(t):c.set(t,r);}}function q(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())T(n,r);}).observe(document.body,d(u({},t),{childList:!0}));}function B(){return c}
3
+ var x=Object.defineProperty,y=Object.defineProperties;var T=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var h=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?x(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,m=(t,e)=>{for(var n in e||(e={}))h.call(e,n)&&f(t,n,e[n]);if(d)for(var n of d(e))v.call(e,n)&&f(t,n,e[n]);return t},l=(t,e)=>y(t,T(e));var b=(t,e,n)=>new Promise((r,o)=>{var i=u=>{try{a(n.next(u));}catch(p){o(p);}},s=u=>{try{a(n.throw(u));}catch(p){o(p);}},a=u=>u.done?r(u.value):Promise.resolve(u.value).then(i,s);a((n=n.apply(t,e)).next());});function O(){try{return unsafeWindow}catch(t){return window}}function L(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function M(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function S(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function N(t,e=!1){let n=t.map(r=>new Promise((o,i)=>{let s=new Image;s.src=r,s.addEventListener("load",()=>o(s)),s.addEventListener("error",a=>e&&i(a));}));return Promise.allSettled(n)}function A(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function w(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function k(t,e){return w(O(),t,e)}function P(t,e,n){return Math.max(Math.min(t,n),e)}function I(t,e,n,r,o){return Number(e)===0&&Number(r)===0?t*(o/n):(t-e)*((o-r)/(n-e))+r}function j(...t){let e,n;if(typeof t[0]=="number"&&typeof t[1]=="number")[e,n]=t;else if(typeof t[0]=="number"&&typeof t[1]!="number")e=0,n=t[0];else throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof t[0]}" and "${typeof t[1]}"`);if(e=Number(e),n=Number(n),isNaN(e)||isNaN(n))throw new TypeError(`Parameters "min" and "max" can't be NaN`);if(e>n)throw new TypeError(`Parameter "min" can't be bigger than "max"`);return Math.floor(Math.random()*(n-e+1))+e}function F(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function W(t){return new Promise(e=>{setTimeout(e,t);})}function $(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function R(n){return b(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),s=yield fetch(t,l(m({},e),{signal:o.signal}));return clearTimeout(i),s})}var c=new Map;function G(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),E(t,n);}function U(t){return c.delete(t)}function E(t,e){let n=[];if(e.forEach((r,o)=>{try{let i=r.all?document.querySelectorAll(t):document.querySelector(t);i&&(r.listener(i),r.continuous||n.push(o));}catch(i){console.error(`Couldn't call listener for selector '${t}'`,i);}}),n.length>0){let r=e.filter((o,i)=>!n.includes(i));r.length===0?c.delete(t):c.set(t,r);}}function z(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())E(n,r);}).observe(document.body,l(m({},t),{childList:!0}));}function D(){return c}
4
4
 
5
- exports.addGlobalStyle = H;
6
- exports.addParent = k;
7
- exports.autoPlural = w;
8
- exports.clamp = M;
9
- exports.debounce = A;
10
- exports.fetchAdvanced = j;
11
- exports.getSelectorMap = B;
12
- exports.getUnsafeWindow = h;
13
- exports.initOnSelector = q;
14
- exports.insertAfter = _;
15
- exports.interceptEvent = O;
16
- exports.interceptWindowEvent = N;
17
- exports.onSelector = W;
18
- exports.openInNewTab = C;
19
- exports.pauseFor = S;
20
- exports.preloadImages = I;
21
- exports.removeOnSelector = $;
5
+ exports.addGlobalStyle = S;
6
+ exports.addParent = M;
7
+ exports.autoPlural = F;
8
+ exports.clamp = P;
9
+ exports.debounce = $;
10
+ exports.fetchAdvanced = R;
11
+ exports.getSelectorMap = D;
12
+ exports.getUnsafeWindow = O;
13
+ exports.initOnSelector = z;
14
+ exports.insertAfter = L;
15
+ exports.interceptEvent = w;
16
+ exports.interceptWindowEvent = k;
17
+ exports.mapRange = I;
18
+ exports.onSelector = G;
19
+ exports.openInNewTab = A;
20
+ exports.pauseFor = W;
21
+ exports.preloadImages = N;
22
+ exports.randRange = j;
23
+ exports.removeOnSelector = U;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var b=Object.defineProperty,y=Object.defineProperties;var g=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&f(t,n,e[n]);if(m)for(var n of m(e))x.call(e,n)&&f(t,n,e[n]);return t},d=(t,e)=>y(t,g(e));var E=(t,e,n)=>new Promise((r,o)=>{var s=a=>{try{l(n.next(a));}catch(p){o(p);}},i=a=>{try{l(n.throw(a));}catch(p){o(p);}},l=a=>a.done?r(a.value):Promise.resolve(a.value).then(s,i);l((n=n.apply(t,e)).next());});function w(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function M(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function h(){try{return unsafeWindow}catch(t){return window}}function _(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function k(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function H(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function I(t,e=!1){let n=t.map(r=>new Promise((o,s)=>{let i=new Image;i.src=r,i.addEventListener("load",()=>o(i)),i.addEventListener("error",l=>e&&s(l));}));return Promise.allSettled(n)}function j(n){return E(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,s=setTimeout(()=>o.abort(),r),i=yield fetch(t,d(u({},e),{signal:o.signal}));return clearTimeout(s),i})}function C(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function O(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function N(t,e){return O(h(),t,e)}var c=new Map;function W(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),T(t,n);}function $(t){return c.delete(t)}function T(t,e){let n=[];if(e.forEach((r,o)=>{try{let s=r.all?document.querySelectorAll(t):document.querySelector(t);s&&(r.listener(s),r.continuous||n.push(o));}catch(s){console.error(`Couldn't call listener for selector '${t}'`,s);}}),n.length>0){let r=e.filter((o,s)=>!n.includes(s));r.length===0?c.delete(t):c.set(t,r);}}function q(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())T(n,r);}).observe(document.body,d(u({},t),{childList:!0}));}function B(){return c}
1
+ var x=Object.defineProperty,y=Object.defineProperties;var T=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var h=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?x(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,m=(t,e)=>{for(var n in e||(e={}))h.call(e,n)&&f(t,n,e[n]);if(d)for(var n of d(e))v.call(e,n)&&f(t,n,e[n]);return t},l=(t,e)=>y(t,T(e));var b=(t,e,n)=>new Promise((r,o)=>{var i=u=>{try{a(n.next(u));}catch(p){o(p);}},s=u=>{try{a(n.throw(u));}catch(p){o(p);}},a=u=>u.done?r(u.value):Promise.resolve(u.value).then(i,s);a((n=n.apply(t,e)).next());});function O(){try{return unsafeWindow}catch(t){return window}}function L(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function M(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function S(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function N(t,e=!1){let n=t.map(r=>new Promise((o,i)=>{let s=new Image;s.src=r,s.addEventListener("load",()=>o(s)),s.addEventListener("error",a=>e&&i(a));}));return Promise.allSettled(n)}function A(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function w(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function k(t,e){return w(O(),t,e)}function P(t,e,n){return Math.max(Math.min(t,n),e)}function I(t,e,n,r,o){return Number(e)===0&&Number(r)===0?t*(o/n):(t-e)*((o-r)/(n-e))+r}function j(...t){let e,n;if(typeof t[0]=="number"&&typeof t[1]=="number")[e,n]=t;else if(typeof t[0]=="number"&&typeof t[1]!="number")e=0,n=t[0];else throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof t[0]}" and "${typeof t[1]}"`);if(e=Number(e),n=Number(n),isNaN(e)||isNaN(n))throw new TypeError(`Parameters "min" and "max" can't be NaN`);if(e>n)throw new TypeError(`Parameter "min" can't be bigger than "max"`);return Math.floor(Math.random()*(n-e+1))+e}function F(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function W(t){return new Promise(e=>{setTimeout(e,t);})}function $(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function R(n){return b(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),s=yield fetch(t,l(m({},e),{signal:o.signal}));return clearTimeout(i),s})}var c=new Map;function G(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),E(t,n);}function U(t){return c.delete(t)}function E(t,e){let n=[];if(e.forEach((r,o)=>{try{let i=r.all?document.querySelectorAll(t):document.querySelector(t);i&&(r.listener(i),r.continuous||n.push(o));}catch(i){console.error(`Couldn't call listener for selector '${t}'`,i);}}),n.length>0){let r=e.filter((o,i)=>!n.includes(i));r.length===0?c.delete(t):c.set(t,r);}}function z(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())E(n,r);}).observe(document.body,l(m({},t),{childList:!0}));}function D(){return c}
2
2
 
3
- export { H as addGlobalStyle, k as addParent, w as autoPlural, M as clamp, A as debounce, j as fetchAdvanced, B as getSelectorMap, h as getUnsafeWindow, q as initOnSelector, _ as insertAfter, O as interceptEvent, N as interceptWindowEvent, W as onSelector, C as openInNewTab, S as pauseFor, I as preloadImages, $ as removeOnSelector };
3
+ export { S as addGlobalStyle, M as addParent, F as autoPlural, P as clamp, $ as debounce, R as fetchAdvanced, D as getSelectorMap, O as getUnsafeWindow, z as initOnSelector, L as insertAfter, w as interceptEvent, k as interceptWindowEvent, I as mapRange, G as onSelector, A as openInNewTab, W as pauseFor, N as preloadImages, j as randRange, U as removeOnSelector };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more ",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",