@sv443-network/userutils 4.1.0 → 4.2.1

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,23 @@
1
1
  # @sv443-network/userutils
2
2
 
3
+ ## 4.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 0462e35: Fixed TS types for overload of SelectorObserver constructor
8
+
9
+ ## 4.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 47639f0: Added SelectorObserver options `disableOnNoListeners` and `enableOnAddListener`
14
+ - 4a58caa: `addGlobalStyle` now returns the created style element
15
+ - 5038967: `fetchAdvanced` is now a drop-in replacement and timeout can now optionally be disabled
16
+
17
+ ### Patch Changes
18
+
19
+ - 17a6ad5: `randomizeArray` now returns a copy if an empty array is passed as well
20
+
3
21
  ## 4.1.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -84,7 +84,7 @@ View the documentation of previous major releases: [3.0.0](https://github.com/Sv
84
84
 
85
85
  <br>
86
86
 
87
- - If you are not using a bundler, you can include the latest release from GreasyFork by adding this directive to the userscript header:
87
+ - If you are not using a bundler, you can include the latest release by adding one of these directives to the userscript header, depending on your preferred CDN:
88
88
  ```
89
89
  // @require https://greasyfork.org/scripts/472956-userutils/code/UserUtils.js
90
90
  ```
@@ -100,7 +100,7 @@ View the documentation of previous major releases: [3.0.0](https://github.com/Sv
100
100
  // or using object destructuring:
101
101
 
102
102
  const { clamp } = UserUtils;
103
- console.log(clamp(1, 5, 10); // 5
103
+ console.log(clamp(1, 5, 10)); // 5
104
104
  ```
105
105
 
106
106
  <br><br>
@@ -148,9 +148,12 @@ If a selector string is passed instead, it will be used to find the element.
148
148
  If you want to observe the entire document, you can pass `document.body`
149
149
 
150
150
  The `options` parameter is optional and will be passed to the MutationObserver that is used internally.
151
- The default options are `{ childList: true, subtree: true }` - you may see the [MutationObserver.observe() documentation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#options) for more information and a list of options.
152
- For example, if you want to trigger the listeners when certain attributes change, pass `{ attributes: true, attributeFilter: ["class", "data-my-attribute"] }`
151
+ The MutationObserver options present by default are `{ childList: true, subtree: true }` - you may see the [MutationObserver.observe() documentation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#options) for more information and a list of options.
152
+ For example, if you want to trigger the listeners when certain attributes change, pass `{ attributeFilter: ["class", "data-my-attribute"] }`
153
+
153
154
  Additionally, there are the following extra options:
155
+ - `disableOnNoListeners` - whether to disable the SelectorObserver when there are no listeners left (defaults to false)
156
+ - `enableOnAddListener` - whether to enable the SelectorObserver when a new listener is added (defaults to true)
154
157
  - `defaultDebounce` - if set to a number, this debounce will be applied to every listener that doesn't have a custom debounce set (defaults to 0)
155
158
 
156
159
  ⚠️ Make sure to call `enable()` to actually start observing. This will need to be done after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired) **and** as soon as the `baseElement` or `baseElementSelector` is available.
@@ -506,10 +509,11 @@ addParent(element, newParent);
506
509
  ### addGlobalStyle()
507
510
  Usage:
508
511
  ```ts
509
- addGlobalStyle(css: string): void
512
+ addGlobalStyle(css: string): HTMLStyleElement
510
513
  ```
511
514
 
512
515
  Adds a global style to the page in form of a `<style>` element that's inserted into the `<head>`.
516
+ Returns the style element that was just created.
513
517
  ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
514
518
 
515
519
  <details><summary><b>Example - click to view</b></summary>
@@ -823,6 +827,9 @@ randomId(length?: number, radix?: number): string
823
827
  ```
824
828
 
825
829
  Generates a cryptographically strong random ID of a given length and [radix (base).](https://en.wikipedia.org/wiki/Radix)
830
+ Uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for generating the random numbers.
831
+ ⚠️ This is not intended for generating encryption keys, only for generating IDs with a decent amount of entropy!
832
+
826
833
  The default length is 16 and the default radix is 16 (hexadecimal).
827
834
  You may change the radix to get digits from different numerical systems.
828
835
  Use 2 for binary, 8 for octal, 10 for decimal, 16 for hexadecimal and 36 for alphanumeric.
@@ -1058,14 +1065,15 @@ window.addEventListener("resize", debounce((event) => {
1058
1065
  ### fetchAdvanced()
1059
1066
  Usage:
1060
1067
  ```ts
1061
- fetchAdvanced(url: string, options?: {
1068
+ fetchAdvanced(input: string | Request | URL, options?: {
1062
1069
  timeout?: number,
1063
1070
  // any other options from fetch() except for signal
1064
1071
  }): Promise<Response>
1065
1072
  ```
1066
1073
 
1067
- A wrapper around the native `fetch()` function that adds options like a timeout property.
1068
- The timeout will default to 10 seconds if left undefined.
1074
+ A drop-in replacement for the native `fetch()` function that adds options like a timeout property.
1075
+ The timeout will default to 10 seconds if left undefined. Set it to a negative number to disable the timeout.
1076
+ Note that the `signal` option will be overwritten if passed.
1069
1077
 
1070
1078
  <details><summary><b>Example - click to view</b></summary>
1071
1079
 
@@ -1076,10 +1084,12 @@ fetchAdvanced("https://jokeapi.dev/joke/Any?safe-mode", {
1076
1084
  timeout: 5000,
1077
1085
  // also accepts any other fetch options like headers:
1078
1086
  headers: {
1079
- "Accept": "application/json",
1087
+ "Accept": "text/plain",
1080
1088
  },
1081
1089
  }).then(async (response) => {
1082
- console.log("Data:", await response.json());
1090
+ console.log("Fetch data:", await response.text());
1091
+ }).catch((err) => {
1092
+ console.error("Fetch error:", err);
1083
1093
  });
1084
1094
  ```
1085
1095
 
@@ -1269,7 +1279,7 @@ randomizeArray(array: Array): Array
1269
1279
  ```
1270
1280
 
1271
1281
  Returns a copy of an array with its items in a random order.
1272
- If the array is empty, the originally passed empty array will be returned without copying.
1282
+ If the array is empty, a new, empty array will be returned.
1273
1283
 
1274
1284
  <details><summary><b>Example - click to view</b></summary>
1275
1285
 
@@ -9,7 +9,7 @@
9
9
  // ==UserLibrary==
10
10
  // @name UserUtils
11
11
  // @description Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more
12
- // @version 4.1.0
12
+ // @version 4.2.1
13
13
  // @license MIT
14
14
  // @copyright Sv443 (https://github.com/Sv443)
15
15
 
@@ -22,8 +22,6 @@
22
22
 
23
23
  var UserUtils = (function (exports) {
24
24
  var __defProp = Object.defineProperty;
25
- var __defProps = Object.defineProperties;
26
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
27
25
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
28
26
  var __hasOwnProp = Object.prototype.hasOwnProperty;
29
27
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -39,7 +37,18 @@ var UserUtils = (function (exports) {
39
37
  }
40
38
  return a;
41
39
  };
42
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
40
+ var __objRest = (source, exclude) => {
41
+ var target = {};
42
+ for (var prop in source)
43
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
44
+ target[prop] = source[prop];
45
+ if (source != null && __getOwnPropSymbols)
46
+ for (var prop of __getOwnPropSymbols(source)) {
47
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
48
+ target[prop] = source[prop];
49
+ }
50
+ return target;
51
+ };
43
52
  var __publicField = (obj, key, value) => {
44
53
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
45
54
  return value;
@@ -120,7 +129,7 @@ var UserUtils = (function (exports) {
120
129
  function randomizeArray(array) {
121
130
  const retArray = [...array];
122
131
  if (array.length === 0)
123
- return array;
132
+ return retArray;
124
133
  for (let i = retArray.length - 1; i > 0; i--) {
125
134
  const j = Math.floor(randRange(0, 1e4) / 1e4 * (i + 1));
126
135
  [retArray[i], retArray[j]] = [retArray[j], retArray[i]];
@@ -282,6 +291,7 @@ var UserUtils = (function (exports) {
282
291
  const styleElem = document.createElement("style");
283
292
  styleElem.innerHTML = style;
284
293
  document.head.appendChild(styleElem);
294
+ return styleElem;
285
295
  }
286
296
  function preloadImages(srcUrls, rejects = false) {
287
297
  const promises = srcUrls.map((src) => new Promise((res, rej) => {
@@ -375,13 +385,15 @@ var UserUtils = (function (exports) {
375
385
  };
376
386
  }
377
387
  function fetchAdvanced(_0) {
378
- return __async(this, arguments, function* (url, options = {}) {
388
+ return __async(this, arguments, function* (input, options = {}) {
379
389
  const { timeout = 1e4 } = options;
380
- const controller = new AbortController();
381
- const id = setTimeout(() => controller.abort(), timeout);
382
- const res = yield fetch(url, __spreadProps(__spreadValues({}, options), {
383
- signal: controller.signal
384
- }));
390
+ let signalOpts = {}, id = void 0;
391
+ if (timeout >= 0) {
392
+ const controller = new AbortController();
393
+ id = setTimeout(() => controller.abort(), timeout);
394
+ signalOpts = { signal: controller.signal };
395
+ }
396
+ const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
385
397
  clearTimeout(id);
386
398
  return res;
387
399
  });
@@ -431,14 +443,29 @@ var UserUtils = (function (exports) {
431
443
  __publicField(this, "baseElement");
432
444
  __publicField(this, "observer");
433
445
  __publicField(this, "observerOptions");
446
+ __publicField(this, "customOptions");
434
447
  __publicField(this, "listenerMap");
435
448
  this.baseElement = baseElement;
436
449
  this.listenerMap = /* @__PURE__ */ new Map();
437
450
  this.observer = new MutationObserver(() => this.checkAllSelectors());
451
+ const _a = options, {
452
+ defaultDebounce,
453
+ disableOnNoListeners,
454
+ enableOnAddListener
455
+ } = _a, observerOptions = __objRest(_a, [
456
+ "defaultDebounce",
457
+ "disableOnNoListeners",
458
+ "enableOnAddListener"
459
+ ]);
438
460
  this.observerOptions = __spreadValues({
439
461
  childList: true,
440
462
  subtree: true
441
- }, options);
463
+ }, observerOptions);
464
+ this.customOptions = {
465
+ defaultDebounce: defaultDebounce != null ? defaultDebounce : 0,
466
+ disableOnNoListeners: disableOnNoListeners != null ? disableOnNoListeners : false,
467
+ enableOnAddListener: enableOnAddListener != null ? enableOnAddListener : true
468
+ };
442
469
  }
443
470
  checkAllSelectors() {
444
471
  for (const [selector, listeners] of this.listenerMap.entries())
@@ -471,6 +498,8 @@ var UserUtils = (function (exports) {
471
498
  }
472
499
  if (((_a = this.listenerMap.get(selector)) == null ? void 0 : _a.length) === 0)
473
500
  this.listenerMap.delete(selector);
501
+ if (this.listenerMap.size === 0 && this.customOptions.disableOnNoListeners)
502
+ this.disable();
474
503
  }
475
504
  }
476
505
  debounce(func, time) {
@@ -491,16 +520,18 @@ var UserUtils = (function (exports) {
491
520
  */
492
521
  addListener(selector, options) {
493
522
  options = __spreadValues({ all: false, continuous: false, debounce: 0 }, options);
494
- if (options.debounce && options.debounce > 0 || this.observerOptions.defaultDebounce && this.observerOptions.defaultDebounce > 0) {
523
+ if (options.debounce && options.debounce > 0 || this.customOptions.defaultDebounce && this.customOptions.defaultDebounce > 0) {
495
524
  options.listener = this.debounce(
496
525
  options.listener,
497
- options.debounce || this.observerOptions.defaultDebounce
526
+ options.debounce || this.customOptions.defaultDebounce
498
527
  );
499
528
  }
500
529
  if (this.listenerMap.has(selector))
501
530
  this.listenerMap.get(selector).push(options);
502
531
  else
503
532
  this.listenerMap.set(selector, [options]);
533
+ if (this.enabled === false && this.customOptions.enableOnAddListener)
534
+ this.enable();
504
535
  this.checkSelector(selector, [options]);
505
536
  }
506
537
  /** Disables the observation of the child elements */
package/dist/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -18,7 +16,18 @@ var __spreadValues = (a, b) => {
18
16
  }
19
17
  return a;
20
18
  };
21
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
19
+ var __objRest = (source, exclude) => {
20
+ var target = {};
21
+ for (var prop in source)
22
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
23
+ target[prop] = source[prop];
24
+ if (source != null && __getOwnPropSymbols)
25
+ for (var prop of __getOwnPropSymbols(source)) {
26
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
27
+ target[prop] = source[prop];
28
+ }
29
+ return target;
30
+ };
22
31
  var __publicField = (obj, key, value) => {
23
32
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
24
33
  return value;
@@ -99,7 +108,7 @@ function takeRandomItem(arr) {
99
108
  function randomizeArray(array) {
100
109
  const retArray = [...array];
101
110
  if (array.length === 0)
102
- return array;
111
+ return retArray;
103
112
  for (let i = retArray.length - 1; i > 0; i--) {
104
113
  const j = Math.floor(randRange(0, 1e4) / 1e4 * (i + 1));
105
114
  [retArray[i], retArray[j]] = [retArray[j], retArray[i]];
@@ -261,6 +270,7 @@ function addGlobalStyle(style) {
261
270
  const styleElem = document.createElement("style");
262
271
  styleElem.innerHTML = style;
263
272
  document.head.appendChild(styleElem);
273
+ return styleElem;
264
274
  }
265
275
  function preloadImages(srcUrls, rejects = false) {
266
276
  const promises = srcUrls.map((src) => new Promise((res, rej) => {
@@ -354,13 +364,15 @@ function debounce(func, timeout = 300) {
354
364
  };
355
365
  }
356
366
  function fetchAdvanced(_0) {
357
- return __async(this, arguments, function* (url, options = {}) {
367
+ return __async(this, arguments, function* (input, options = {}) {
358
368
  const { timeout = 1e4 } = options;
359
- const controller = new AbortController();
360
- const id = setTimeout(() => controller.abort(), timeout);
361
- const res = yield fetch(url, __spreadProps(__spreadValues({}, options), {
362
- signal: controller.signal
363
- }));
369
+ let signalOpts = {}, id = void 0;
370
+ if (timeout >= 0) {
371
+ const controller = new AbortController();
372
+ id = setTimeout(() => controller.abort(), timeout);
373
+ signalOpts = { signal: controller.signal };
374
+ }
375
+ const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
364
376
  clearTimeout(id);
365
377
  return res;
366
378
  });
@@ -410,14 +422,29 @@ var SelectorObserver = class {
410
422
  __publicField(this, "baseElement");
411
423
  __publicField(this, "observer");
412
424
  __publicField(this, "observerOptions");
425
+ __publicField(this, "customOptions");
413
426
  __publicField(this, "listenerMap");
414
427
  this.baseElement = baseElement;
415
428
  this.listenerMap = /* @__PURE__ */ new Map();
416
429
  this.observer = new MutationObserver(() => this.checkAllSelectors());
430
+ const _a = options, {
431
+ defaultDebounce,
432
+ disableOnNoListeners,
433
+ enableOnAddListener
434
+ } = _a, observerOptions = __objRest(_a, [
435
+ "defaultDebounce",
436
+ "disableOnNoListeners",
437
+ "enableOnAddListener"
438
+ ]);
417
439
  this.observerOptions = __spreadValues({
418
440
  childList: true,
419
441
  subtree: true
420
- }, options);
442
+ }, observerOptions);
443
+ this.customOptions = {
444
+ defaultDebounce: defaultDebounce != null ? defaultDebounce : 0,
445
+ disableOnNoListeners: disableOnNoListeners != null ? disableOnNoListeners : false,
446
+ enableOnAddListener: enableOnAddListener != null ? enableOnAddListener : true
447
+ };
421
448
  }
422
449
  checkAllSelectors() {
423
450
  for (const [selector, listeners] of this.listenerMap.entries())
@@ -450,6 +477,8 @@ var SelectorObserver = class {
450
477
  }
451
478
  if (((_a = this.listenerMap.get(selector)) == null ? void 0 : _a.length) === 0)
452
479
  this.listenerMap.delete(selector);
480
+ if (this.listenerMap.size === 0 && this.customOptions.disableOnNoListeners)
481
+ this.disable();
453
482
  }
454
483
  }
455
484
  debounce(func, time) {
@@ -470,16 +499,18 @@ var SelectorObserver = class {
470
499
  */
471
500
  addListener(selector, options) {
472
501
  options = __spreadValues({ all: false, continuous: false, debounce: 0 }, options);
473
- if (options.debounce && options.debounce > 0 || this.observerOptions.defaultDebounce && this.observerOptions.defaultDebounce > 0) {
502
+ if (options.debounce && options.debounce > 0 || this.customOptions.defaultDebounce && this.customOptions.defaultDebounce > 0) {
474
503
  options.listener = this.debounce(
475
504
  options.listener,
476
- options.debounce || this.observerOptions.defaultDebounce
505
+ options.debounce || this.customOptions.defaultDebounce
477
506
  );
478
507
  }
479
508
  if (this.listenerMap.has(selector))
480
509
  this.listenerMap.get(selector).push(options);
481
510
  else
482
511
  this.listenerMap.set(selector, [options]);
512
+ if (this.enabled === false && this.customOptions.enableOnAddListener)
513
+ this.enable();
483
514
  this.checkSelector(selector, [options]);
484
515
  }
485
516
  /** Disables the observation of the child elements */
package/dist/index.mjs CHANGED
@@ -1,6 +1,4 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -16,7 +14,18 @@ var __spreadValues = (a, b) => {
16
14
  }
17
15
  return a;
18
16
  };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
17
+ var __objRest = (source, exclude) => {
18
+ var target = {};
19
+ for (var prop in source)
20
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
21
+ target[prop] = source[prop];
22
+ if (source != null && __getOwnPropSymbols)
23
+ for (var prop of __getOwnPropSymbols(source)) {
24
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
25
+ target[prop] = source[prop];
26
+ }
27
+ return target;
28
+ };
20
29
  var __publicField = (obj, key, value) => {
21
30
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
22
31
  return value;
@@ -97,7 +106,7 @@ function takeRandomItem(arr) {
97
106
  function randomizeArray(array) {
98
107
  const retArray = [...array];
99
108
  if (array.length === 0)
100
- return array;
109
+ return retArray;
101
110
  for (let i = retArray.length - 1; i > 0; i--) {
102
111
  const j = Math.floor(randRange(0, 1e4) / 1e4 * (i + 1));
103
112
  [retArray[i], retArray[j]] = [retArray[j], retArray[i]];
@@ -259,6 +268,7 @@ function addGlobalStyle(style) {
259
268
  const styleElem = document.createElement("style");
260
269
  styleElem.innerHTML = style;
261
270
  document.head.appendChild(styleElem);
271
+ return styleElem;
262
272
  }
263
273
  function preloadImages(srcUrls, rejects = false) {
264
274
  const promises = srcUrls.map((src) => new Promise((res, rej) => {
@@ -352,13 +362,15 @@ function debounce(func, timeout = 300) {
352
362
  };
353
363
  }
354
364
  function fetchAdvanced(_0) {
355
- return __async(this, arguments, function* (url, options = {}) {
365
+ return __async(this, arguments, function* (input, options = {}) {
356
366
  const { timeout = 1e4 } = options;
357
- const controller = new AbortController();
358
- const id = setTimeout(() => controller.abort(), timeout);
359
- const res = yield fetch(url, __spreadProps(__spreadValues({}, options), {
360
- signal: controller.signal
361
- }));
367
+ let signalOpts = {}, id = void 0;
368
+ if (timeout >= 0) {
369
+ const controller = new AbortController();
370
+ id = setTimeout(() => controller.abort(), timeout);
371
+ signalOpts = { signal: controller.signal };
372
+ }
373
+ const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
362
374
  clearTimeout(id);
363
375
  return res;
364
376
  });
@@ -408,14 +420,29 @@ var SelectorObserver = class {
408
420
  __publicField(this, "baseElement");
409
421
  __publicField(this, "observer");
410
422
  __publicField(this, "observerOptions");
423
+ __publicField(this, "customOptions");
411
424
  __publicField(this, "listenerMap");
412
425
  this.baseElement = baseElement;
413
426
  this.listenerMap = /* @__PURE__ */ new Map();
414
427
  this.observer = new MutationObserver(() => this.checkAllSelectors());
428
+ const _a = options, {
429
+ defaultDebounce,
430
+ disableOnNoListeners,
431
+ enableOnAddListener
432
+ } = _a, observerOptions = __objRest(_a, [
433
+ "defaultDebounce",
434
+ "disableOnNoListeners",
435
+ "enableOnAddListener"
436
+ ]);
415
437
  this.observerOptions = __spreadValues({
416
438
  childList: true,
417
439
  subtree: true
418
- }, options);
440
+ }, observerOptions);
441
+ this.customOptions = {
442
+ defaultDebounce: defaultDebounce != null ? defaultDebounce : 0,
443
+ disableOnNoListeners: disableOnNoListeners != null ? disableOnNoListeners : false,
444
+ enableOnAddListener: enableOnAddListener != null ? enableOnAddListener : true
445
+ };
419
446
  }
420
447
  checkAllSelectors() {
421
448
  for (const [selector, listeners] of this.listenerMap.entries())
@@ -448,6 +475,8 @@ var SelectorObserver = class {
448
475
  }
449
476
  if (((_a = this.listenerMap.get(selector)) == null ? void 0 : _a.length) === 0)
450
477
  this.listenerMap.delete(selector);
478
+ if (this.listenerMap.size === 0 && this.customOptions.disableOnNoListeners)
479
+ this.disable();
451
480
  }
452
481
  }
453
482
  debounce(func, time) {
@@ -468,16 +497,18 @@ var SelectorObserver = class {
468
497
  */
469
498
  addListener(selector, options) {
470
499
  options = __spreadValues({ all: false, continuous: false, debounce: 0 }, options);
471
- if (options.debounce && options.debounce > 0 || this.observerOptions.defaultDebounce && this.observerOptions.defaultDebounce > 0) {
500
+ if (options.debounce && options.debounce > 0 || this.customOptions.defaultDebounce && this.customOptions.defaultDebounce > 0) {
472
501
  options.listener = this.debounce(
473
502
  options.listener,
474
- options.debounce || this.observerOptions.defaultDebounce
503
+ options.debounce || this.customOptions.defaultDebounce
475
504
  );
476
505
  }
477
506
  if (this.listenerMap.has(selector))
478
507
  this.listenerMap.get(selector).push(options);
479
508
  else
480
509
  this.listenerMap.set(selector, [options]);
510
+ if (this.enabled === false && this.customOptions.enableOnAddListener)
511
+ this.enable();
481
512
  this.checkSelector(selector, [options]);
482
513
  }
483
514
  /** Disables the observation of the child elements */
@@ -18,29 +18,35 @@ type SelectorOptionsCommon = {
18
18
  /** Whether to debounce the listener to reduce calls to `querySelector` or `querySelectorAll` - set undefined or <=0 to disable (default) */
19
19
  debounce?: number;
20
20
  };
21
- export type SelectorObserverOptions = MutationObserverInit & {
21
+ export type SelectorObserverOptions = {
22
22
  /** If set, applies this debounce in milliseconds to all listeners that don't have their own debounce set */
23
23
  defaultDebounce?: number;
24
+ /** Whether to disable the observer when no listeners are present - default is true */
25
+ disableOnNoListeners?: boolean;
26
+ /** Whether to ensure the observer is enabled when a new listener is added - default is true */
27
+ enableOnAddListener?: boolean;
24
28
  };
29
+ export type SelectorObserverConstructorOptions = MutationObserverInit & SelectorObserverOptions;
25
30
  /** Observes the children of the given element for changes */
26
31
  export declare class SelectorObserver {
27
32
  private enabled;
28
33
  private baseElement;
29
34
  private observer;
30
35
  private observerOptions;
36
+ private customOptions;
31
37
  private listenerMap;
32
38
  /**
33
39
  * Creates a new SelectorObserver that will observe the children of the given base element selector for changes (only creation and deletion of elements by default)
34
40
  * @param baseElementSelector The selector of the element to observe
35
41
  * @param options Fine-tune what triggers the MutationObserver's checking function - `subtree` and `childList` are set to true by default
36
42
  */
37
- constructor(baseElementSelector: string, options?: SelectorObserverOptions);
43
+ constructor(baseElementSelector: string, options?: SelectorObserverConstructorOptions);
38
44
  /**
39
45
  * Creates a new SelectorObserver that will observe the children of the given base element for changes (only creation and deletion of elements by default)
40
46
  * @param baseElement The element to observe
41
47
  * @param options Fine-tune what triggers the MutationObserver's checking function - `subtree` and `childList` are set to true by default
42
48
  */
43
- constructor(baseElement: Element, options?: SelectorObserverOptions);
49
+ constructor(baseElement: Element, options?: SelectorObserverConstructorOptions);
44
50
  private checkAllSelectors;
45
51
  private checkSelector;
46
52
  private debounce;
package/dist/lib/dom.d.ts CHANGED
@@ -16,8 +16,9 @@ export declare function addParent(element: Element, newParent: Element): Element
16
16
  * Adds global CSS style in the form of a `<style>` element in the document's `<head>`
17
17
  * This needs to be run after the `DOMContentLoaded` event has fired on the document object (or instantly if `@run-at document-end` is used).
18
18
  * @param style CSS string
19
+ * @returns Returns the created style element
19
20
  */
20
- export declare function addGlobalStyle(style: string): void;
21
+ export declare function addGlobalStyle(style: string): HTMLStyleElement;
21
22
  /**
22
23
  * Preloads an array of image URLs so they can be loaded instantly from the browser cache later on
23
24
  * @param rejects If set to `true`, the returned PromiseSettledResults will contain rejections for any of the images that failed to load
@@ -12,6 +12,7 @@ export declare function randRange(max: number): number;
12
12
  /**
13
13
  * Generates a random ID with the specified length and radix (16 characters and hexadecimal by default)
14
14
  * Uses [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for better cryptographic randomness
15
+ * ⚠️ Not suitable for generating encryption keys! Use [`crypto.subtle.generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that.
15
16
  * @param length The length of the ID to generate (defaults to 16)
16
17
  * @param radix The [radix](https://en.wikipedia.org/wiki/Radix) of each digit (defaults to 16 which is hexadecimal. Use 2 for binary, 10 for decimal, 36 for alphanumeric, etc.)
17
18
  */
@@ -29,12 +29,12 @@ export declare function pauseFor(time: number): Promise<void>;
29
29
  */
30
30
  export declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
31
31
  /** Options for the `fetchAdvanced()` function */
32
- export type FetchAdvancedOpts = RequestInit & Partial<{
32
+ export type FetchAdvancedOpts = Omit<RequestInit & Partial<{
33
33
  /** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
34
34
  timeout: number;
35
- }>;
35
+ }>, "signal">;
36
36
  /** Calls the fetch API with special options like a timeout */
37
- export declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
37
+ export declare function fetchAdvanced(input: RequestInfo | URL, options?: FetchAdvancedOpts): Promise<Response>;
38
38
  /**
39
39
  * Inserts the passed values into a string at the respective placeholders.
40
40
  * The placeholder format is `%n`, where `n` is the 1-indexed argument number.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
- "version": "4.1.0",
3
+ "version": "4.2.1",
4
4
  "description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",