@sv443-network/userutils 8.3.3 → 9.0.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.
@@ -7,8 +7,8 @@
7
7
 
8
8
  // ==UserLibrary==
9
9
  // @name UserUtils
10
- // @description Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and more
11
- // @version 8.3.3
10
+ // @description Lightweight library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and much more
11
+ // @version 9.0.0
12
12
  // @license MIT
13
13
  // @copyright Sv443 (https://github.com/Sv443)
14
14
 
@@ -48,10 +48,7 @@ var UserUtils = (function (exports) {
48
48
  }
49
49
  return target;
50
50
  };
51
- var __publicField = (obj, key, value) => {
52
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
53
- return value;
54
- };
51
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
55
52
  var __async = (__this, __arguments, generator) => {
56
53
  return new Promise((resolve, reject) => {
57
54
  var fulfilled = (value) => {
@@ -75,14 +72,17 @@ var UserUtils = (function (exports) {
75
72
 
76
73
  // lib/math.ts
77
74
  function clamp(value, min, max) {
75
+ if (typeof max !== "number") {
76
+ max = min;
77
+ min = 0;
78
+ }
78
79
  return Math.max(Math.min(value, max), min);
79
80
  }
80
81
  function mapRange(value, range1min, range1max, range2min, range2max) {
81
- if (typeof range2min === "undefined" || range2max === void 0) {
82
+ if (typeof range2min === "undefined" || typeof range2max === "undefined") {
82
83
  range2max = range1max;
83
- range2min = 0;
84
84
  range1max = range1min;
85
- range1min = 0;
85
+ range2min = range1min = 0;
86
86
  }
87
87
  if (Number(range1min) === 0 && Number(range2min) === 0)
88
88
  return value * (range2max / range1max);
@@ -96,7 +96,7 @@ var UserUtils = (function (exports) {
96
96
  min = 0;
97
97
  [max] = args;
98
98
  } else
99
- throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof args[0]}" and "${typeof args[1]}"`);
99
+ throw new TypeError(`Wrong parameter(s) provided - expected (number, boolean|undefined) or (number, number, boolean|undefined) but got (${args.map((a) => typeof a).join(", ")}) instead`);
100
100
  if (typeof args[2] === "boolean")
101
101
  enhancedEntropy = args[2];
102
102
  else if (typeof args[1] === "boolean")
@@ -112,11 +112,19 @@ var UserUtils = (function (exports) {
112
112
  crypto.getRandomValues(uintArr);
113
113
  return Number(Array.from(
114
114
  uintArr,
115
- (v) => Math.round(mapRange(v, 0, 255, min, max)).toString(10).substring(0, 1)
115
+ (v) => Math.round(mapRange(v, 0, 255, min, max)).toString(10)
116
116
  ).join(""));
117
117
  } else
118
118
  return Math.floor(Math.random() * (max - min + 1)) + min;
119
119
  }
120
+ function digitCount(num) {
121
+ num = Number(!["string", "number"].includes(typeof num) ? String(num) : num);
122
+ if (typeof num === "number" && isNaN(num))
123
+ return NaN;
124
+ return num === 0 ? 1 : Math.floor(
125
+ Math.log10(Math.abs(Number(num))) + 1
126
+ );
127
+ }
120
128
 
121
129
  // lib/array.ts
122
130
  function randomItem(array) {
@@ -124,14 +132,14 @@ var UserUtils = (function (exports) {
124
132
  }
125
133
  function randomItemIndex(array) {
126
134
  if (array.length === 0)
127
- return [void 0, void 0];
135
+ return [undefined, undefined];
128
136
  const idx = randRange(array.length - 1);
129
137
  return [array[idx], idx];
130
138
  }
131
139
  function takeRandomItem(arr) {
132
140
  const [itm, idx] = randomItemIndex(arr);
133
- if (idx === void 0)
134
- return void 0;
141
+ if (idx === undefined)
142
+ return undefined;
135
143
  arr.splice(idx, 1);
136
144
  return itm;
137
145
  }
@@ -149,7 +157,7 @@ var UserUtils = (function (exports) {
149
157
  // lib/colors.ts
150
158
  function hexToRgb(hex) {
151
159
  hex = (hex.startsWith("#") ? hex.slice(1) : hex).trim();
152
- const a = hex.length === 8 || hex.length === 4 ? parseInt(hex.slice(-(hex.length / 4)), 16) / (hex.length === 8 ? 255 : 15) : void 0;
160
+ const a = hex.length === 8 || hex.length === 4 ? parseInt(hex.slice(-(hex.length / 4)), 16) / (hex.length === 8 ? 255 : 15) : undefined;
153
161
  if (!isNaN(Number(a)))
154
162
  hex = hex.slice(0, -(hex.length / 4));
155
163
  if (hex.length === 3 || hex.length === 4)
@@ -158,7 +166,7 @@ var UserUtils = (function (exports) {
158
166
  const r = bigint >> 16 & 255;
159
167
  const g = bigint >> 8 & 255;
160
168
  const b = bigint & 255;
161
- return [clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255), typeof a === "number" ? clamp(a, 0, 1) : void 0];
169
+ return [clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255), typeof a === "number" ? clamp(a, 0, 1) : undefined];
162
170
  }
163
171
  function rgbToHex(red, green, blue, alpha, withHash = true, upperCase = false) {
164
172
  const toHexVal = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, "0")[upperCase ? "toUpperCase" : "toLowerCase"]();
@@ -181,7 +189,7 @@ var UserUtils = (function (exports) {
181
189
  if (isHexCol)
182
190
  [r, g, b, a] = hexToRgb(color);
183
191
  else if (color.startsWith("rgb")) {
184
- const rgbValues = (_a = color.match(/\d+(\.\d+)?/g)) == null ? void 0 : _a.map(Number);
192
+ const rgbValues = (_a = color.match(/\d+(\.\d+)?/g)) == null ? undefined : _a.map(Number);
185
193
  if (!rgbValues)
186
194
  throw new Error("Invalid RGB/RGBA color format");
187
195
  [r, g, b, a] = rgbValues;
@@ -229,26 +237,32 @@ var UserUtils = (function (exports) {
229
237
  }));
230
238
  return Promise.allSettled(promises);
231
239
  }
232
- function openInNewTab(href, background) {
240
+ function openInNewTab(href, background, additionalProps) {
241
+ var _a;
233
242
  try {
234
- GM.openInTab(href, background);
243
+ (_a = GM.openInTab) == null ? void 0 : _a.call(GM, href, background);
235
244
  } catch (e) {
236
245
  const openElem = document.createElement("a");
237
- Object.assign(openElem, {
246
+ Object.assign(openElem, __spreadValues({
238
247
  className: "userutils-open-in-new-tab",
239
248
  target: "_blank",
240
249
  rel: "noopener noreferrer",
250
+ tabIndex: -1,
251
+ ariaHidden: "true",
241
252
  href
253
+ }, additionalProps));
254
+ Object.assign(openElem.style, {
255
+ display: "none",
256
+ pointerEvents: "none"
242
257
  });
243
- openElem.style.display = "none";
244
258
  document.body.appendChild(openElem);
245
259
  openElem.click();
246
- setTimeout(openElem.remove, 50);
260
+ setTimeout(openElem.remove, 0);
247
261
  }
248
262
  }
249
263
  function interceptEvent(eventObject, eventName, predicate = () => true) {
250
264
  var _a;
251
- if ((eventObject === window || eventObject === getUnsafeWindow()) && ((_a = GM == null ? void 0 : GM.info) == null ? void 0 : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey")
265
+ if ((eventObject === window || eventObject === getUnsafeWindow()) && ((_a = GM == null ? undefined : GM.info) == null ? undefined : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey")
252
266
  throw new Error("Intercepting window events is not supported on FireMonkey due to the isolated context the userscript runs in.");
253
267
  Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
254
268
  if (isNaN(Error.stackTraceLimit))
@@ -256,7 +270,7 @@ var UserUtils = (function (exports) {
256
270
  (function(original) {
257
271
  eventObject.__proto__.addEventListener = function(...args) {
258
272
  var _a2, _b;
259
- const origListener = typeof args[1] === "function" ? args[1] : (_b = (_a2 = args[1]) == null ? void 0 : _a2.handleEvent) != null ? _b : () => void 0;
273
+ const origListener = typeof args[1] === "function" ? args[1] : (_b = (_a2 = args[1]) == null ? undefined : _a2.handleEvent) != null ? _b : () => undefined;
260
274
  args[1] = function(...a) {
261
275
  if (args[0] === eventName && predicate(Array.isArray(a) ? a[0] : a))
262
276
  return;
@@ -284,12 +298,12 @@ var UserUtils = (function (exports) {
284
298
  Object.defineProperty(element, property, {
285
299
  get: function() {
286
300
  var _a;
287
- return (_a = descriptor == null ? void 0 : descriptor.get) == null ? void 0 : _a.apply(this, arguments);
301
+ return (_a = descriptor == null ? undefined : descriptor.get) == null ? undefined : _a.apply(this, arguments);
288
302
  },
289
303
  set: function() {
290
304
  var _a;
291
305
  const oldValue = this[property];
292
- (_a = descriptor == null ? void 0 : descriptor.set) == null ? void 0 : _a.apply(this, arguments);
306
+ (_a = descriptor == null ? undefined : descriptor.set) == null ? undefined : _a.apply(this, arguments);
293
307
  const newValue = this[property];
294
308
  if (typeof callback === "function") {
295
309
  callback.bind(this, oldValue, newValue);
@@ -301,7 +315,7 @@ var UserUtils = (function (exports) {
301
315
  }
302
316
  function getSiblingsFrame(refElement, siblingAmount, refElementAlignment = "center-top", includeRef = true) {
303
317
  var _a, _b;
304
- const siblings = [...(_b = (_a = refElement.parentNode) == null ? void 0 : _a.childNodes) != null ? _b : []];
318
+ const siblings = [...(_b = (_a = refElement.parentNode) == null ? undefined : _a.childNodes) != null ? _b : []];
305
319
  const elemSiblIdx = siblings.indexOf(refElement);
306
320
  if (elemSiblIdx === -1)
307
321
  throw new Error("Element doesn't have a parent node");
@@ -323,12 +337,12 @@ var UserUtils = (function (exports) {
323
337
  var ttPolicy;
324
338
  function setInnerHtmlUnsafe(element, html) {
325
339
  var _a, _b, _c;
326
- if (!ttPolicy && typeof ((_a = window == null ? void 0 : window.trustedTypes) == null ? void 0 : _a.createPolicy) === "function") {
340
+ if (!ttPolicy && typeof ((_a = window == null ? undefined : window.trustedTypes) == null ? undefined : _a.createPolicy) === "function") {
327
341
  ttPolicy = window.trustedTypes.createPolicy("_uu_set_innerhtml_unsafe", {
328
342
  createHTML: (unsafeHtml) => unsafeHtml
329
343
  });
330
344
  }
331
- element.innerHTML = (_c = (_b = ttPolicy == null ? void 0 : ttPolicy.createHTML) == null ? void 0 : _b.call(ttPolicy, html)) != null ? _c : html;
345
+ element.innerHTML = (_c = (_b = ttPolicy == null ? undefined : ttPolicy.createHTML) == null ? undefined : _b.call(ttPolicy, html)) != null ? _c : html;
332
346
  return element;
333
347
  }
334
348
 
@@ -404,8 +418,8 @@ var UserUtils = (function (exports) {
404
418
  * Creates an instance of DataStore to manage a sync & async database that is cached in memory and persistently saved across sessions.
405
419
  * Supports migrating data from older versions to newer ones and populating the cache with default data if no persistent data is found.
406
420
  *
407
- * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue` if the storageMethod is left as the default of `"GM"`
408
- * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
421
+ * - ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue` if the storageMethod is left as the default of `"GM"`
422
+ * - ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
409
423
  *
410
424
  * @template TData The type of the data that is saved in persistent storage for the currently set format version (will be automatically inferred from `defaultData` if not provided) - **This has to be a JSON-compatible object!** (no undefined, circular references, etc.)
411
425
  * @param options The options for this DataStore instance
@@ -512,7 +526,7 @@ var UserUtils = (function (exports) {
512
526
  * The in-memory cache will be left untouched, so you may still access the data with {@linkcode getData()}
513
527
  * Calling {@linkcode loadData()} or {@linkcode setData()} after this method was called will recreate persistent storage with the cached or default data.
514
528
  *
515
- * ⚠️ This requires the additional directive `@grant GM.deleteValue` if the storageMethod is left as the default of `"GM"`
529
+ * - ⚠️ This requires the additional directive `@grant GM.deleteValue` if the storageMethod is left as the default of `"GM"`
516
530
  */
517
531
  deleteData() {
518
532
  return __async(this, null, function* () {
@@ -577,7 +591,7 @@ var UserUtils = (function (exports) {
577
591
  const data = yield this.getValue(`_uucfg-${id}`, JSON.stringify(this.defaultData));
578
592
  const fmtVer = Number(yield this.getValue(`_uucfgver-${id}`, NaN));
579
593
  const isEncoded = Boolean(yield this.getValue(`_uucfgenc-${id}`, false));
580
- if (data === void 0 || isNaN(fmtVer))
594
+ if (data === undefined || isNaN(fmtVer))
581
595
  return;
582
596
  const parsed = yield this.deserializeData(data, isEncoded);
583
597
  yield Promise.allSettled([
@@ -607,7 +621,7 @@ var UserUtils = (function (exports) {
607
621
  /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
608
622
  deserializeData(data, useEncoding = true) {
609
623
  return __async(this, null, function* () {
610
- let decRes = this.encodingEnabled() && useEncoding ? this.decodeData(data) : void 0;
624
+ let decRes = this.encodingEnabled() && useEncoding ? this.decodeData(data) : undefined;
611
625
  if (decRes instanceof Promise)
612
626
  decRes = yield decRes;
613
627
  return JSON.parse(decRes != null ? decRes : data);
@@ -619,7 +633,7 @@ var UserUtils = (function (exports) {
619
633
  return JSON.parse(JSON.stringify(obj));
620
634
  }
621
635
  //#region storage
622
- /** Gets a value from persistent storage - can be overwritten in a subclass if you want to use something other than GM storage */
636
+ /** Gets a value from persistent storage - can be overwritten in a subclass if you want to use something other than the default storage methods */
623
637
  getValue(name, defaultValue) {
624
638
  return __async(this, null, function* () {
625
639
  var _a, _b;
@@ -634,7 +648,7 @@ var UserUtils = (function (exports) {
634
648
  });
635
649
  }
636
650
  /**
637
- * Sets a value in persistent storage - can be overwritten in a subclass if you want to use something other than GM storage.
651
+ * Sets a value in persistent storage - can be overwritten in a subclass if you want to use something other than the default storage methods.
638
652
  * The default storage engines will stringify all passed values like numbers or booleans, so be aware of that.
639
653
  */
640
654
  setValue(name, value) {
@@ -649,7 +663,7 @@ var UserUtils = (function (exports) {
649
663
  }
650
664
  });
651
665
  }
652
- /** Deletes a value from persistent storage - can be overwritten in a subclass if you want to use something other than GM storage */
666
+ /** Deletes a value from persistent storage - can be overwritten in a subclass if you want to use something other than the default storage methods */
653
667
  deleteValue(name) {
654
668
  return __async(this, null, function* () {
655
669
  switch (this.storageMethod) {
@@ -687,7 +701,7 @@ var UserUtils = (function (exports) {
687
701
  serializeStore(storeInst) {
688
702
  return __async(this, null, function* () {
689
703
  const data = storeInst.encodingEnabled() ? yield storeInst.encodeData(JSON.stringify(storeInst.getData())) : JSON.stringify(storeInst.getData());
690
- const checksum = this.options.addChecksum ? yield this.calcChecksum(data) : void 0;
704
+ const checksum = this.options.addChecksum ? yield this.calcChecksum(data) : undefined;
691
705
  return {
692
706
  id: storeInst.id,
693
707
  data,
@@ -766,10 +780,10 @@ Has: ${checksum}`);
766
780
  }
767
781
  };
768
782
 
769
- // node_modules/nanoevents/index.js
783
+ // node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
770
784
  var createNanoEvents = () => ({
771
785
  emit(event, ...args) {
772
- for (let i = 0, callbacks = this.events[event] || [], length = callbacks.length; i < length; i++) {
786
+ for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
773
787
  callbacks[i](...args);
774
788
  }
775
789
  },
@@ -779,7 +793,7 @@ Has: ${checksum}`);
779
793
  ((_a = this.events)[event] || (_a[event] = [])).push(cb);
780
794
  return () => {
781
795
  var _a2;
782
- this.events[event] = (_a2 = this.events[event]) == null ? void 0 : _a2.filter((i) => cb !== i);
796
+ this.events[event] = (_a2 = this.events[event]) == null ? undefined : _a2.filter((i) => cb !== i);
783
797
  };
784
798
  }
785
799
  });
@@ -813,7 +827,7 @@ Has: ${checksum}`);
813
827
  let unsub;
814
828
  const onceProxy = (...args) => {
815
829
  unsub();
816
- cb == null ? void 0 : cb(...args);
830
+ cb == null ? undefined : cb(...args);
817
831
  resolve(args);
818
832
  };
819
833
  unsub = this.on(event, onceProxy);
@@ -835,6 +849,106 @@ Has: ${checksum}`);
835
849
  }
836
850
  };
837
851
 
852
+ // lib/Debouncer.ts
853
+ var Debouncer = class extends NanoEmitter {
854
+ /**
855
+ * Creates a new debouncer with the specified timeout and edge type.
856
+ * @param timeout Timeout in milliseconds between letting through calls - defaults to 200
857
+ * @param type The edge type to use for the debouncer - see {@linkcode DebouncerType} for details or [the documentation for an explanation and diagram](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer) - defaults to "immediate"
858
+ */
859
+ constructor(timeout = 200, type = "immediate") {
860
+ super();
861
+ this.timeout = timeout;
862
+ this.type = type;
863
+ /** All registered listener functions and the time they were attached */
864
+ __publicField(this, "listeners", []);
865
+ /** The currently active timeout */
866
+ __publicField(this, "activeTimeout");
867
+ /** The latest queued call */
868
+ __publicField(this, "queuedCall");
869
+ }
870
+ //#region listeners
871
+ /** Adds a listener function that will be called on timeout */
872
+ addListener(fn) {
873
+ this.listeners.push(fn);
874
+ }
875
+ /** Removes the listener with the specified function reference */
876
+ removeListener(fn) {
877
+ const idx = this.listeners.findIndex((l) => l === fn);
878
+ idx !== -1 && this.listeners.splice(idx, 1);
879
+ }
880
+ /** Removes all listeners */
881
+ removeAllListeners() {
882
+ this.listeners = [];
883
+ }
884
+ //#region timeout
885
+ /** Sets the timeout for the debouncer */
886
+ setTimeout(timeout) {
887
+ this.emit("change", this.timeout = timeout, this.type);
888
+ }
889
+ /** Returns the current timeout */
890
+ getTimeout() {
891
+ return this.timeout;
892
+ }
893
+ /** Whether the timeout is currently active, meaning any latest call to the {@linkcode call()} method will be queued */
894
+ isTimeoutActive() {
895
+ return typeof this.activeTimeout !== "undefined";
896
+ }
897
+ //#region type
898
+ /** Sets the edge type for the debouncer */
899
+ setType(type) {
900
+ this.emit("change", this.timeout, this.type = type);
901
+ }
902
+ /** Returns the current edge type */
903
+ getType() {
904
+ return this.type;
905
+ }
906
+ //#region call
907
+ /** Use this to call the debouncer with the specified arguments that will be passed to all listener functions registered with {@linkcode addListener()} */
908
+ call(...args) {
909
+ const cl = (...a) => {
910
+ this.queuedCall = undefined;
911
+ this.emit("call", ...a);
912
+ this.listeners.forEach((l) => l.apply(this, a));
913
+ };
914
+ const setRepeatTimeout = () => {
915
+ this.activeTimeout = setTimeout(() => {
916
+ if (this.queuedCall) {
917
+ this.queuedCall();
918
+ setRepeatTimeout();
919
+ } else
920
+ this.activeTimeout = undefined;
921
+ }, this.timeout);
922
+ };
923
+ switch (this.type) {
924
+ case "immediate":
925
+ if (typeof this.activeTimeout === "undefined") {
926
+ cl(...args);
927
+ setRepeatTimeout();
928
+ } else
929
+ this.queuedCall = () => cl(...args);
930
+ break;
931
+ case "idle":
932
+ if (this.activeTimeout)
933
+ clearTimeout(this.activeTimeout);
934
+ this.activeTimeout = setTimeout(() => {
935
+ cl(...args);
936
+ this.activeTimeout = undefined;
937
+ }, this.timeout);
938
+ break;
939
+ default:
940
+ throw new Error(`Invalid debouncer type: ${this.type}`);
941
+ }
942
+ }
943
+ };
944
+ function debounce(fn, timeout = 200, type = "immediate") {
945
+ const debouncer = new Debouncer(timeout, type);
946
+ debouncer.addListener(fn);
947
+ const func = (...args) => debouncer.call(...args);
948
+ func.debouncer = debouncer;
949
+ return func;
950
+ }
951
+
838
952
  // lib/Dialog.ts
839
953
  var defaultDialogCss = `.uu-no-select {
840
954
  user-select: none;
@@ -1052,7 +1166,7 @@ Has: ${checksum}`);
1052
1166
  `#uu-style-dialog-${this.id}`
1053
1167
  ];
1054
1168
  for (const sel of clearSelectors)
1055
- (_a = document.querySelector(sel)) == null ? void 0 : _a.remove();
1169
+ (_a = document.querySelector(sel)) == null ? undefined : _a.remove();
1056
1170
  this.events.emit("clear");
1057
1171
  }
1058
1172
  /** Clears the DOM of the dialog and then renders it again */
@@ -1069,8 +1183,8 @@ Has: ${checksum}`);
1069
1183
  open(e) {
1070
1184
  return __async(this, null, function* () {
1071
1185
  var _a;
1072
- e == null ? void 0 : e.preventDefault();
1073
- e == null ? void 0 : e.stopImmediatePropagation();
1186
+ e == null ? undefined : e.preventDefault();
1187
+ e == null ? undefined : e.stopImmediatePropagation();
1074
1188
  if (this.isOpen())
1075
1189
  return;
1076
1190
  this.dialogOpen = true;
@@ -1088,7 +1202,7 @@ Has: ${checksum}`);
1088
1202
  openDialogs.unshift(this.id);
1089
1203
  for (const dialogId of openDialogs)
1090
1204
  if (dialogId !== this.id)
1091
- (_a = document.querySelector(`#uu-${dialogId}-dialog-bg`)) == null ? void 0 : _a.setAttribute("inert", "true");
1205
+ (_a = document.querySelector(`#uu-${dialogId}-dialog-bg`)) == null ? undefined : _a.setAttribute("inert", "true");
1092
1206
  document.body.classList.remove("uu-no-select");
1093
1207
  document.body.setAttribute("inert", "true");
1094
1208
  this.events.emit("open");
@@ -1098,8 +1212,8 @@ Has: ${checksum}`);
1098
1212
  /** Closes the dialog - prevents default action and immediate propagation of the passed event */
1099
1213
  close(e) {
1100
1214
  var _a, _b;
1101
- e == null ? void 0 : e.preventDefault();
1102
- e == null ? void 0 : e.stopImmediatePropagation();
1215
+ e == null ? undefined : e.preventDefault();
1216
+ e == null ? undefined : e.stopImmediatePropagation();
1103
1217
  if (!this.isOpen())
1104
1218
  return;
1105
1219
  this.dialogOpen = false;
@@ -1112,7 +1226,7 @@ Has: ${checksum}`);
1112
1226
  openDialogs.splice(openDialogs.indexOf(this.id), 1);
1113
1227
  exports.currentDialogId = (_a = openDialogs[0]) != null ? _a : null;
1114
1228
  if (exports.currentDialogId)
1115
- (_b = document.querySelector(`#uu-${exports.currentDialogId}-dialog-bg`)) == null ? void 0 : _b.removeAttribute("inert");
1229
+ (_b = document.querySelector(`#uu-${exports.currentDialogId}-dialog-bg`)) == null ? undefined : _b.removeAttribute("inert");
1116
1230
  if (openDialogs.length === 0) {
1117
1231
  document.body.classList.add("uu-no-select");
1118
1232
  document.body.removeAttribute("inert");
@@ -1156,7 +1270,7 @@ Has: ${checksum}`);
1156
1270
  if (this.options.closeOnBgClick) {
1157
1271
  bgElem.addEventListener("click", (e) => {
1158
1272
  var _a;
1159
- if (this.isOpen() && ((_a = e.target) == null ? void 0 : _a.id) === `uu-${this.id}-dialog-bg`)
1273
+ if (this.isOpen() && ((_a = e.target) == null ? undefined : _a.id) === `uu-${this.id}-dialog-bg`)
1160
1274
  this.close(e);
1161
1275
  });
1162
1276
  }
@@ -1181,14 +1295,13 @@ Has: ${checksum}`);
1181
1295
  if (interactionKeys.includes(e.key)) {
1182
1296
  preventDefault && e.preventDefault();
1183
1297
  stopPropagation && e.stopPropagation();
1184
- } else
1185
- return;
1298
+ } else return;
1186
1299
  } else if (e instanceof MouseEvent) {
1187
1300
  preventDefault && e.preventDefault();
1188
1301
  stopPropagation && e.stopPropagation();
1189
1302
  }
1190
- (listenerOpts == null ? void 0 : listenerOpts.once) && e.type === "keydown" && elem.removeEventListener("click", proxListener, listenerOpts);
1191
- (listenerOpts == null ? void 0 : listenerOpts.once) && e.type === "click" && elem.removeEventListener("keydown", proxListener, listenerOpts);
1303
+ (listenerOpts == null ? undefined : listenerOpts.once) && e.type === "keydown" && elem.removeEventListener("click", proxListener, listenerOpts);
1304
+ (listenerOpts == null ? undefined : listenerOpts.once) && e.type === "click" && elem.removeEventListener("keydown", proxListener, listenerOpts);
1192
1305
  listener(e);
1193
1306
  };
1194
1307
  elem.addEventListener("click", proxListener, listenerOpts);
@@ -1198,8 +1311,8 @@ Has: ${checksum}`);
1198
1311
  getDialogContent() {
1199
1312
  return __async(this, null, function* () {
1200
1313
  var _a, _b, _c, _d;
1201
- const header = (_b = (_a = this.options).renderHeader) == null ? void 0 : _b.call(_a);
1202
- const footer = (_d = (_c = this.options).renderFooter) == null ? void 0 : _d.call(_c);
1314
+ const header = (_b = (_a = this.options).renderHeader) == null ? undefined : _b.call(_a);
1315
+ const footer = (_d = (_c = this.options).renderFooter) == null ? undefined : _d.call(_c);
1203
1316
  const dialogWrapperEl = document.createElement("div");
1204
1317
  dialogWrapperEl.id = `uu-${this.id}-dialog`;
1205
1318
  dialogWrapperEl.classList.add("uu-dialog");
@@ -1265,7 +1378,7 @@ Has: ${checksum}`);
1265
1378
  return input.replace(/%\d/gm, (match) => {
1266
1379
  var _a, _b;
1267
1380
  const argIndex = Number(match.substring(1)) - 1;
1268
- return (_b = (_a = values[argIndex]) != null ? _a : match) == null ? void 0 : _b.toString();
1381
+ return (_b = (_a = values[argIndex]) != null ? _a : match) == null ? undefined : _b.toString();
1269
1382
  });
1270
1383
  }
1271
1384
  function pauseFor(time) {
@@ -1273,27 +1386,13 @@ Has: ${checksum}`);
1273
1386
  setTimeout(() => res(), time);
1274
1387
  });
1275
1388
  }
1276
- function debounce(func, timeout = 300, edge = "falling") {
1277
- let id;
1278
- return function(...args) {
1279
- if (edge === "rising") {
1280
- if (!id) {
1281
- func.apply(this, args);
1282
- id = setTimeout(() => id = void 0, timeout);
1283
- }
1284
- } else {
1285
- clearTimeout(id);
1286
- id = setTimeout(() => func.apply(this, args), timeout);
1287
- }
1288
- };
1289
- }
1290
1389
  function fetchAdvanced(_0) {
1291
1390
  return __async(this, arguments, function* (input, options = {}) {
1292
1391
  var _a;
1293
1392
  const { timeout = 1e4 } = options;
1294
1393
  const { signal, abort } = new AbortController();
1295
- (_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abort);
1296
- let signalOpts = {}, id = void 0;
1394
+ (_a = options.signal) == null ? undefined : _a.addEventListener("abort", abort);
1395
+ let signalOpts = {}, id = undefined;
1297
1396
  if (timeout >= 0) {
1298
1397
  id = setTimeout(() => abort(), timeout);
1299
1398
  signalOpts = { signal };
@@ -1308,6 +1407,18 @@ Has: ${checksum}`);
1308
1407
  }
1309
1408
  });
1310
1409
  }
1410
+ function consumeGen(valGen) {
1411
+ return __async(this, null, function* () {
1412
+ return yield typeof valGen === "function" ? valGen() : valGen;
1413
+ });
1414
+ }
1415
+ function consumeStringGen(strGen) {
1416
+ return __async(this, null, function* () {
1417
+ return typeof strGen === "string" ? strGen : String(
1418
+ typeof strGen === "function" ? yield strGen() : strGen
1419
+ );
1420
+ });
1421
+ }
1311
1422
 
1312
1423
  // lib/SelectorObserver.ts
1313
1424
  var domLoaded = false;
@@ -1324,12 +1435,12 @@ Has: ${checksum}`);
1324
1435
  this.listenerMap = /* @__PURE__ */ new Map();
1325
1436
  const _a = options, {
1326
1437
  defaultDebounce,
1327
- defaultDebounceEdge,
1438
+ defaultDebounceType,
1328
1439
  disableOnNoListeners,
1329
1440
  enableOnAddListener
1330
1441
  } = _a, observerOptions = __objRest(_a, [
1331
1442
  "defaultDebounce",
1332
- "defaultDebounceEdge",
1443
+ "defaultDebounceType",
1333
1444
  "disableOnNoListeners",
1334
1445
  "enableOnAddListener"
1335
1446
  ]);
@@ -1339,7 +1450,7 @@ Has: ${checksum}`);
1339
1450
  }, observerOptions);
1340
1451
  this.customOptions = {
1341
1452
  defaultDebounce: defaultDebounce != null ? defaultDebounce : 0,
1342
- defaultDebounceEdge: defaultDebounceEdge != null ? defaultDebounceEdge : "rising",
1453
+ defaultDebounceType: defaultDebounceType != null ? defaultDebounceType : "immediate",
1343
1454
  disableOnNoListeners: disableOnNoListeners != null ? disableOnNoListeners : false,
1344
1455
  enableOnAddListener: enableOnAddListener != null ? enableOnAddListener : true
1345
1456
  };
@@ -1383,7 +1494,7 @@ Has: ${checksum}`);
1383
1494
  this.removeListener(selector, options);
1384
1495
  }
1385
1496
  }
1386
- if (((_a = this.listenerMap.get(selector)) == null ? void 0 : _a.length) === 0)
1497
+ if (((_a = this.listenerMap.get(selector)) == null ? undefined : _a.length) === 0)
1387
1498
  this.listenerMap.delete(selector);
1388
1499
  if (this.listenerMap.size === 0 && this.customOptions.disableOnNoListeners)
1389
1500
  this.disable();
@@ -1409,7 +1520,7 @@ Has: ${checksum}`);
1409
1520
  options.listener = debounce(
1410
1521
  options.listener,
1411
1522
  options.debounce || this.customOptions.defaultDebounce,
1412
- options.debounceEdge || this.customOptions.defaultDebounceEdge
1523
+ options.debounceType || this.customOptions.defaultDebounceType
1413
1524
  );
1414
1525
  }
1415
1526
  if (this.listenerMap.has(selector))
@@ -1427,7 +1538,7 @@ Has: ${checksum}`);
1427
1538
  if (!this.enabled)
1428
1539
  return;
1429
1540
  this.enabled = false;
1430
- (_a = this.observer) == null ? void 0 : _a.disconnect();
1541
+ (_a = this.observer) == null ? undefined : _a.disconnect();
1431
1542
  }
1432
1543
  /**
1433
1544
  * Enables or reenables the observation of the child elements.
@@ -1440,7 +1551,7 @@ Has: ${checksum}`);
1440
1551
  if (this.enabled || !baseElement)
1441
1552
  return false;
1442
1553
  this.enabled = true;
1443
- (_a = this.observer) == null ? void 0 : _a.observe(baseElement, this.observerOptions);
1554
+ (_a = this.observer) == null ? undefined : _a.observe(baseElement, this.observerOptions);
1444
1555
  if (immediatelyCheckSelectors)
1445
1556
  this.checkAllSelectors();
1446
1557
  return true;
@@ -1487,38 +1598,169 @@ Has: ${checksum}`);
1487
1598
 
1488
1599
  // lib/translation.ts
1489
1600
  var trans = {};
1490
- var curLang;
1491
- var trLang = (language, key, ...args) => {
1492
- var _a;
1493
- if (!language)
1494
- return key;
1495
- const trText = (_a = trans[language]) == null ? void 0 : _a[key];
1496
- if (!trText)
1497
- return key;
1498
- if (args.length > 0 && trText.match(/%\d/)) {
1499
- return insertValues(trText, ...args);
1500
- }
1501
- return trText;
1502
- };
1503
- function tr(key, ...args) {
1504
- return trLang(curLang, key, ...args);
1601
+ var valTransforms = [];
1602
+ var fallbackLang;
1603
+ function translate(language, key, ...trArgs) {
1604
+ if (typeof language !== "string")
1605
+ language = fallbackLang != null ? fallbackLang : "";
1606
+ const trObj = trans[language];
1607
+ if (typeof language !== "string" || language.length === 0 || typeof trObj !== "object" || trObj === null)
1608
+ return fallbackLang ? translate(fallbackLang, key, ...trArgs) : key;
1609
+ const transformTrVal = (trKey, trValue) => {
1610
+ const tfs = valTransforms.filter(({ regex }) => new RegExp(regex).test(trValue));
1611
+ if (tfs.length === 0)
1612
+ return trValue;
1613
+ let retStr = String(trValue);
1614
+ for (const tf of tfs) {
1615
+ const re = new RegExp(tf.regex);
1616
+ const matches = [];
1617
+ let execRes;
1618
+ while ((execRes = re.exec(trValue)) !== null) {
1619
+ if (matches.some((m) => m[0] === (execRes == null ? undefined : execRes[0])))
1620
+ break;
1621
+ matches.push(execRes);
1622
+ }
1623
+ retStr = String(tf.fn({
1624
+ language,
1625
+ trValue,
1626
+ currentValue: retStr,
1627
+ matches,
1628
+ trKey,
1629
+ trArgs
1630
+ }));
1631
+ }
1632
+ return retStr;
1633
+ };
1634
+ const keyParts = key.split(".");
1635
+ let value = trObj;
1636
+ for (const part of keyParts) {
1637
+ if (typeof value !== "object" || value === null) {
1638
+ value = undefined;
1639
+ break;
1640
+ }
1641
+ value = value == null ? undefined : value[part];
1642
+ }
1643
+ if (typeof value === "string")
1644
+ return transformTrVal(key, value);
1645
+ value = trObj == null ? undefined : trObj[key];
1646
+ if (typeof value === "string")
1647
+ return transformTrVal(key, value);
1648
+ return fallbackLang ? translate(fallbackLang, key, ...trArgs) : key;
1505
1649
  }
1506
- tr.forLang = trLang;
1507
- tr.addLanguage = (language, translations) => {
1508
- trans[language] = translations;
1509
- };
1510
- tr.setLanguage = (language) => {
1511
- curLang = language;
1512
- };
1513
- tr.getLanguage = () => {
1514
- return curLang;
1650
+ function trFor(language, key, ...args) {
1651
+ const txt = translate(language, key, ...args);
1652
+ if (txt === key)
1653
+ return fallbackLang ? translate(fallbackLang, key, ...args) : key;
1654
+ return txt;
1655
+ }
1656
+ function useTr(language) {
1657
+ return (key, ...args) => translate(language, key, ...args);
1658
+ }
1659
+ function hasKey(language = fallbackLang != null ? fallbackLang : "", key) {
1660
+ return tr.for(language, key) !== key;
1661
+ }
1662
+ function addTranslations(language, translations) {
1663
+ trans[language] = JSON.parse(JSON.stringify(translations));
1664
+ }
1665
+ function getTranslations(language = fallbackLang != null ? fallbackLang : "") {
1666
+ return trans[language];
1667
+ }
1668
+ var deleteTranslations = (language) => {
1669
+ if (language in trans) {
1670
+ delete trans[language];
1671
+ return true;
1672
+ }
1673
+ return false;
1515
1674
  };
1516
- tr.getTranslations = (language) => {
1517
- return trans[language != null ? language : curLang];
1675
+ function setFallbackLanguage(fallbackLanguage) {
1676
+ fallbackLang = fallbackLanguage;
1677
+ }
1678
+ function getFallbackLanguage() {
1679
+ return fallbackLang;
1680
+ }
1681
+ function addTransform(transform) {
1682
+ const [pattern, fn] = transform;
1683
+ valTransforms.push({
1684
+ fn,
1685
+ regex: typeof pattern === "string" ? new RegExp(pattern, "gm") : pattern
1686
+ });
1687
+ }
1688
+ function deleteTransform(patternOrFn) {
1689
+ const idx = valTransforms.findIndex(
1690
+ (t) => typeof patternOrFn === "function" ? t.fn === patternOrFn : typeof patternOrFn === "string" ? t.regex.source === patternOrFn : t.regex === patternOrFn
1691
+ );
1692
+ if (idx !== -1) {
1693
+ valTransforms.splice(idx, 1);
1694
+ return true;
1695
+ }
1696
+ return false;
1697
+ }
1698
+ var templateLiteralTransform = [
1699
+ /\$\{([a-zA-Z0-9$_-]+)\}/gm,
1700
+ ({ matches, trArgs, trValue }) => {
1701
+ const patternStart = "${", patternEnd = "}", patternRegex = /\$\{.+\}/m;
1702
+ let str = String(trValue);
1703
+ const eachKeyInTrString = (keys) => keys.every((key) => trValue.includes(`${patternStart}${key}${patternEnd}`));
1704
+ const namedMapping = () => {
1705
+ var _a;
1706
+ if (!str.includes(patternStart) || typeof trArgs[0] === "undefined" || typeof trArgs[0] !== "object" || !eachKeyInTrString(Object.keys((_a = trArgs[0]) != null ? _a : {})))
1707
+ return;
1708
+ for (const match of matches) {
1709
+ const repl = match[1] !== undefined ? trArgs[0][match[1]] : undefined;
1710
+ if (typeof repl !== "undefined")
1711
+ str = str.replace(match[0], String(repl));
1712
+ }
1713
+ };
1714
+ const positionalMapping = () => {
1715
+ if (!patternRegex.test(str) || !trArgs[0])
1716
+ return;
1717
+ let matchNum = -1;
1718
+ for (const match of matches) {
1719
+ matchNum++;
1720
+ if (typeof trArgs[matchNum] !== "undefined")
1721
+ str = str.replace(match[0], String(trArgs[matchNum]));
1722
+ }
1723
+ };
1724
+ const isArgsObject = trArgs[0] && typeof trArgs[0] === "object" && trArgs[0] !== null && String(trArgs[0]).startsWith("[object");
1725
+ if (isArgsObject && eachKeyInTrString(Object.keys(trArgs[0])))
1726
+ namedMapping();
1727
+ else
1728
+ positionalMapping();
1729
+ return str;
1730
+ }
1731
+ ];
1732
+ var percentTransform = [
1733
+ /\$\{([a-zA-Z0-9$_-]+)\}/gm,
1734
+ ({ matches, trArgs, trValue }) => {
1735
+ let str = String(trValue);
1736
+ for (const match of matches) {
1737
+ const repl = match[1] !== undefined ? trArgs[0][match[1]] : undefined;
1738
+ if (typeof repl !== "undefined")
1739
+ str = str.replace(match[0], String(repl));
1740
+ }
1741
+ return str;
1742
+ }
1743
+ ];
1744
+ var tr = {
1745
+ for: (...params) => trFor(...params),
1746
+ use: (...params) => useTr(...params),
1747
+ hasKey: (language = fallbackLang != null ? fallbackLang : "", key) => hasKey(language, key),
1748
+ addTranslations,
1749
+ getTranslations,
1750
+ deleteTranslations,
1751
+ setFallbackLanguage,
1752
+ getFallbackLanguage,
1753
+ addTransform,
1754
+ deleteTransform,
1755
+ transforms: {
1756
+ templateLiteral: templateLiteralTransform,
1757
+ percent: percentTransform
1758
+ }
1518
1759
  };
1519
1760
 
1520
1761
  exports.DataStore = DataStore;
1521
1762
  exports.DataStoreSerializer = DataStoreSerializer;
1763
+ exports.Debouncer = Debouncer;
1522
1764
  exports.Dialog = Dialog;
1523
1765
  exports.NanoEmitter = NanoEmitter;
1524
1766
  exports.SelectorObserver = SelectorObserver;
@@ -1528,11 +1770,14 @@ Has: ${checksum}`);
1528
1770
  exports.clamp = clamp;
1529
1771
  exports.compress = compress;
1530
1772
  exports.computeHash = computeHash;
1773
+ exports.consumeGen = consumeGen;
1774
+ exports.consumeStringGen = consumeStringGen;
1531
1775
  exports.darkenColor = darkenColor;
1532
1776
  exports.debounce = debounce;
1533
1777
  exports.decompress = decompress;
1534
1778
  exports.defaultDialogCss = defaultDialogCss;
1535
1779
  exports.defaultStrings = defaultStrings;
1780
+ exports.digitCount = digitCount;
1536
1781
  exports.fetchAdvanced = fetchAdvanced;
1537
1782
  exports.getSiblingsFrame = getSiblingsFrame;
1538
1783
  exports.getUnsafeWindow = getUnsafeWindow;