@sv443-network/userutils 9.4.3 → 10.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.
@@ -0,0 +1,1889 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // lib/index.ts
31
+ var lib_exports = {};
32
+ __export(lib_exports, {
33
+ Dialog: () => Dialog,
34
+ GMStorageEngine: () => GMStorageEngine,
35
+ Mixins: () => Mixins,
36
+ PlatformError: () => PlatformError,
37
+ SelectorObserver: () => SelectorObserver,
38
+ addGlobalStyle: () => addGlobalStyle,
39
+ addParent: () => addParent,
40
+ currentDialogId: () => currentDialogId,
41
+ defaultDialogCss: () => defaultDialogCss,
42
+ defaultStrings: () => defaultStrings,
43
+ getSiblingsFrame: () => getSiblingsFrame,
44
+ getUnsafeWindow: () => getUnsafeWindow,
45
+ interceptEvent: () => interceptEvent,
46
+ interceptWindowEvent: () => interceptWindowEvent,
47
+ isDomLoaded: () => isDomLoaded,
48
+ isScrollable: () => isScrollable,
49
+ observeElementProp: () => observeElementProp,
50
+ onDomLoad: () => onDomLoad,
51
+ openDialogs: () => openDialogs,
52
+ openInNewTab: () => openInNewTab,
53
+ preloadImages: () => preloadImages,
54
+ probeElementStyle: () => probeElementStyle,
55
+ setInnerHtmlUnsafe: () => setInnerHtmlUnsafe,
56
+ tr: () => tr
57
+ });
58
+ module.exports = __toCommonJS(lib_exports);
59
+
60
+ // node_modules/.pnpm/@sv443-network+coreutils@3.0.1/node_modules/@sv443-network/coreutils/dist/CoreUtils.min.umd.js
61
+ (function(g, f) {
62
+ if ("object" == typeof exports && "object" == typeof module) {
63
+ module.exports = f();
64
+ } else if ("function" == typeof define && define.amd) {
65
+ define("CoreUtils", [], f);
66
+ } else if ("object" == typeof exports) {
67
+ exports["CoreUtils"] = f();
68
+ } else {
69
+ g["CoreUtils"] = f();
70
+ }
71
+ })(void 0, () => {
72
+ var exports2 = {};
73
+ var module2 = { exports: exports2 };
74
+ "use strict";
75
+ var X = Object.create;
76
+ var F = Object.defineProperty;
77
+ var Y = Object.getOwnPropertyDescriptor;
78
+ var ee = Object.getOwnPropertyNames;
79
+ var te = Object.getPrototypeOf, re = Object.prototype.hasOwnProperty;
80
+ var ie = (r, e) => {
81
+ for (var t in e) F(r, t, { get: e[t], enumerable: true });
82
+ }, B = (r, e, t, i) => {
83
+ if (e && typeof e == "object" || typeof e == "function") for (let n of ee(e)) !re.call(r, n) && n !== t && F(r, n, { get: () => e[n], enumerable: !(i = Y(e, n)) || i.enumerable });
84
+ return r;
85
+ };
86
+ var I = (r, e, t) => (t = r != null ? X(te(r)) : {}, B(e || !r || !r.__esModule ? F(t, "default", { value: r, enumerable: true }) : t, r)), ne = (r) => B(F({}, "__esModule", { value: true }), r);
87
+ var _e = {};
88
+ ie(_e, { BrowserStorageEngine: () => U, ChecksumMismatchError: () => S, CustomError: () => v, DataStore: () => z, DataStoreEngine: () => E, DataStoreSerializer: () => j, DatedError: () => d, Debouncer: () => A, FileStorageEngine: () => R, MigrationError: () => w, NanoEmitter: () => P, NetworkError: () => x, ScriptContextError: () => g, ValidationError: () => $, abtoa: () => H, atoab: () => W, autoPlural: () => Pe, bitSetHas: () => ae, capitalize: () => Oe, clamp: () => D, compress: () => N, computeHash: () => k, consumeGen: () => ge, consumeStringGen: () => be, createProgressBar: () => Fe, darkenColor: () => L, debounce: () => Ie, decompress: () => fe, defaultPbChars: () => Q, digitCount: () => oe, fetchAdvanced: () => ye, formatNumber: () => se, getCallStack: () => Ee, getListLength: () => De, hexToRgb: () => q, insertValues: () => Ve, joinArrayReadable: () => Ne, lightenColor: () => pe, mapRange: () => V, overflowVal: () => ue, pauseFor: () => Te, pureObj: () => Se, randRange: () => T, randomId: () => he, randomItem: () => le, randomItemIndex: () => C, randomizeArray: () => de, rgbToHex: () => J, roundFixed: () => _, scheduleExit: () => xe, secsToTimeStr: () => Ae, setImmediateInterval: () => ve, setImmediateTimeoutLoop: () => we, takeRandomItem: () => me, takeRandomItemIndex: () => K, truncStr: () => Me, valsWithin: () => ce });
89
+ module2.exports = ne(_e);
90
+ function ae(r, e) {
91
+ return (r & e) === e;
92
+ }
93
+ function D(r, e, t) {
94
+ return typeof t != "number" && (t = e, e = 0), Math.max(Math.min(r, t), e);
95
+ }
96
+ function oe(r, e = true) {
97
+ if (r = Number(["string", "number"].includes(typeof r) ? r : String(r)), typeof r == "number" && isNaN(r)) return NaN;
98
+ let [t, i] = r.toString().split("."), n = t === "0" ? 1 : Math.floor(Math.log10(Math.abs(Number(t))) + 1), o = e && i ? i.length : 0;
99
+ return n + o;
100
+ }
101
+ function se(r, e, t) {
102
+ return r.toLocaleString(e, t === "short" ? { notation: "compact", compactDisplay: "short", maximumFractionDigits: 1 } : { style: "decimal", maximumFractionDigits: 0 });
103
+ }
104
+ function V(r, e, t, i, n) {
105
+ return (typeof i > "u" || typeof n > "u") && (n = t, t = e, i = e = 0), Number(e) === 0 && Number(i) === 0 ? r * (n / t) : (r - e) * ((n - i) / (t - e)) + i;
106
+ }
107
+ function ue(r, e, t) {
108
+ let i = typeof t == "number" ? e : 0;
109
+ if (t = typeof t == "number" ? t : e, i > t) throw new RangeError(`Parameter "min" can't be bigger than "max"`);
110
+ if (isNaN(r) || isNaN(i) || isNaN(t) || !isFinite(r) || !isFinite(i) || !isFinite(t)) return NaN;
111
+ if (r >= i && r <= t) return r;
112
+ let n = t - i + 1;
113
+ return ((r - i) % n + n) % n + i;
114
+ }
115
+ function T(...r) {
116
+ let e, t, i = false;
117
+ if (typeof r[0] == "number" && typeof r[1] == "number") [e, t] = r;
118
+ else if (typeof r[0] == "number" && typeof r[1] != "number") e = 0, [t] = r;
119
+ else throw new TypeError(`Wrong parameter(s) provided - expected (number, boolean|undefined) or (number, number, boolean|undefined) but got (${r.map((n) => typeof n).join(", ")}) instead`);
120
+ if (typeof r[2] == "boolean" ? i = r[2] : typeof r[1] == "boolean" && (i = r[1]), e = Number(e), t = Number(t), isNaN(e) || isNaN(t)) return NaN;
121
+ if (e > t) throw new TypeError(`Parameter "min" can't be bigger than "max"`);
122
+ if (i) {
123
+ let n = new Uint8Array(1);
124
+ return crypto.getRandomValues(n), Number(Array.from(n, (o) => Math.round(V(o, 0, 255, e, t)).toString(10)).join(""));
125
+ } else return Math.floor(Math.random() * (t - e + 1)) + e;
126
+ }
127
+ function _(r, e) {
128
+ let t = 10 ** e;
129
+ return Math.round(r * t) / t;
130
+ }
131
+ function ce(r, e, t = 1, i = 0.5) {
132
+ return Math.abs(_(r, t) - _(e, t)) <= i;
133
+ }
134
+ function le(r) {
135
+ return C(r)[0];
136
+ }
137
+ function C(r) {
138
+ if (r.length === 0) return [void 0, void 0];
139
+ let e = T(r.length - 1);
140
+ return [r[e], e];
141
+ }
142
+ function de(r) {
143
+ let e = [...r];
144
+ if (r.length === 0) return e;
145
+ for (let t = e.length - 1; t > 0; t--) {
146
+ let i = Math.floor(Math.random() * (t + 1));
147
+ [e[t], e[i]] = [e[i], e[t]];
148
+ }
149
+ return e;
150
+ }
151
+ function me(r) {
152
+ var e;
153
+ return (e = K(r)) == null ? void 0 : e[0];
154
+ }
155
+ function K(r) {
156
+ let [e, t] = C(r);
157
+ return t === void 0 ? [void 0, void 0] : (r.splice(t, 1), [e, t]);
158
+ }
159
+ function L(r, e, t = false) {
160
+ var l;
161
+ r = r.trim();
162
+ let i = (c, p, m, b) => (c = Math.max(0, Math.min(255, c - c * b / 100)), p = Math.max(0, Math.min(255, p - p * b / 100)), m = Math.max(0, Math.min(255, m - m * b / 100)), [c, p, m]), n, o, a, s, u = r.match(/^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/);
163
+ if (u) [n, o, a, s] = q(r);
164
+ else if (r.startsWith("rgb")) {
165
+ let c = (l = r.match(/\d+(\.\d+)?/g)) == null ? void 0 : l.map(Number);
166
+ if (!c) throw new TypeError("Invalid RGB/RGBA color format");
167
+ [n, o, a, s] = c;
168
+ } else throw new TypeError("Unsupported color format");
169
+ return [n, o, a] = i(n, o, a, e), u ? J(n, o, a, s, r.startsWith("#"), t) : r.startsWith("rgba") ? `rgba(${n}, ${o}, ${a}, ${s ?? NaN})` : `rgb(${n}, ${o}, ${a})`;
170
+ }
171
+ function q(r) {
172
+ r = (r.startsWith("#") ? r.slice(1) : r).trim();
173
+ let e = r.length === 8 || r.length === 4 ? parseInt(r.slice(-(r.length / 4)), 16) / (r.length === 8 ? 255 : 15) : void 0;
174
+ isNaN(Number(e)) || (r = r.slice(0, -(r.length / 4))), (r.length === 3 || r.length === 4) && (r = r.split("").map((a) => a + a).join(""));
175
+ let t = parseInt(r, 16), i = t >> 16 & 255, n = t >> 8 & 255, o = t & 255;
176
+ return [D(i, 0, 255), D(n, 0, 255), D(o, 0, 255), typeof e == "number" ? D(e, 0, 1) : void 0];
177
+ }
178
+ function pe(r, e, t = false) {
179
+ return L(r, e * -1, t);
180
+ }
181
+ function J(r, e, t, i, n = true, o = false) {
182
+ let a = (s) => D(Math.round(s), 0, 255).toString(16).padStart(2, "0")[o ? "toUpperCase" : "toLowerCase"]();
183
+ return `${n ? "#" : ""}${a(r)}${a(e)}${a(t)}${i ? a(i * 255) : ""}`;
184
+ }
185
+ function H(r) {
186
+ return btoa(new Uint8Array(r).reduce((e, t) => e + String.fromCharCode(t), ""));
187
+ }
188
+ function W(r) {
189
+ return Uint8Array.from(atob(r), (e) => e.charCodeAt(0));
190
+ }
191
+ async function N(r, e, t = "string") {
192
+ let i = r instanceof Uint8Array ? r : new TextEncoder().encode((r == null ? void 0 : r.toString()) ?? String(r)), n = new CompressionStream(e), o = n.writable.getWriter();
193
+ o.write(i), o.close();
194
+ let a = new Uint8Array(await new Response(n.readable).arrayBuffer());
195
+ return t === "arrayBuffer" ? a : H(a);
196
+ }
197
+ async function fe(r, e, t = "string") {
198
+ let i = r instanceof Uint8Array ? r : W((r == null ? void 0 : r.toString()) ?? String(r)), n = new DecompressionStream(e), o = n.writable.getWriter();
199
+ o.write(i), o.close();
200
+ let a = new Uint8Array(await new Response(n.readable).arrayBuffer());
201
+ return t === "arrayBuffer" ? a : new TextDecoder().decode(a);
202
+ }
203
+ async function k(r, e = "SHA-256") {
204
+ let t;
205
+ typeof r == "string" ? t = new TextEncoder().encode(r) : t = r;
206
+ let i = await crypto.subtle.digest(e, t);
207
+ return Array.from(new Uint8Array(i)).map((a) => a.toString(16).padStart(2, "0")).join("");
208
+ }
209
+ function he(r = 16, e = 16, t = false, i = true) {
210
+ if (r < 1) throw new RangeError("The length argument must be at least 1");
211
+ if (e < 2 || e > 36) throw new RangeError("The radix argument must be between 2 and 36");
212
+ let n = [], o = i ? [0, 1] : [0];
213
+ if (t) {
214
+ let a = new Uint8Array(r);
215
+ crypto.getRandomValues(a), n = Array.from(a, (s) => V(s, 0, 255, 0, e).toString(e).substring(0, 1));
216
+ } else n = Array.from({ length: r }, () => Math.floor(Math.random() * e).toString(e));
217
+ return n.some((a) => /[a-zA-Z]/.test(a)) ? n.map((a) => o[T(0, o.length - 1, t)] === 1 ? a.toUpperCase() : a).join("") : n.join("");
218
+ }
219
+ var d = class extends Error {
220
+ date;
221
+ constructor(e, t) {
222
+ super(e, t), this.name = this.constructor.name, this.date = /* @__PURE__ */ new Date();
223
+ }
224
+ }, S = class extends d {
225
+ constructor(e, t) {
226
+ super(e, t), this.name = "ChecksumMismatchError";
227
+ }
228
+ }, v = class extends d {
229
+ constructor(e, t, i) {
230
+ super(t, i), this.name = e;
231
+ }
232
+ }, w = class extends d {
233
+ constructor(e, t) {
234
+ super(e, t), this.name = "MigrationError";
235
+ }
236
+ }, $ = class extends d {
237
+ constructor(e, t) {
238
+ super(e, t), this.name = "ValidationError";
239
+ }
240
+ }, g = class extends d {
241
+ constructor(e, t) {
242
+ super(e, t), this.name = "ScriptContextError";
243
+ }
244
+ }, x = class extends d {
245
+ constructor(e, t) {
246
+ super(e, t), this.name = "NetworkError";
247
+ }
248
+ };
249
+ async function ge(r) {
250
+ return await (typeof r == "function" ? r() : r);
251
+ }
252
+ async function be(r) {
253
+ return typeof r == "string" ? r : String(typeof r == "function" ? await r() : r);
254
+ }
255
+ async function ye(r, e = {}) {
256
+ let { timeout: t = 1e4, signal: i, ...n } = e, o = new AbortController();
257
+ i == null || i.addEventListener("abort", () => o.abort());
258
+ let a = {}, s;
259
+ t >= 0 && (s = setTimeout(() => o.abort(), t), a = { signal: o.signal });
260
+ try {
261
+ let u = await fetch(r, { ...n, ...a });
262
+ return typeof s < "u" && clearTimeout(s), u;
263
+ } catch (u) {
264
+ throw typeof s < "u" && clearTimeout(s), new x("Error while calling fetch", { cause: u });
265
+ }
266
+ }
267
+ function De(r, e = true) {
268
+ return "length" in r ? r.length : "size" in r ? r.size : "count" in r ? r.count : e ? 0 : NaN;
269
+ }
270
+ function Te(r, e, t = false) {
271
+ return new Promise((i, n) => {
272
+ let o = setTimeout(() => i(), r);
273
+ e == null || e.addEventListener("abort", () => {
274
+ clearTimeout(o), t ? n(new v("AbortError", "The pause was aborted")) : i();
275
+ });
276
+ });
277
+ }
278
+ function Se(r) {
279
+ return Object.assign(/* @__PURE__ */ Object.create(null), r ?? {});
280
+ }
281
+ function ve(r, e, t) {
282
+ let i, n = () => clearInterval(i), o = () => {
283
+ if (t != null && t.aborted) return n();
284
+ r();
285
+ };
286
+ t == null || t.addEventListener("abort", n), o(), i = setInterval(o, e);
287
+ }
288
+ function we(r, e, t) {
289
+ let i, n = () => clearTimeout(i), o = async () => {
290
+ if (t != null && t.aborted) return n();
291
+ await r(), i = setTimeout(o, e);
292
+ };
293
+ t == null || t.addEventListener("abort", n), o();
294
+ }
295
+ function xe(r = 0, e = 0) {
296
+ if (e < 0) throw new TypeError("Timeout must be a non-negative number");
297
+ let t;
298
+ if (typeof process < "u" && "exit" in process && typeof process.exit == "function") t = () => process.exit(r);
299
+ else if (typeof Deno < "u" && "exit" in Deno && typeof Deno.exit == "function") t = () => Deno.exit(r);
300
+ else throw new g("Cannot exit the process, no exit method available");
301
+ setTimeout(t, e);
302
+ }
303
+ function Ee(r, e = 1 / 0) {
304
+ if (typeof e != "number" || isNaN(e) || e < 0) throw new TypeError("lines parameter must be a non-negative number");
305
+ try {
306
+ throw new Error("This is to capture a stack trace with CoreUtils.getCallStack(). (If you see this somewhere, you can safely ignore it.)");
307
+ } catch (t) {
308
+ let i = (t.stack ?? "").split(`
309
+ `).map((n) => n.trim()).slice(2, e + 2);
310
+ return r !== false ? i : i.join(`
311
+ `);
312
+ }
313
+ }
314
+ function Pe(r, e, t = "auto") {
315
+ switch (typeof e != "number" && ("length" in e ? e = e.length : "size" in e ? e = e.size : "count" in e && (e = e.count)), ["-s", "-ies"].includes(t) || (t = "auto"), isNaN(e) && (e = 2), t === "auto" ? String(r).endsWith("y") ? "-ies" : "-s" : t) {
316
+ case "-s":
317
+ return `${r}${e === 1 ? "" : "s"}`;
318
+ case "-ies":
319
+ return `${String(r).slice(0, -1)}${e === 1 ? "y" : "ies"}`;
320
+ }
321
+ }
322
+ function Oe(r) {
323
+ return r.charAt(0).toUpperCase() + r.slice(1);
324
+ }
325
+ var Q = { 100: "\u2588", 75: "\u2593", 50: "\u2592", 25: "\u2591", 0: "\u2500" };
326
+ function Fe(r, e, t = Q) {
327
+ if (r === 100) return t[100].repeat(e);
328
+ let i = Math.floor(r / 100 * e), n = r / 10 * e - i, o = "";
329
+ n >= 0.75 ? o = t[75] : n >= 0.5 ? o = t[50] : n >= 0.25 && (o = t[25]);
330
+ let a = t[100].repeat(i), s = t[0].repeat(e - i - (o ? 1 : 0));
331
+ return `${a}${o}${s}`;
332
+ }
333
+ function Ve(r, ...e) {
334
+ return r.replace(/%\d/gm, (t) => {
335
+ var n;
336
+ let i = Number(t.substring(1)) - 1;
337
+ return (n = e[i] ?? t) == null ? void 0 : n.toString();
338
+ });
339
+ }
340
+ function Ne(r, e = ", ", t = " and ") {
341
+ let i = [...r];
342
+ if (i.length === 0) return "";
343
+ if (i.length === 1) return String(i[0]);
344
+ if (i.length === 2) return i.join(t);
345
+ let n = t + i[i.length - 1];
346
+ return i.pop(), i.join(e) + n;
347
+ }
348
+ function Ae(r) {
349
+ let e = r < 0, t = Math.abs(r);
350
+ if (isNaN(t) || !isFinite(t)) throw new TypeError("The seconds argument must be a valid number");
351
+ let i = Math.floor(t / 3600), n = Math.floor(t % 3600 / 60), o = Math.floor(t % 60);
352
+ return (e ? "-" : "") + [i ? i + ":" : "", String(n).padStart(n > 0 || i > 0 ? 2 : 1, "0"), ":", String(o).padStart(o > 0 || n > 0 || i > 0 || r === 0 ? 2 : 1, "0")].join("");
353
+ }
354
+ function Me(r, e, t = "...") {
355
+ let i = (r == null ? void 0 : r.toString()) ?? String(r), n = i.length > e ? i.substring(0, e - t.length) + t : i;
356
+ return n.length > e ? n.substring(0, e) : n;
357
+ }
358
+ var G = 1, z = class {
359
+ id;
360
+ formatVersion;
361
+ defaultData;
362
+ encodeData;
363
+ decodeData;
364
+ compressionFormat = "deflate-raw";
365
+ memoryCache = true;
366
+ engine;
367
+ options;
368
+ firstInit = true;
369
+ cachedData;
370
+ migrations;
371
+ migrateIds = [];
372
+ constructor(e) {
373
+ var t;
374
+ if (this.id = e.id, this.formatVersion = e.formatVersion, this.defaultData = e.defaultData, this.memoryCache = !!(e.memoryCache ?? true), this.cachedData = this.memoryCache ? e.defaultData : {}, this.migrations = e.migrations, e.migrateIds && (this.migrateIds = Array.isArray(e.migrateIds) ? e.migrateIds : [e.migrateIds]), this.encodeData = e.encodeData, this.decodeData = e.decodeData, this.engine = typeof e.engine == "function" ? e.engine() : e.engine, this.options = e, typeof e.compressionFormat > "u" && (this.compressionFormat = e.compressionFormat = ((t = e.encodeData) == null ? void 0 : t[0]) ?? "deflate-raw"), typeof e.compressionFormat == "string") this.encodeData = [e.compressionFormat, async (i) => await N(i, e.compressionFormat, "string")], this.decodeData = [e.compressionFormat, async (i) => await N(i, e.compressionFormat, "string")];
375
+ else if ("encodeData" in e && "decodeData" in e && Array.isArray(e.encodeData) && Array.isArray(e.decodeData)) this.encodeData = [e.encodeData[0], e.encodeData[1]], this.decodeData = [e.decodeData[0], e.decodeData[1]], this.compressionFormat = e.encodeData[0] ?? null;
376
+ else if (e.compressionFormat === null) this.encodeData = void 0, this.decodeData = void 0, this.compressionFormat = null;
377
+ else throw new TypeError("Either `compressionFormat` or `encodeData` and `decodeData` have to be set and valid, but not all three at a time. Please refer to the documentation for more info.");
378
+ this.engine.setDataStoreOptions(e);
379
+ }
380
+ async loadData() {
381
+ try {
382
+ if (this.firstInit) {
383
+ this.firstInit = false;
384
+ let u = Number(await this.engine.getValue("__ds_fmt_ver", 0)), l = await this.engine.getValue(`_uucfg-${this.id}`, null);
385
+ if (l) {
386
+ let c = Number(await this.engine.getValue(`_uucfgver-${this.id}`, NaN)), p = await this.engine.getValue(`_uucfgenc-${this.id}`, null), m = [], b = (O, h, y) => {
387
+ m.push(this.engine.setValue(h, y)), m.push(this.engine.deleteValue(O));
388
+ };
389
+ b(`_uucfg-${this.id}`, `__ds-${this.id}-dat`, l), isNaN(c) || b(`_uucfgver-${this.id}`, `__ds-${this.id}-ver`, c), typeof p == "boolean" ? b(`_uucfgenc-${this.id}`, `__ds-${this.id}-enf`, p === true ? this.compressionFormat ?? null : null) : (m.push(this.engine.setValue(`__ds-${this.id}-enf`, this.compressionFormat)), m.push(this.engine.deleteValue(`_uucfgenc-${this.id}`))), await Promise.allSettled(m);
390
+ }
391
+ (isNaN(u) || u < G) && await this.engine.setValue("__ds_fmt_ver", G);
392
+ }
393
+ this.migrateIds.length > 0 && (await this.migrateId(this.migrateIds), this.migrateIds = []);
394
+ let e = await this.engine.getValue(`__ds-${this.id}-dat`, null), t = Number(await this.engine.getValue(`__ds-${this.id}-ver`, NaN));
395
+ if (typeof e != "string") return await this.saveDefaultData(), this.engine.deepCopy(this.defaultData);
396
+ let i = e ?? JSON.stringify(this.defaultData), n = String(await this.engine.getValue(`__ds-${this.id}-enf`, null)), o = n !== "null" && n !== "false", a = false;
397
+ isNaN(t) && (await this.engine.setValue(`__ds-${this.id}-ver`, t = this.formatVersion), a = true);
398
+ let s = await this.engine.deserializeData(i, o);
399
+ return t < this.formatVersion && this.migrations && (s = await this.runMigrations(s, t)), a && await this.setData(s), this.memoryCache ? this.cachedData = this.engine.deepCopy(s) : this.engine.deepCopy(s);
400
+ } catch (e) {
401
+ return console.warn("Error while parsing JSON data, resetting it to the default value.", e), await this.saveDefaultData(), this.defaultData;
402
+ }
403
+ }
404
+ getData() {
405
+ if (!this.memoryCache) throw new d("In-memory cache is disabled for this DataStore instance, so getData() can't be used. Please use loadData() instead.");
406
+ return this.engine.deepCopy(this.cachedData);
407
+ }
408
+ setData(e) {
409
+ return this.memoryCache && (this.cachedData = e), new Promise(async (t) => {
410
+ await Promise.allSettled([this.engine.setValue(`__ds-${this.id}-dat`, await this.engine.serializeData(e, this.encodingEnabled())), this.engine.setValue(`__ds-${this.id}-ver`, this.formatVersion), this.engine.setValue(`__ds-${this.id}-enf`, this.compressionFormat)]), t();
411
+ });
412
+ }
413
+ async saveDefaultData() {
414
+ this.memoryCache && (this.cachedData = this.defaultData), await Promise.allSettled([this.engine.setValue(`__ds-${this.id}-dat`, await this.engine.serializeData(this.defaultData, this.encodingEnabled())), this.engine.setValue(`__ds-${this.id}-ver`, this.formatVersion), this.engine.setValue(`__ds-${this.id}-enf`, this.compressionFormat)]);
415
+ }
416
+ async deleteData() {
417
+ var e, t;
418
+ await Promise.allSettled([this.engine.deleteValue(`__ds-${this.id}-dat`), this.engine.deleteValue(`__ds-${this.id}-ver`), this.engine.deleteValue(`__ds-${this.id}-enf`)]), await ((t = (e = this.engine).deleteStorage) == null ? void 0 : t.call(e));
419
+ }
420
+ encodingEnabled() {
421
+ return !!(this.encodeData && this.decodeData) && this.compressionFormat !== null || !!this.compressionFormat;
422
+ }
423
+ async runMigrations(e, t, i = true) {
424
+ if (!this.migrations) return e;
425
+ let n = e, o = Object.entries(this.migrations).sort(([s], [u]) => Number(s) - Number(u)), a = t;
426
+ for (let [s, u] of o) {
427
+ let l = Number(s);
428
+ if (t < this.formatVersion && t < l) try {
429
+ let c = u(n);
430
+ n = c instanceof Promise ? await c : c, a = t = l;
431
+ } catch (c) {
432
+ if (!i) throw new w(`Error while running migration function for format version '${s}'`, { cause: c });
433
+ return await this.saveDefaultData(), this.getData();
434
+ }
435
+ }
436
+ return await Promise.allSettled([this.engine.setValue(`__ds-${this.id}-dat`, await this.engine.serializeData(n)), this.engine.setValue(`__ds-${this.id}-ver`, a), this.engine.setValue(`__ds-${this.id}-enf`, this.compressionFormat)]), this.memoryCache ? this.cachedData = this.engine.deepCopy(n) : this.engine.deepCopy(n);
437
+ }
438
+ async migrateId(e) {
439
+ let t = Array.isArray(e) ? e : [e];
440
+ await Promise.all(t.map(async (i) => {
441
+ let [n, o, a] = await (async () => {
442
+ let [u, l, c] = await Promise.all([this.engine.getValue(`__ds-${i}-dat`, JSON.stringify(this.defaultData)), this.engine.getValue(`__ds-${i}-ver`, NaN), this.engine.getValue(`__ds-${i}-enf`, null)]);
443
+ return [u, Number(l), !!c && String(c) !== "null"];
444
+ })();
445
+ if (n === void 0 || isNaN(o)) return;
446
+ let s = await this.engine.deserializeData(n, a);
447
+ await Promise.allSettled([this.engine.setValue(`__ds-${this.id}-dat`, await this.engine.serializeData(s)), this.engine.setValue(`__ds-${this.id}-ver`, o), this.engine.setValue(`__ds-${this.id}-enf`, this.compressionFormat), this.engine.deleteValue(`__ds-${i}-dat`), this.engine.deleteValue(`__ds-${i}-ver`), this.engine.deleteValue(`__ds-${i}-enf`)]);
448
+ }));
449
+ }
450
+ };
451
+ var E = class {
452
+ dataStoreOptions;
453
+ constructor(e) {
454
+ e && (this.dataStoreOptions = e);
455
+ }
456
+ setDataStoreOptions(e) {
457
+ this.dataStoreOptions = e;
458
+ }
459
+ async serializeData(e, t) {
460
+ var o, a, s, u, l;
461
+ this.ensureDataStoreOptions();
462
+ let i = JSON.stringify(e);
463
+ if (!t || !((o = this.dataStoreOptions) != null && o.encodeData) || !((a = this.dataStoreOptions) != null && a.decodeData)) return i;
464
+ let n = (l = (u = (s = this.dataStoreOptions) == null ? void 0 : s.encodeData) == null ? void 0 : u[1]) == null ? void 0 : l.call(u, i);
465
+ return n instanceof Promise ? await n : n;
466
+ }
467
+ async deserializeData(e, t) {
468
+ var n, o, a;
469
+ this.ensureDataStoreOptions();
470
+ let i = (n = this.dataStoreOptions) != null && n.decodeData && t ? (a = (o = this.dataStoreOptions.decodeData) == null ? void 0 : o[1]) == null ? void 0 : a.call(o, e) : void 0;
471
+ return i instanceof Promise && (i = await i), JSON.parse(i ?? e);
472
+ }
473
+ ensureDataStoreOptions() {
474
+ if (!this.dataStoreOptions) throw new d("DataStoreEngine must be initialized with DataStore options before use. If you are using this instance standalone, set them in the constructor or call `setDataStoreOptions()` with the DataStore options.");
475
+ if (!this.dataStoreOptions.id) throw new d("DataStoreEngine must be initialized with a valid DataStore ID");
476
+ }
477
+ deepCopy(e) {
478
+ try {
479
+ if ("structuredClone" in globalThis) return structuredClone(e);
480
+ } catch {
481
+ }
482
+ return JSON.parse(JSON.stringify(e));
483
+ }
484
+ }, U = class extends E {
485
+ options;
486
+ constructor(e) {
487
+ super(e == null ? void 0 : e.dataStoreOptions), this.options = { type: "localStorage", ...e };
488
+ }
489
+ async getValue(e, t) {
490
+ let i = this.options.type === "localStorage" ? globalThis.localStorage.getItem(e) : globalThis.sessionStorage.getItem(e);
491
+ return typeof i > "u" ? t : i;
492
+ }
493
+ async setValue(e, t) {
494
+ this.options.type === "localStorage" ? globalThis.localStorage.setItem(e, String(t)) : globalThis.sessionStorage.setItem(e, String(t));
495
+ }
496
+ async deleteValue(e) {
497
+ this.options.type === "localStorage" ? globalThis.localStorage.removeItem(e) : globalThis.sessionStorage.removeItem(e);
498
+ }
499
+ }, f, R = class extends E {
500
+ options;
501
+ fileAccessQueue = Promise.resolve();
502
+ constructor(e) {
503
+ super(e == null ? void 0 : e.dataStoreOptions), this.options = { filePath: (t) => `.ds-${t}`, ...e };
504
+ }
505
+ async readFile() {
506
+ var e, t, i, n;
507
+ this.ensureDataStoreOptions();
508
+ try {
509
+ if (f || (f = (e = await import("fs/promises")) == null ? void 0 : e.default), !f) throw new g("FileStorageEngine requires Node.js or Deno with Node compatibility (v1.31+)", { cause: new d("'node:fs/promises' module not available") });
510
+ let o = typeof this.options.filePath == "string" ? this.options.filePath : this.options.filePath(this.dataStoreOptions.id), a = await f.readFile(o, "utf-8");
511
+ return a ? JSON.parse(await ((n = (i = (t = this.dataStoreOptions) == null ? void 0 : t.decodeData) == null ? void 0 : i[1]) == null ? void 0 : n.call(i, a)) ?? a) : void 0;
512
+ } catch {
513
+ return;
514
+ }
515
+ }
516
+ async writeFile(e) {
517
+ var t, i, n, o;
518
+ this.ensureDataStoreOptions();
519
+ try {
520
+ if (f || (f = (t = await import("fs/promises")) == null ? void 0 : t.default), !f) throw new g("FileStorageEngine requires Node.js or Deno with Node compatibility (v1.31+)", { cause: new d("'node:fs/promises' module not available") });
521
+ let a = typeof this.options.filePath == "string" ? this.options.filePath : this.options.filePath(this.dataStoreOptions.id);
522
+ await f.mkdir(a.slice(0, a.lastIndexOf(a.includes("/") ? "/" : "\\")), { recursive: true }), await f.writeFile(a, await ((o = (n = (i = this.dataStoreOptions) == null ? void 0 : i.encodeData) == null ? void 0 : n[1]) == null ? void 0 : o.call(n, JSON.stringify(e))) ?? JSON.stringify(e, void 0, 2), "utf-8");
523
+ } catch (a) {
524
+ console.error("Error writing file:", a);
525
+ }
526
+ }
527
+ async getValue(e, t) {
528
+ let i = await this.readFile();
529
+ if (!i) return t;
530
+ let n = i == null ? void 0 : i[e];
531
+ return typeof n > "u" ? t : n;
532
+ }
533
+ async setValue(e, t) {
534
+ this.fileAccessQueue = this.fileAccessQueue.then(async () => {
535
+ let i = await this.readFile();
536
+ i || (i = {}), i[e] = t, await this.writeFile(i);
537
+ }).catch((i) => {
538
+ throw console.error("Error in setValue:", i), i;
539
+ }), await this.fileAccessQueue.catch(() => {
540
+ });
541
+ }
542
+ async deleteValue(e) {
543
+ this.fileAccessQueue = this.fileAccessQueue.then(async () => {
544
+ let t = await this.readFile();
545
+ t && (delete t[e], await this.writeFile(t));
546
+ }).catch((t) => {
547
+ throw console.error("Error in deleteValue:", t), t;
548
+ }), await this.fileAccessQueue.catch(() => {
549
+ });
550
+ }
551
+ async deleteStorage() {
552
+ var e;
553
+ this.ensureDataStoreOptions();
554
+ try {
555
+ if (f || (f = (e = await import("fs/promises")) == null ? void 0 : e.default), !f) throw new g("FileStorageEngine requires Node.js or Deno with Node compatibility (v1.31+)", { cause: new d("'node:fs/promises' module not available") });
556
+ let t = typeof this.options.filePath == "string" ? this.options.filePath : this.options.filePath(this.dataStoreOptions.id);
557
+ return await f.unlink(t);
558
+ } catch (t) {
559
+ console.error("Error deleting file:", t);
560
+ }
561
+ }
562
+ };
563
+ var j = class r {
564
+ stores;
565
+ options;
566
+ constructor(e, t = {}) {
567
+ if (!crypto || !crypto.subtle) throw new g("DataStoreSerializer has to run in a secure context (HTTPS) or in another environment that implements the subtleCrypto API!");
568
+ this.stores = e, this.options = { addChecksum: true, ensureIntegrity: true, remapIds: {}, ...t };
569
+ }
570
+ async calcChecksum(e) {
571
+ return k(e, "SHA-256");
572
+ }
573
+ async serializePartial(e, t = true, i = true) {
574
+ var a;
575
+ let n = [], o = this.stores.filter((s) => typeof e == "function" ? e(s.id) : e.includes(s.id));
576
+ for (let s of o) {
577
+ let u = !!(t && s.encodingEnabled() && ((a = s.encodeData) != null && a[1])), l = s.memoryCache ? s.getData() : await s.loadData(), c = u ? await s.encodeData[1](JSON.stringify(l)) : JSON.stringify(l);
578
+ n.push({ id: s.id, data: c, formatVersion: s.formatVersion, encoded: u, checksum: this.options.addChecksum ? await this.calcChecksum(c) : void 0 });
579
+ }
580
+ return i ? JSON.stringify(n) : n;
581
+ }
582
+ async serialize(e = true, t = true) {
583
+ return this.serializePartial(this.stores.map((i) => i.id), e, t);
584
+ }
585
+ async deserializePartial(e, t) {
586
+ let i = typeof t == "string" ? JSON.parse(t) : t;
587
+ if (!Array.isArray(i) || !i.every(r.isSerializedDataStoreObj)) throw new TypeError("Invalid serialized data format! Expected an array of SerializedDataStore objects.");
588
+ let n = (a) => {
589
+ var s;
590
+ return ((s = Object.entries(this.options.remapIds).find(([, u]) => u.includes(a))) == null ? void 0 : s[0]) ?? a;
591
+ }, o = (a) => typeof e == "function" ? e(a) : e.includes(a);
592
+ for (let a of i) {
593
+ let s = n(a.id);
594
+ if (!o(s)) continue;
595
+ let u = this.stores.find((c) => c.id === s);
596
+ if (!u) throw new d(`Can't deserialize data because no DataStore instance with the ID "${s}" was found! Make sure to provide it in the DataStoreSerializer constructor.`);
597
+ if (this.options.ensureIntegrity && typeof a.checksum == "string") {
598
+ let c = await this.calcChecksum(a.data);
599
+ if (c !== a.checksum) throw new S(`Checksum mismatch for DataStore with ID "${a.id}"!
600
+ Expected: ${a.checksum}
601
+ Has: ${c}`);
602
+ }
603
+ let l = a.encoded && u.encodingEnabled() ? await u.decodeData[1](a.data) : a.data;
604
+ a.formatVersion && !isNaN(Number(a.formatVersion)) && Number(a.formatVersion) < u.formatVersion ? await u.runMigrations(JSON.parse(l), Number(a.formatVersion), false) : await u.setData(JSON.parse(l));
605
+ }
606
+ }
607
+ async deserialize(e) {
608
+ return this.deserializePartial(this.stores.map((t) => t.id), e);
609
+ }
610
+ async loadStoresData(e) {
611
+ return Promise.allSettled(this.getStoresFiltered(e).map(async (t) => ({ id: t.id, data: await t.loadData() })));
612
+ }
613
+ async resetStoresData(e) {
614
+ return Promise.allSettled(this.getStoresFiltered(e).map((t) => t.saveDefaultData()));
615
+ }
616
+ async deleteStoresData(e) {
617
+ return Promise.allSettled(this.getStoresFiltered(e).map((t) => t.deleteData()));
618
+ }
619
+ static isSerializedDataStoreObjArray(e) {
620
+ return Array.isArray(e) && e.every((t) => typeof t == "object" && t !== null && "id" in t && "data" in t && "formatVersion" in t && "encoded" in t);
621
+ }
622
+ static isSerializedDataStoreObj(e) {
623
+ return typeof e == "object" && e !== null && "id" in e && "data" in e && "formatVersion" in e && "encoded" in e;
624
+ }
625
+ getStoresFiltered(e) {
626
+ return this.stores.filter((t) => typeof e > "u" ? true : Array.isArray(e) ? e.includes(t.id) : e(t.id));
627
+ }
628
+ };
629
+ var Z = () => ({ emit(r, ...e) {
630
+ for (let t = this.events[r] || [], i = 0, n = t.length; i < n; i++) t[i](...e);
631
+ }, events: {}, on(r, e) {
632
+ return (this.events[r] ||= []).push(e), () => {
633
+ var t;
634
+ this.events[r] = (t = this.events[r]) == null ? void 0 : t.filter((i) => e !== i);
635
+ };
636
+ } });
637
+ var P = class {
638
+ events = Z();
639
+ eventUnsubscribes = [];
640
+ emitterOptions;
641
+ constructor(e = {}) {
642
+ this.emitterOptions = { publicEmit: false, ...e };
643
+ }
644
+ on(e, t) {
645
+ let i, n = () => {
646
+ i && (i(), this.eventUnsubscribes = this.eventUnsubscribes.filter((o) => o !== i));
647
+ };
648
+ return i = this.events.on(e, t), this.eventUnsubscribes.push(i), n;
649
+ }
650
+ once(e, t) {
651
+ return new Promise((i) => {
652
+ let n, o = ((...a) => {
653
+ t == null || t(...a), n == null || n(), i(a);
654
+ });
655
+ n = this.events.on(e, o), this.eventUnsubscribes.push(n);
656
+ });
657
+ }
658
+ onMulti(e) {
659
+ let t = [], i = () => {
660
+ for (let n of t) n();
661
+ t.splice(0, t.length), this.eventUnsubscribes = this.eventUnsubscribes.filter((n) => !t.includes(n));
662
+ };
663
+ for (let n of Array.isArray(e) ? e : [e]) {
664
+ let o = { allOf: [], oneOf: [], once: false, ...n }, { oneOf: a, allOf: s, once: u, signal: l, callback: c } = o;
665
+ if (l != null && l.aborted) return i;
666
+ if (a.length === 0 && s.length === 0) throw new TypeError("NanoEmitter.onMulti(): Either `oneOf` or `allOf` or both must be provided in the options");
667
+ let p = [], m = (h = false) => {
668
+ if (!(!(l != null && l.aborted) && !h)) {
669
+ for (let y of p) y();
670
+ p.splice(0, p.length), this.eventUnsubscribes = this.eventUnsubscribes.filter((y) => !p.includes(y));
671
+ }
672
+ }, b = /* @__PURE__ */ new Set(), O = () => s.length === 0 || b.size === s.length;
673
+ for (let h of a) {
674
+ let y = this.events.on(h, ((...M) => {
675
+ m(), O() && (c(h, ...M), u && m(true));
676
+ }));
677
+ p.push(y);
678
+ }
679
+ for (let h of s) {
680
+ let y = this.events.on(h, ((...M) => {
681
+ m(), b.add(h), O() && (a.length === 0 || a.includes(h)) && (c(h, ...M), u && m(true));
682
+ }));
683
+ p.push(y);
684
+ }
685
+ t.push(() => m(true));
686
+ }
687
+ return i;
688
+ }
689
+ emit(e, ...t) {
690
+ return this.emitterOptions.publicEmit ? (this.events.emit(e, ...t), true) : false;
691
+ }
692
+ unsubscribeAll() {
693
+ for (let e of this.eventUnsubscribes) e();
694
+ this.eventUnsubscribes = [];
695
+ }
696
+ };
697
+ var A = class extends P {
698
+ constructor(t = 200, i = "immediate") {
699
+ super();
700
+ this.timeout = t;
701
+ this.type = i;
702
+ }
703
+ listeners = [];
704
+ activeTimeout;
705
+ queuedCall;
706
+ addListener(t) {
707
+ this.listeners.push(t);
708
+ }
709
+ removeListener(t) {
710
+ let i = this.listeners.findIndex((n) => n === t);
711
+ i !== -1 && this.listeners.splice(i, 1);
712
+ }
713
+ removeAllListeners() {
714
+ this.listeners = [];
715
+ }
716
+ getListeners() {
717
+ return this.listeners;
718
+ }
719
+ setTimeout(t) {
720
+ this.emit("change", this.timeout = t, this.type);
721
+ }
722
+ getTimeout() {
723
+ return this.timeout;
724
+ }
725
+ isTimeoutActive() {
726
+ return typeof this.activeTimeout < "u";
727
+ }
728
+ setType(t) {
729
+ this.emit("change", this.timeout, this.type = t);
730
+ }
731
+ getType() {
732
+ return this.type;
733
+ }
734
+ call(...t) {
735
+ let i = (...o) => {
736
+ this.queuedCall = void 0, this.emit("call", ...o), this.listeners.forEach((a) => a.call(this, ...o));
737
+ }, n = () => {
738
+ this.activeTimeout = setTimeout(() => {
739
+ this.queuedCall ? (this.queuedCall(), n()) : this.activeTimeout = void 0;
740
+ }, this.timeout);
741
+ };
742
+ switch (this.type) {
743
+ case "immediate":
744
+ typeof this.activeTimeout > "u" ? (i(...t), n()) : this.queuedCall = () => i(...t);
745
+ break;
746
+ case "idle":
747
+ this.activeTimeout && clearTimeout(this.activeTimeout), this.activeTimeout = setTimeout(() => {
748
+ i(...t), this.activeTimeout = void 0;
749
+ }, this.timeout);
750
+ break;
751
+ default:
752
+ throw new TypeError(`Invalid debouncer type: ${this.type}`);
753
+ }
754
+ }
755
+ };
756
+ function Ie(r, e = 200, t = "immediate") {
757
+ let i = new A(e, t);
758
+ i.addListener(r);
759
+ let n = ((...o) => i.call(...o));
760
+ return n.debouncer = i, n;
761
+ }
762
+ if (typeof module2.exports == "object" && typeof exports2 == "object") {
763
+ var __cp = (to, from, except, desc) => {
764
+ if (from && typeof from === "object" || typeof from === "function") {
765
+ for (let key of Object.getOwnPropertyNames(from)) {
766
+ if (!Object.prototype.hasOwnProperty.call(to, key) && key !== except)
767
+ Object.defineProperty(to, key, {
768
+ get: () => from[key],
769
+ enumerable: !(desc = Object.getOwnPropertyDescriptor(from, key)) || desc.enumerable
770
+ });
771
+ }
772
+ }
773
+ return to;
774
+ };
775
+ module2.exports = __cp(module2.exports, exports2);
776
+ }
777
+ return module2.exports;
778
+ });
779
+
780
+ // lib/Errors.ts
781
+ var PlatformError = class extends (void 0) {
782
+ constructor(message, options) {
783
+ super(message, options);
784
+ this.name = "PlatformError";
785
+ }
786
+ };
787
+
788
+ // lib/dom.ts
789
+ function getUnsafeWindow() {
790
+ try {
791
+ return unsafeWindow;
792
+ } catch {
793
+ return window;
794
+ }
795
+ }
796
+ function addParent(element, newParent) {
797
+ const oldParent = element.parentNode;
798
+ if (!oldParent)
799
+ throw new Error("Element doesn't have a parent node");
800
+ oldParent.replaceChild(newParent, element);
801
+ newParent.appendChild(element);
802
+ return newParent;
803
+ }
804
+ function addGlobalStyle(style) {
805
+ const styleElem = document.createElement("style");
806
+ setInnerHtmlUnsafe(styleElem, style);
807
+ document.head.appendChild(styleElem);
808
+ return styleElem;
809
+ }
810
+ function preloadImages(srcUrls, rejects = false) {
811
+ const promises = srcUrls.map((src) => new Promise((res, rej) => {
812
+ const image = new Image();
813
+ image.addEventListener("load", () => res(image), { once: true });
814
+ image.addEventListener("error", (evt) => rejects ? rej(evt) : res(image), { once: true });
815
+ image.src = src;
816
+ }));
817
+ return Promise.allSettled(promises);
818
+ }
819
+ function openInNewTab(href, background, additionalProps) {
820
+ try {
821
+ if (typeof window.GM === "object")
822
+ GM.openInTab(href, background);
823
+ } catch {
824
+ const openElem = document.createElement("a");
825
+ Object.assign(openElem, {
826
+ className: "userutils-open-in-new-tab",
827
+ target: "_blank",
828
+ rel: "noopener noreferrer",
829
+ tabIndex: -1,
830
+ ariaHidden: "true",
831
+ href,
832
+ ...additionalProps
833
+ });
834
+ Object.assign(openElem.style, {
835
+ display: "none",
836
+ pointerEvents: "none"
837
+ });
838
+ document.body.appendChild(openElem);
839
+ openElem.click();
840
+ setTimeout(() => {
841
+ try {
842
+ openElem.remove();
843
+ } catch {
844
+ }
845
+ }, 0);
846
+ }
847
+ }
848
+ function interceptEvent(eventObject, eventName, predicate = () => true) {
849
+ var _a;
850
+ if (typeof window.GM === "object" && ((_a = GM == null ? void 0 : GM.info) == null ? void 0 : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey" && (eventObject === window || eventObject === getUnsafeWindow()))
851
+ throw new PlatformError("Intercepting window events is not supported on FireMonkey due to the isolated context the userscript is forced to run in.");
852
+ if ("stackTraceLimit" in Error) {
853
+ Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
854
+ if (isNaN(Error.stackTraceLimit))
855
+ Error.stackTraceLimit = 100;
856
+ }
857
+ (function(original) {
858
+ eventObject.__proto__.addEventListener = function(...args) {
859
+ var _a2;
860
+ const origListener = typeof args[1] === "function" ? args[1] : ((_a2 = args[1]) == null ? void 0 : _a2.handleEvent) ?? (() => void 0);
861
+ args[1] = function(...a) {
862
+ if (args[0] === eventName && predicate(Array.isArray(a) ? a[0] : a))
863
+ return;
864
+ else
865
+ return origListener.apply(this, a);
866
+ };
867
+ original.apply(this, args);
868
+ };
869
+ })(eventObject.__proto__.addEventListener);
870
+ }
871
+ function interceptWindowEvent(eventName, predicate = () => true) {
872
+ return interceptEvent(getUnsafeWindow(), eventName, predicate);
873
+ }
874
+ function isScrollable(element) {
875
+ const { overflowX, overflowY } = getComputedStyle(element);
876
+ return {
877
+ vertical: (overflowY === "scroll" || overflowY === "auto") && element.scrollHeight > element.clientHeight,
878
+ horizontal: (overflowX === "scroll" || overflowX === "auto") && element.scrollWidth > element.clientWidth
879
+ };
880
+ }
881
+ function observeElementProp(element, property, callback) {
882
+ const elementPrototype = Object.getPrototypeOf(element);
883
+ if (elementPrototype.hasOwnProperty(property)) {
884
+ const descriptor = Object.getOwnPropertyDescriptor(elementPrototype, property);
885
+ Object.defineProperty(element, property, {
886
+ get: function() {
887
+ var _a;
888
+ return (_a = descriptor == null ? void 0 : descriptor.get) == null ? void 0 : _a.apply(this, arguments);
889
+ },
890
+ set: function() {
891
+ var _a;
892
+ const oldValue = this[property];
893
+ (_a = descriptor == null ? void 0 : descriptor.set) == null ? void 0 : _a.apply(this, arguments);
894
+ const newValue = this[property];
895
+ if (typeof callback === "function")
896
+ callback.bind(this, oldValue, newValue);
897
+ return newValue;
898
+ }
899
+ });
900
+ }
901
+ }
902
+ function getSiblingsFrame(refElement, siblingAmount, refElementAlignment = "center-top", includeRef = true) {
903
+ var _a;
904
+ const siblings = [...((_a = refElement.parentNode) == null ? void 0 : _a.childNodes) ?? []];
905
+ const elemSiblIdx = siblings.indexOf(refElement);
906
+ if (elemSiblIdx === -1)
907
+ throw new Error("Element doesn't have a parent node");
908
+ if (refElementAlignment === "top")
909
+ return [...siblings.slice(elemSiblIdx + Number(!includeRef), elemSiblIdx + siblingAmount + Number(!includeRef))];
910
+ else if (refElementAlignment.startsWith("center-")) {
911
+ const halfAmount = (refElementAlignment === "center-bottom" ? Math.ceil : Math.floor)(siblingAmount / 2);
912
+ const startIdx = Math.max(0, elemSiblIdx - halfAmount);
913
+ const topOffset = Number(refElementAlignment === "center-top" && siblingAmount % 2 === 0 && includeRef);
914
+ const btmOffset = Number(refElementAlignment === "center-bottom" && siblingAmount % 2 !== 0 && includeRef);
915
+ const startIdxWithOffset = startIdx + topOffset + btmOffset;
916
+ return [
917
+ ...siblings.filter((_, idx) => includeRef || idx !== elemSiblIdx).slice(startIdxWithOffset, startIdxWithOffset + siblingAmount)
918
+ ];
919
+ } else if (refElementAlignment === "bottom")
920
+ return [...siblings.slice(elemSiblIdx - siblingAmount + Number(includeRef), elemSiblIdx + Number(includeRef))];
921
+ return [];
922
+ }
923
+ var ttPolicy;
924
+ function setInnerHtmlUnsafe(element, html) {
925
+ var _a, _b;
926
+ if (!ttPolicy && typeof ((_a = window == null ? void 0 : window.trustedTypes) == null ? void 0 : _a.createPolicy) === "function") {
927
+ ttPolicy = window.trustedTypes.createPolicy("_uu_set_innerhtml_unsafe", {
928
+ createHTML: (unsafeHtml) => unsafeHtml
929
+ });
930
+ }
931
+ element.innerHTML = ((_b = ttPolicy == null ? void 0 : ttPolicy.createHTML) == null ? void 0 : _b.call(ttPolicy, html)) ?? html;
932
+ return element;
933
+ }
934
+ function probeElementStyle(probeStyle, element, hideOffscreen = true, parentElement = document.body) {
935
+ const el = element ? typeof element === "function" ? element() : element : document.createElement("span");
936
+ if (hideOffscreen) {
937
+ el.style.position = "absolute";
938
+ el.style.left = "-9999px";
939
+ el.style.top = "-9999px";
940
+ el.style.zIndex = "-9999";
941
+ }
942
+ el.classList.add("_uu_probe_element");
943
+ parentElement.appendChild(el);
944
+ const style = window.getComputedStyle(el);
945
+ const result = probeStyle(style, el);
946
+ setTimeout(() => el.remove(), 1);
947
+ return result;
948
+ }
949
+ var domReady = document.readyState !== "loading";
950
+ !domReady && document.addEventListener("DOMContentLoaded", () => domReady = true, { once: true });
951
+ function isDomLoaded() {
952
+ return domReady;
953
+ }
954
+ function onDomLoad(cb) {
955
+ return new Promise((res) => {
956
+ if (domReady) {
957
+ cb == null ? void 0 : cb();
958
+ res();
959
+ } else
960
+ document.addEventListener("DOMContentLoaded", () => {
961
+ cb == null ? void 0 : cb();
962
+ res();
963
+ }, { once: true });
964
+ });
965
+ }
966
+
967
+ // lib/Dialog.ts
968
+ var defaultDialogCss = `.uu-no-select {
969
+ user-select: none;
970
+ }
971
+
972
+ .uu-dialog-bg {
973
+ --uu-dialog-bg: #333333;
974
+ --uu-dialog-bg-highlight: #252525;
975
+ --uu-scroll-indicator-bg: rgba(10, 10, 10, 0.7);
976
+ --uu-dialog-separator-color: #797979;
977
+ --uu-dialog-border-radius: 10px;
978
+ }
979
+
980
+ .uu-dialog-bg {
981
+ display: block;
982
+ position: fixed;
983
+ width: 100%;
984
+ height: 100%;
985
+ top: 0;
986
+ left: 0;
987
+ z-index: 5;
988
+ background-color: rgba(0, 0, 0, 0.6);
989
+ }
990
+
991
+ .uu-dialog {
992
+ --uu-calc-dialog-height: calc(min(100vh - 40px, var(--uu-dialog-height-max)));
993
+ position: absolute;
994
+ display: flex;
995
+ flex-direction: column;
996
+ width: calc(min(100% - 60px, var(--uu-dialog-width-max)));
997
+ border-radius: var(--uu-dialog-border-radius);
998
+ height: auto;
999
+ max-height: var(--uu-calc-dialog-height);
1000
+ left: 50%;
1001
+ top: 50%;
1002
+ transform: translate(-50%, -50%);
1003
+ z-index: 6;
1004
+ color: #fff;
1005
+ background-color: var(--uu-dialog-bg);
1006
+ }
1007
+
1008
+ .uu-dialog.align-top {
1009
+ top: 0;
1010
+ transform: translate(-50%, 40px);
1011
+ }
1012
+
1013
+ .uu-dialog.align-bottom {
1014
+ top: 100%;
1015
+ transform: translate(-50%, -100%);
1016
+ }
1017
+
1018
+ .uu-dialog-body {
1019
+ font-size: 1.5rem;
1020
+ padding: 20px;
1021
+ }
1022
+
1023
+ .uu-dialog-body.small {
1024
+ padding: 15px;
1025
+ }
1026
+
1027
+ #uu-dialog-opts {
1028
+ display: flex;
1029
+ flex-direction: column;
1030
+ position: relative;
1031
+ padding: 30px 0px;
1032
+ overflow-y: auto;
1033
+ }
1034
+
1035
+ .uu-dialog-header {
1036
+ display: flex;
1037
+ justify-content: space-between;
1038
+ align-items: center;
1039
+ margin-bottom: 6px;
1040
+ padding: 15px 20px 15px 20px;
1041
+ background-color: var(--uu-dialog-bg);
1042
+ border: 2px solid var(--uu-dialog-separator-color);
1043
+ border-style: none none solid none !important;
1044
+ border-radius: var(--uu-dialog-border-radius) var(--uu-dialog-border-radius) 0px 0px;
1045
+ }
1046
+
1047
+ .uu-dialog-header.small {
1048
+ padding: 10px 15px;
1049
+ border-style: none none solid none !important;
1050
+ }
1051
+
1052
+ .uu-dialog-header-pad {
1053
+ content: " ";
1054
+ min-height: 32px;
1055
+ }
1056
+
1057
+ .uu-dialog-header-pad.small {
1058
+ min-height: 24px;
1059
+ }
1060
+
1061
+ .uu-dialog-titlecont {
1062
+ display: flex;
1063
+ align-items: center;
1064
+ }
1065
+
1066
+ .uu-dialog-titlecont-no-title {
1067
+ display: flex;
1068
+ justify-content: flex-end;
1069
+ align-items: center;
1070
+ }
1071
+
1072
+ .uu-dialog-title {
1073
+ position: relative;
1074
+ display: inline-block;
1075
+ font-size: 22px;
1076
+ }
1077
+
1078
+ .uu-dialog-close {
1079
+ cursor: pointer;
1080
+ }
1081
+
1082
+ .uu-dialog-header-img,
1083
+ .uu-dialog-close
1084
+ {
1085
+ width: 32px;
1086
+ height: 32px;
1087
+ }
1088
+
1089
+ .uu-dialog-header-img.small,
1090
+ .uu-dialog-close.small
1091
+ {
1092
+ width: 24px;
1093
+ height: 24px;
1094
+ }
1095
+
1096
+ .uu-dialog-footer {
1097
+ font-size: 17px;
1098
+ text-decoration: underline;
1099
+ }
1100
+
1101
+ .uu-dialog-footer.hidden {
1102
+ display: none;
1103
+ }
1104
+
1105
+ .uu-dialog-footer-cont {
1106
+ margin-top: 6px;
1107
+ padding: 15px 20px;
1108
+ background: var(--uu-dialog-bg);
1109
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, var(--uu-dialog-bg) 30%, var(--uu-dialog-bg) 100%);
1110
+ border: 2px solid var(--uu-dialog-separator-color);
1111
+ border-style: solid none none none !important;
1112
+ border-radius: 0px 0px var(--uu-dialog-border-radius) var(--uu-dialog-border-radius);
1113
+ }
1114
+
1115
+ .uu-dialog-footer-buttons-cont button:not(:last-of-type) {
1116
+ margin-right: 15px;
1117
+ }`;
1118
+ var currentDialogId = null;
1119
+ var openDialogs = [];
1120
+ var defaultStrings = {
1121
+ closeDialogTooltip: "Click to close the dialog"
1122
+ };
1123
+ var Dialog = class _Dialog extends (void 0) {
1124
+ /** Options passed to the dialog in the constructor */
1125
+ options;
1126
+ /** ID that gets added to child element IDs - has to be unique and conform to HTML ID naming rules! */
1127
+ id;
1128
+ /** Strings used in the dialog (used for translations) */
1129
+ strings;
1130
+ dialogOpen = false;
1131
+ dialogMounted = false;
1132
+ constructor(options) {
1133
+ super();
1134
+ const { strings, ...opts } = options;
1135
+ this.strings = {
1136
+ ...defaultStrings,
1137
+ ...strings ?? {}
1138
+ };
1139
+ this.options = {
1140
+ closeOnBgClick: true,
1141
+ closeOnEscPress: true,
1142
+ destroyOnClose: false,
1143
+ unmountOnClose: true,
1144
+ removeListenersOnDestroy: true,
1145
+ small: false,
1146
+ verticalAlign: "center",
1147
+ ...opts
1148
+ };
1149
+ this.id = opts.id;
1150
+ }
1151
+ //#region public
1152
+ /** Call after DOMContentLoaded to pre-render the dialog and invisibly mount it in the DOM */
1153
+ async mount() {
1154
+ if (this.dialogMounted)
1155
+ return;
1156
+ this.dialogMounted = true;
1157
+ if (!document.querySelector("style.uu-dialog-css"))
1158
+ addGlobalStyle(this.options.dialogCss ?? defaultDialogCss).classList.add("uu-dialog-css");
1159
+ const bgElem = document.createElement("div");
1160
+ bgElem.id = `uu-${this.id}-dialog-bg`;
1161
+ bgElem.classList.add("uu-dialog-bg");
1162
+ if (this.options.closeOnBgClick)
1163
+ bgElem.ariaLabel = bgElem.title = this.getString("closeDialogTooltip");
1164
+ bgElem.style.setProperty("--uu-dialog-width-max", `${this.options.width}px`);
1165
+ bgElem.style.setProperty("--uu-dialog-height-max", `${this.options.height}px`);
1166
+ bgElem.style.visibility = "hidden";
1167
+ bgElem.style.display = "none";
1168
+ bgElem.inert = true;
1169
+ bgElem.appendChild(await this.getDialogContent());
1170
+ document.body.appendChild(bgElem);
1171
+ this.attachListeners(bgElem);
1172
+ this.events.emit("render");
1173
+ return bgElem;
1174
+ }
1175
+ /** Closes the dialog and clears all its contents (unmounts elements from the DOM) in preparation for a new rendering call */
1176
+ unmount() {
1177
+ var _a;
1178
+ this.close();
1179
+ this.dialogMounted = false;
1180
+ const clearSelectors = [
1181
+ `#uu-${this.id}-dialog-bg`,
1182
+ `#uu-style-dialog-${this.id}`
1183
+ ];
1184
+ for (const sel of clearSelectors)
1185
+ (_a = document.querySelector(sel)) == null ? void 0 : _a.remove();
1186
+ this.events.emit("clear");
1187
+ }
1188
+ /** Clears the DOM of the dialog and then renders it again */
1189
+ async remount() {
1190
+ this.unmount();
1191
+ await this.mount();
1192
+ }
1193
+ /**
1194
+ * Opens the dialog - also mounts it if it hasn't been mounted yet
1195
+ * Prevents default action and immediate propagation of the passed event
1196
+ */
1197
+ async open(e) {
1198
+ var _a;
1199
+ e == null ? void 0 : e.preventDefault();
1200
+ e == null ? void 0 : e.stopImmediatePropagation();
1201
+ if (this.isOpen())
1202
+ return;
1203
+ this.dialogOpen = true;
1204
+ if (openDialogs.includes(this.id))
1205
+ throw new Error(`A dialog with the same ID of '${this.id}' already exists and is open!`);
1206
+ if (!this.isMounted())
1207
+ await this.mount();
1208
+ const dialogBg = document.querySelector(`#uu-${this.id}-dialog-bg`);
1209
+ if (!dialogBg)
1210
+ return console.warn(`Couldn't find background element for dialog with ID '${this.id}'`);
1211
+ dialogBg.style.visibility = "visible";
1212
+ dialogBg.style.display = "block";
1213
+ dialogBg.inert = false;
1214
+ currentDialogId = this.id;
1215
+ openDialogs.unshift(this.id);
1216
+ for (const dialogId of openDialogs)
1217
+ if (dialogId !== this.id)
1218
+ (_a = document.querySelector(`#uu-${dialogId}-dialog-bg`)) == null ? void 0 : _a.setAttribute("inert", "true");
1219
+ document.body.classList.remove("uu-no-select");
1220
+ document.body.setAttribute("inert", "true");
1221
+ this.events.emit("open");
1222
+ return dialogBg;
1223
+ }
1224
+ /** Closes the dialog - prevents default action and immediate propagation of the passed event */
1225
+ close(e) {
1226
+ var _a;
1227
+ e == null ? void 0 : e.preventDefault();
1228
+ e == null ? void 0 : e.stopImmediatePropagation();
1229
+ if (!this.isOpen())
1230
+ return;
1231
+ this.dialogOpen = false;
1232
+ const dialogBg = document.querySelector(`#uu-${this.id}-dialog-bg`);
1233
+ if (!dialogBg)
1234
+ return console.warn(`Couldn't find background element for dialog with ID '${this.id}'`);
1235
+ dialogBg.style.visibility = "hidden";
1236
+ dialogBg.style.display = "none";
1237
+ dialogBg.inert = true;
1238
+ openDialogs.splice(openDialogs.indexOf(this.id), 1);
1239
+ currentDialogId = openDialogs[0] ?? null;
1240
+ if (currentDialogId)
1241
+ (_a = document.querySelector(`#uu-${currentDialogId}-dialog-bg`)) == null ? void 0 : _a.removeAttribute("inert");
1242
+ if (openDialogs.length === 0) {
1243
+ document.body.classList.add("uu-no-select");
1244
+ document.body.removeAttribute("inert");
1245
+ }
1246
+ this.events.emit("close");
1247
+ if (this.options.destroyOnClose)
1248
+ this.destroy();
1249
+ else if (this.options.unmountOnClose)
1250
+ this.unmount();
1251
+ }
1252
+ /** Returns true if the dialog is currently open */
1253
+ isOpen() {
1254
+ return this.dialogOpen;
1255
+ }
1256
+ /** Returns true if the dialog is currently mounted */
1257
+ isMounted() {
1258
+ return this.dialogMounted;
1259
+ }
1260
+ /** Clears the DOM of the dialog and removes all event listeners */
1261
+ destroy() {
1262
+ this.unmount();
1263
+ this.events.emit("destroy");
1264
+ this.options.removeListenersOnDestroy && this.unsubscribeAll();
1265
+ }
1266
+ //#region static
1267
+ /** Returns the ID of the top-most dialog (the dialog that has been opened last) */
1268
+ static getCurrentDialogId() {
1269
+ return currentDialogId;
1270
+ }
1271
+ /** Returns the IDs of all currently open dialogs, top-most first */
1272
+ static getOpenDialogs() {
1273
+ return openDialogs;
1274
+ }
1275
+ //#region protected
1276
+ getString(key) {
1277
+ return this.strings[key] ?? defaultStrings[key];
1278
+ }
1279
+ /** Called once to attach all generic event listeners */
1280
+ attachListeners(bgElem) {
1281
+ if (this.options.closeOnBgClick) {
1282
+ bgElem.addEventListener("click", (e) => {
1283
+ var _a;
1284
+ if (this.isOpen() && ((_a = e.target) == null ? void 0 : _a.id) === `uu-${this.id}-dialog-bg`)
1285
+ this.close(e);
1286
+ });
1287
+ }
1288
+ if (this.options.closeOnEscPress) {
1289
+ document.body.addEventListener("keydown", (e) => {
1290
+ if (e.key === "Escape" && this.isOpen() && _Dialog.getCurrentDialogId() === this.id)
1291
+ this.close(e);
1292
+ });
1293
+ }
1294
+ }
1295
+ //#region protected
1296
+ /**
1297
+ * Adds generic, accessible interaction listeners to the passed element.
1298
+ * All listeners have the default behavior prevented and stop propagation (for keyboard events only as long as the captured key is valid).
1299
+ * @param listenerOptions Provide a {@linkcode listenerOptions} object to configure the listeners
1300
+ */
1301
+ onInteraction(elem, listener, listenerOptions) {
1302
+ const { preventDefault = true, stopPropagation = true, ...listenerOpts } = listenerOptions ?? {};
1303
+ const interactionKeys = ["Enter", " ", "Space"];
1304
+ const proxListener = (e) => {
1305
+ if (e instanceof KeyboardEvent) {
1306
+ if (interactionKeys.includes(e.key)) {
1307
+ preventDefault && e.preventDefault();
1308
+ stopPropagation && e.stopPropagation();
1309
+ } else return;
1310
+ } else if (e instanceof MouseEvent) {
1311
+ preventDefault && e.preventDefault();
1312
+ stopPropagation && e.stopPropagation();
1313
+ }
1314
+ (listenerOpts == null ? void 0 : listenerOpts.once) && e.type === "keydown" && elem.removeEventListener("click", proxListener, listenerOpts);
1315
+ (listenerOpts == null ? void 0 : listenerOpts.once) && e.type === "click" && elem.removeEventListener("keydown", proxListener, listenerOpts);
1316
+ listener(e);
1317
+ };
1318
+ elem.addEventListener("click", proxListener, listenerOpts);
1319
+ elem.addEventListener("keydown", proxListener, listenerOpts);
1320
+ }
1321
+ /** Returns the dialog content element and all its children */
1322
+ async getDialogContent() {
1323
+ var _a, _b, _c, _d;
1324
+ const header = (_b = (_a = this.options).renderHeader) == null ? void 0 : _b.call(_a);
1325
+ const footer = (_d = (_c = this.options).renderFooter) == null ? void 0 : _d.call(_c);
1326
+ const dialogWrapperEl = document.createElement("div");
1327
+ dialogWrapperEl.id = `uu-${this.id}-dialog`;
1328
+ dialogWrapperEl.classList.add("uu-dialog");
1329
+ dialogWrapperEl.ariaLabel = dialogWrapperEl.title = "";
1330
+ dialogWrapperEl.role = "dialog";
1331
+ dialogWrapperEl.setAttribute("aria-labelledby", `uu-${this.id}-dialog-title`);
1332
+ dialogWrapperEl.setAttribute("aria-describedby", `uu-${this.id}-dialog-body`);
1333
+ if (this.options.verticalAlign !== "center")
1334
+ dialogWrapperEl.classList.add(`align-${this.options.verticalAlign}`);
1335
+ const headerWrapperEl = document.createElement("div");
1336
+ headerWrapperEl.classList.add("uu-dialog-header");
1337
+ this.options.small && headerWrapperEl.classList.add("small");
1338
+ if (header) {
1339
+ const headerTitleWrapperEl = document.createElement("div");
1340
+ headerTitleWrapperEl.id = `uu-${this.id}-dialog-title`;
1341
+ headerTitleWrapperEl.classList.add("uu-dialog-title-wrapper");
1342
+ headerTitleWrapperEl.role = "heading";
1343
+ headerTitleWrapperEl.ariaLevel = "1";
1344
+ headerTitleWrapperEl.appendChild(header instanceof Promise ? await header : header);
1345
+ headerWrapperEl.appendChild(headerTitleWrapperEl);
1346
+ } else {
1347
+ const padEl = document.createElement("div");
1348
+ padEl.classList.add("uu-dialog-header-pad", this.options.small ? "small" : "");
1349
+ headerWrapperEl.appendChild(padEl);
1350
+ }
1351
+ if (this.options.renderCloseBtn) {
1352
+ const closeBtnEl = await this.options.renderCloseBtn();
1353
+ closeBtnEl.classList.add("uu-dialog-close");
1354
+ this.options.small && closeBtnEl.classList.add("small");
1355
+ closeBtnEl.tabIndex = 0;
1356
+ if (closeBtnEl.hasAttribute("alt"))
1357
+ closeBtnEl.setAttribute("alt", this.getString("closeDialogTooltip"));
1358
+ closeBtnEl.title = closeBtnEl.ariaLabel = this.getString("closeDialogTooltip");
1359
+ this.onInteraction(closeBtnEl, () => this.close());
1360
+ headerWrapperEl.appendChild(closeBtnEl);
1361
+ }
1362
+ dialogWrapperEl.appendChild(headerWrapperEl);
1363
+ const dialogBodyElem = document.createElement("div");
1364
+ dialogBodyElem.id = `uu-${this.id}-dialog-body`;
1365
+ dialogBodyElem.classList.add("uu-dialog-body");
1366
+ this.options.small && dialogBodyElem.classList.add("small");
1367
+ const body = this.options.renderBody();
1368
+ dialogBodyElem.appendChild(body instanceof Promise ? await body : body);
1369
+ dialogWrapperEl.appendChild(dialogBodyElem);
1370
+ if (footer) {
1371
+ const footerWrapper = document.createElement("div");
1372
+ footerWrapper.classList.add("uu-dialog-footer-cont");
1373
+ dialogWrapperEl.appendChild(footerWrapper);
1374
+ footerWrapper.appendChild(footer instanceof Promise ? await footer : footer);
1375
+ }
1376
+ return dialogWrapperEl;
1377
+ }
1378
+ };
1379
+
1380
+ // lib/GMStorageEngine.ts
1381
+ var GMStorageEngine = class extends (void 0) {
1382
+ options;
1383
+ /**
1384
+ * Creates an instance of `GMStorageEngine`.
1385
+ *
1386
+ * - ⚠️ Requires the grants `GM.getValue`, `GM.setValue`, `GM.deleteValue`, and `GM.listValues` in your userscript metadata.
1387
+ * - ⚠️ Don't reuse engine instances, always create a new one for each {@linkcode DataStore} instance.
1388
+ */
1389
+ constructor(options) {
1390
+ super(options == null ? void 0 : options.dataStoreOptions);
1391
+ this.options = {
1392
+ ...options
1393
+ };
1394
+ }
1395
+ /** Fetches a value from persistent storage */
1396
+ async getValue(name, defaultValue) {
1397
+ try {
1398
+ if (!("GM" in globalThis))
1399
+ throw new PlatformError("GM is not defined. Make sure to run this in a userscript environment and that the necessary grants are set.");
1400
+ const value = await globalThis.GM.getValue(name, defaultValue);
1401
+ return value === void 0 ? defaultValue : value;
1402
+ } catch (err) {
1403
+ console.error(`Error getting value for key "${name}":`, err);
1404
+ throw err;
1405
+ }
1406
+ }
1407
+ /** Sets a value in persistent storage */
1408
+ async setValue(name, value) {
1409
+ try {
1410
+ if (!("GM" in globalThis))
1411
+ throw new PlatformError("GM is not defined. Make sure to run this in a userscript environment and that the necessary grants are set.");
1412
+ await globalThis.GM.setValue(name, value);
1413
+ } catch (err) {
1414
+ console.error(`Error setting value for key "${name}":`, err);
1415
+ throw err;
1416
+ }
1417
+ }
1418
+ /** Deletes a value from persistent storage */
1419
+ async deleteValue(name) {
1420
+ try {
1421
+ if (!("GM" in globalThis))
1422
+ throw new PlatformError("GM is not defined. Make sure to run this in a userscript environment and that the necessary grants are set.");
1423
+ await globalThis.GM.deleteValue(name);
1424
+ } catch (err) {
1425
+ console.error(`Error deleting value for key "${name}":`, err);
1426
+ throw err;
1427
+ }
1428
+ }
1429
+ /** Deletes all values from GM storage. Use with caution! */
1430
+ async deleteStorage() {
1431
+ try {
1432
+ if (!("GM" in globalThis))
1433
+ throw new PlatformError("GM is not defined. Make sure to run this in a userscript environment and that the necessary grants are set.");
1434
+ const keys = await globalThis.GM.listValues();
1435
+ for (const key of keys)
1436
+ await globalThis.GM.deleteValue(key);
1437
+ } catch (err) {
1438
+ console.error("Error deleting storage:", err);
1439
+ throw err;
1440
+ }
1441
+ }
1442
+ };
1443
+
1444
+ // lib/Mixins.ts
1445
+ var Mixins = class {
1446
+ /** List of all registered mixins */
1447
+ mixins = [];
1448
+ /** Default configuration object for mixins */
1449
+ defaultMixinCfg;
1450
+ /** Whether the priorities should auto-increment if not specified */
1451
+ autoIncPrioEnabled;
1452
+ /** The current auto-increment priority counter */
1453
+ autoIncPrioCounter = /* @__PURE__ */ new Map();
1454
+ /**
1455
+ * Creates a new Mixins instance.
1456
+ * @param config Configuration object to customize the behavior.
1457
+ */
1458
+ constructor(config = {}) {
1459
+ this.defaultMixinCfg = (void 0)({
1460
+ priority: config.defaultPriority ?? 0,
1461
+ stopPropagation: config.defaultStopPropagation ?? false,
1462
+ signal: config.defaultSignal
1463
+ });
1464
+ this.autoIncPrioEnabled = config.autoIncrementPriority ?? false;
1465
+ }
1466
+ //#region public
1467
+ /**
1468
+ * Adds a mixin function to the given {@linkcode mixinKey}.
1469
+ * If no priority is specified, it will be calculated via the protected method {@linkcode calcPriority()} based on the constructor configuration, or fall back to the default priority.
1470
+ * @param mixinKey The key to identify the mixin function.
1471
+ * @param mixinFn The function to be called to apply the mixin. The first argument is the input value, the second argument is the context object (if any).
1472
+ * @param config Configuration object to customize the mixin behavior, or just the priority if a number is passed.
1473
+ * @returns Returns a cleanup function, to be called when this mixin is no longer needed.
1474
+ */
1475
+ add(mixinKey, mixinFn, config = (void 0)({})) {
1476
+ const calcPrio = typeof config === "number" ? config : this.calcPriority(mixinKey, config);
1477
+ const mixin = (void 0)({
1478
+ ...this.defaultMixinCfg,
1479
+ key: mixinKey,
1480
+ fn: mixinFn,
1481
+ ...typeof config === "object" ? config : {},
1482
+ ...typeof calcPrio === "number" && !isNaN(calcPrio) ? { priority: calcPrio } : {}
1483
+ });
1484
+ this.mixins.push(mixin);
1485
+ const rem = () => {
1486
+ this.mixins = this.mixins.filter((m) => m !== mixin);
1487
+ };
1488
+ if (mixin.signal)
1489
+ mixin.signal.addEventListener("abort", rem, { once: true });
1490
+ return rem;
1491
+ }
1492
+ /** Returns a list of all added mixins with their keys and configuration objects, but not their functions */
1493
+ list() {
1494
+ return this.mixins.map(({ fn: _f, ...rest }) => rest);
1495
+ }
1496
+ /**
1497
+ * Applies all mixins with the given key to the input value, respecting the priority and stopPropagation settings.
1498
+ * If additional context is set in the MixinMap, it will need to be passed as the third argument.
1499
+ * @returns The modified value after all mixins have been applied. The method will return a Promise if at least one of the mixins is async. If all mixins are indicated to be synchronous in TS, but at least one of them turns out to be asynchronous, the return type will be a Promise. With `await`, this will not make a difference, but `.then().catch()` could be affected.
1500
+ */
1501
+ resolve(mixinKey, inputValue, ...inputCtx) {
1502
+ const mixins = this.mixins.filter((m) => m.key === mixinKey);
1503
+ const sortedMixins = [...mixins].sort((a, b) => b.priority - a.priority);
1504
+ let result = inputValue;
1505
+ for (let i = 0; i < sortedMixins.length; i++) {
1506
+ const mixin = sortedMixins[i];
1507
+ result = mixin.fn(result, ...inputCtx);
1508
+ if (result instanceof Promise) {
1509
+ return (async () => {
1510
+ result = await result;
1511
+ if (mixin.stopPropagation)
1512
+ return result;
1513
+ for (let j = i + 1; j < sortedMixins.length; j++) {
1514
+ const mixin2 = sortedMixins[j];
1515
+ result = await mixin2.fn(result, ...inputCtx);
1516
+ if (mixin2.stopPropagation)
1517
+ break;
1518
+ }
1519
+ return result;
1520
+ })();
1521
+ } else if (mixin.stopPropagation)
1522
+ break;
1523
+ }
1524
+ return result;
1525
+ }
1526
+ //#region protected
1527
+ /** Calculates the priority for a mixin based on the given configuration and the current auto-increment state of the instance */
1528
+ calcPriority(mixinKey, config) {
1529
+ if (config.priority !== void 0)
1530
+ return void 0;
1531
+ if (!this.autoIncPrioEnabled)
1532
+ return config.priority ?? this.defaultMixinCfg.priority;
1533
+ if (!this.autoIncPrioCounter.has(mixinKey))
1534
+ this.autoIncPrioCounter.set(mixinKey, this.defaultMixinCfg.priority);
1535
+ let prio = this.autoIncPrioCounter.get(mixinKey);
1536
+ while (this.mixins.some((m) => m.key === mixinKey && m.priority === prio))
1537
+ prio++;
1538
+ this.autoIncPrioCounter.set(mixinKey, prio + 1);
1539
+ return prio;
1540
+ }
1541
+ /**
1542
+ * Removes all mixins with the given key.
1543
+ * Note: this method is protected to avoid third-party code from removing mixins. If needed, you can extend the Mixins class and expose this method publicly.
1544
+ */
1545
+ removeAll(mixinKey) {
1546
+ this.mixins.filter((m) => m.key === mixinKey);
1547
+ this.mixins = this.mixins.filter((m) => m.key !== mixinKey);
1548
+ }
1549
+ };
1550
+
1551
+ // lib/SelectorObserver.ts
1552
+ var SelectorObserver = class {
1553
+ enabled = false;
1554
+ baseElement;
1555
+ observer;
1556
+ observerOptions;
1557
+ customOptions;
1558
+ listenerMap;
1559
+ constructor(baseElement, options = {}) {
1560
+ this.baseElement = baseElement;
1561
+ this.listenerMap = /* @__PURE__ */ new Map();
1562
+ const {
1563
+ defaultDebounce,
1564
+ defaultDebounceType,
1565
+ disableOnNoListeners,
1566
+ enableOnAddListener,
1567
+ ...observerOptions
1568
+ } = options;
1569
+ this.observerOptions = {
1570
+ childList: true,
1571
+ subtree: true,
1572
+ ...observerOptions
1573
+ };
1574
+ this.customOptions = {
1575
+ defaultDebounce: defaultDebounce ?? 0,
1576
+ defaultDebounceType: defaultDebounceType ?? "immediate",
1577
+ disableOnNoListeners: disableOnNoListeners ?? false,
1578
+ enableOnAddListener: enableOnAddListener ?? true
1579
+ };
1580
+ if (typeof this.customOptions.checkInterval !== "number") {
1581
+ this.observer = new MutationObserver(() => this.checkAllSelectors());
1582
+ } else {
1583
+ this.checkAllSelectors();
1584
+ setInterval(() => this.checkAllSelectors(), this.customOptions.checkInterval);
1585
+ }
1586
+ }
1587
+ /** Call to check all selectors in the {@linkcode listenerMap} using {@linkcode checkSelector()} */
1588
+ checkAllSelectors() {
1589
+ if (!this.enabled || !isDomLoaded())
1590
+ return;
1591
+ for (const [selector, listeners] of this.listenerMap.entries())
1592
+ this.checkSelector(selector, listeners);
1593
+ }
1594
+ /** Checks if the element(s) with the given {@linkcode selector} exist in the DOM and calls the respective {@linkcode listeners} accordingly */
1595
+ checkSelector(selector, listeners) {
1596
+ var _a;
1597
+ if (!this.enabled)
1598
+ return;
1599
+ const baseElement = typeof this.baseElement === "string" ? document.querySelector(this.baseElement) : this.baseElement;
1600
+ if (!baseElement)
1601
+ return;
1602
+ const all = listeners.some((listener) => listener.all);
1603
+ const one = listeners.some((listener) => !listener.all);
1604
+ const allElements = all ? baseElement.querySelectorAll(selector) : null;
1605
+ const oneElement = one ? baseElement.querySelector(selector) : null;
1606
+ for (const options of listeners) {
1607
+ if (options.all) {
1608
+ if (allElements && allElements.length > 0) {
1609
+ options.listener(allElements);
1610
+ if (!options.continuous)
1611
+ this.removeListener(selector, options);
1612
+ }
1613
+ } else {
1614
+ if (oneElement) {
1615
+ options.listener(oneElement);
1616
+ if (!options.continuous)
1617
+ this.removeListener(selector, options);
1618
+ }
1619
+ }
1620
+ if (((_a = this.listenerMap.get(selector)) == null ? void 0 : _a.length) === 0)
1621
+ this.listenerMap.delete(selector);
1622
+ if (this.listenerMap.size === 0 && this.customOptions.disableOnNoListeners)
1623
+ this.disable();
1624
+ }
1625
+ }
1626
+ /**
1627
+ * Starts observing the children of the base element for changes to the given {@linkcode selector} according to the set {@linkcode options}
1628
+ * @param selector The selector to observe
1629
+ * @param options Options for the selector observation
1630
+ * @param options.listener Gets called whenever the selector was found in the DOM
1631
+ * @param [options.all] Whether to use `querySelectorAll()` instead - default is false
1632
+ * @param [options.continuous] Whether to call the listener continuously instead of just once - default is false
1633
+ * @param [options.debounce] Whether to debounce the listener to reduce calls to `querySelector` or `querySelectorAll` - set undefined or <=0 to disable (default)
1634
+ * @returns Returns a function that can be called to remove this listener more easily
1635
+ */
1636
+ addListener(selector, options) {
1637
+ options = {
1638
+ all: false,
1639
+ continuous: false,
1640
+ debounce: 0,
1641
+ ...options
1642
+ };
1643
+ if (options.debounce && options.debounce > 0 || this.customOptions.defaultDebounce && this.customOptions.defaultDebounce > 0) {
1644
+ options.listener = (void 0)(
1645
+ options.listener,
1646
+ options.debounce || this.customOptions.defaultDebounce,
1647
+ options.debounceType || this.customOptions.defaultDebounceType
1648
+ );
1649
+ }
1650
+ if (this.listenerMap.has(selector))
1651
+ this.listenerMap.get(selector).push(options);
1652
+ else
1653
+ this.listenerMap.set(selector, [options]);
1654
+ if (this.enabled === false && this.customOptions.enableOnAddListener)
1655
+ this.enable();
1656
+ this.checkSelector(selector, [options]);
1657
+ return () => this.removeListener(selector, options);
1658
+ }
1659
+ /** Disables the observation of the child elements */
1660
+ disable() {
1661
+ var _a;
1662
+ if (!this.enabled)
1663
+ return;
1664
+ this.enabled = false;
1665
+ (_a = this.observer) == null ? void 0 : _a.disconnect();
1666
+ }
1667
+ /**
1668
+ * Enables or reenables the observation of the child elements.
1669
+ * @param immediatelyCheckSelectors Whether to immediately check if all previously registered selectors exist (default is true)
1670
+ * @returns Returns true when the observation was enabled, false otherwise (e.g. when the base element wasn't found)
1671
+ */
1672
+ enable(immediatelyCheckSelectors = true) {
1673
+ var _a;
1674
+ const baseElement = typeof this.baseElement === "string" ? document.querySelector(this.baseElement) : this.baseElement;
1675
+ if (this.enabled || !baseElement)
1676
+ return false;
1677
+ this.enabled = true;
1678
+ (_a = this.observer) == null ? void 0 : _a.observe(baseElement, this.observerOptions);
1679
+ if (immediatelyCheckSelectors)
1680
+ this.checkAllSelectors();
1681
+ return true;
1682
+ }
1683
+ /** Returns whether the observation of the child elements is currently enabled */
1684
+ isEnabled() {
1685
+ return this.enabled;
1686
+ }
1687
+ /** Removes all listeners that have been registered with {@linkcode addListener()} */
1688
+ clearListeners() {
1689
+ this.listenerMap.clear();
1690
+ }
1691
+ /**
1692
+ * Removes all listeners for the given {@linkcode selector} that have been registered with {@linkcode addListener()}
1693
+ * @returns Returns true when all listeners for the associated selector were found and removed, false otherwise
1694
+ */
1695
+ removeAllListeners(selector) {
1696
+ return this.listenerMap.delete(selector);
1697
+ }
1698
+ /**
1699
+ * Removes a single listener for the given {@linkcode selector} and {@linkcode options} that has been registered with {@linkcode addListener()}
1700
+ * @returns Returns true when the listener was found and removed, false otherwise
1701
+ */
1702
+ removeListener(selector, options) {
1703
+ const listeners = this.listenerMap.get(selector);
1704
+ if (!listeners)
1705
+ return false;
1706
+ const index = listeners.indexOf(options);
1707
+ if (index > -1) {
1708
+ listeners.splice(index, 1);
1709
+ return true;
1710
+ }
1711
+ return false;
1712
+ }
1713
+ /** Returns all listeners that have been registered with {@linkcode addListener()} */
1714
+ getAllListeners() {
1715
+ return this.listenerMap;
1716
+ }
1717
+ /** Returns all listeners for the given {@linkcode selector} that have been registered with {@linkcode addListener()} */
1718
+ getListeners(selector) {
1719
+ return this.listenerMap.get(selector);
1720
+ }
1721
+ };
1722
+
1723
+ // lib/translation.ts
1724
+ var trans = {};
1725
+ var valTransforms = [];
1726
+ var fallbackLang;
1727
+ function translate(language, key, ...trArgs) {
1728
+ if (typeof language !== "string")
1729
+ language = fallbackLang ?? "";
1730
+ const trObj = trans[language];
1731
+ if (typeof language !== "string" || language.length === 0 || typeof trObj !== "object" || trObj === null)
1732
+ return fallbackLang && language !== fallbackLang ? translate(fallbackLang, key, ...trArgs) : key;
1733
+ const transformTrVal = (trKey, trValue) => {
1734
+ const tfs = valTransforms.filter(({ regex }) => new RegExp(regex).test(String(trValue)));
1735
+ if (tfs.length === 0)
1736
+ return String(trValue);
1737
+ let retStr = String(trValue);
1738
+ for (const tf of tfs) {
1739
+ const re = new RegExp(tf.regex);
1740
+ const matches = [];
1741
+ let execRes;
1742
+ while ((execRes = re.exec(trValue)) !== null) {
1743
+ if (matches.some((m) => m[0] === (execRes == null ? void 0 : execRes[0]) && m.index === (execRes == null ? void 0 : execRes.index)))
1744
+ break;
1745
+ matches.push(execRes);
1746
+ }
1747
+ retStr = String(tf.fn({
1748
+ language,
1749
+ trValue,
1750
+ currentValue: retStr,
1751
+ matches,
1752
+ trKey,
1753
+ trArgs
1754
+ }));
1755
+ }
1756
+ return retStr;
1757
+ };
1758
+ const keyParts = key.split(".");
1759
+ let value = trObj;
1760
+ for (const part of keyParts) {
1761
+ if (typeof value !== "object" || value === null) {
1762
+ value = void 0;
1763
+ break;
1764
+ }
1765
+ value = value == null ? void 0 : value[part];
1766
+ }
1767
+ if (typeof value === "string")
1768
+ return transformTrVal(key, value);
1769
+ value = trObj == null ? void 0 : trObj[key];
1770
+ if (typeof value === "string")
1771
+ return transformTrVal(key, value);
1772
+ return fallbackLang && language !== fallbackLang ? translate(fallbackLang, key, ...trArgs) : key;
1773
+ }
1774
+ function trFor(language, key, ...args) {
1775
+ const txt = translate(language, key, ...args);
1776
+ if (txt === key)
1777
+ return fallbackLang ? translate(fallbackLang, key, ...args) : key;
1778
+ return txt;
1779
+ }
1780
+ function useTr(language) {
1781
+ return (key, ...args) => translate(language, key, ...args);
1782
+ }
1783
+ function hasKey(language = fallbackLang ?? "", key) {
1784
+ return tr.for(language, key) !== key;
1785
+ }
1786
+ function addTranslations(language, translations) {
1787
+ trans[language] = JSON.parse(JSON.stringify(translations));
1788
+ }
1789
+ function getTranslations(language = fallbackLang ?? "") {
1790
+ return trans[language];
1791
+ }
1792
+ var deleteTranslations = (language) => {
1793
+ if (language in trans) {
1794
+ delete trans[language];
1795
+ return true;
1796
+ }
1797
+ return false;
1798
+ };
1799
+ function setFallbackLanguage(fallbackLanguage) {
1800
+ fallbackLang = fallbackLanguage;
1801
+ }
1802
+ function getFallbackLanguage() {
1803
+ return fallbackLang;
1804
+ }
1805
+ function addTransform(transform) {
1806
+ const [regex, fn] = transform;
1807
+ valTransforms.push({
1808
+ fn,
1809
+ regex
1810
+ });
1811
+ }
1812
+ function deleteTransform(patternOrFn) {
1813
+ const idx = valTransforms.findIndex(
1814
+ (t) => typeof patternOrFn === "function" ? t.fn === patternOrFn : t.regex === patternOrFn
1815
+ );
1816
+ if (idx !== -1) {
1817
+ valTransforms.splice(idx, 1);
1818
+ return true;
1819
+ }
1820
+ return false;
1821
+ }
1822
+ var templateLiteralTransform = [
1823
+ /\$\{([a-zA-Z0-9$_-]+)\}/gm,
1824
+ ({ matches, trArgs, trValue }) => {
1825
+ const patternStart = "${", patternEnd = "}", patternRegex = /\$\{.+\}/m;
1826
+ let str = String(trValue);
1827
+ const eachKeyInTrString = (keys) => keys.every((key) => trValue.includes(`${patternStart}${key}${patternEnd}`));
1828
+ const namedMapping = () => {
1829
+ if (!str.includes(patternStart) || typeof trArgs[0] === "undefined" || typeof trArgs[0] !== "object" || !eachKeyInTrString(Object.keys(trArgs[0] ?? {})))
1830
+ return;
1831
+ for (const match of matches) {
1832
+ const repl = match[1] !== void 0 ? trArgs[0][match[1]] : void 0;
1833
+ if (typeof repl !== "undefined")
1834
+ str = str.replace(match[0], String(repl));
1835
+ }
1836
+ };
1837
+ const positionalMapping = () => {
1838
+ if (!patternRegex.test(str) || !trArgs[0])
1839
+ return;
1840
+ let matchNum = -1;
1841
+ for (const match of matches) {
1842
+ matchNum++;
1843
+ if (typeof trArgs[matchNum] !== "undefined")
1844
+ str = str.replace(match[0], String(trArgs[matchNum]));
1845
+ }
1846
+ };
1847
+ let notStringifiable = false;
1848
+ try {
1849
+ String(trArgs[0]);
1850
+ } catch {
1851
+ notStringifiable = true;
1852
+ }
1853
+ const isArgsObject = trArgs[0] && typeof trArgs[0] === "object" && trArgs[0] !== null && (notStringifiable || String(trArgs[0]).startsWith("[object"));
1854
+ if (isArgsObject && eachKeyInTrString(Object.keys(trArgs[0])))
1855
+ namedMapping();
1856
+ else
1857
+ positionalMapping();
1858
+ return str;
1859
+ }
1860
+ ];
1861
+ var percentTransform = [
1862
+ /%(\d+)/gm,
1863
+ ({ matches, trArgs, trValue }) => {
1864
+ let str = String(trValue);
1865
+ for (const match of matches) {
1866
+ const repl = match[1] !== void 0 ? trArgs == null ? void 0 : trArgs[Number(match[1]) - 1] : void 0;
1867
+ if (typeof repl !== "undefined")
1868
+ str = str.replace(match[0], String(repl));
1869
+ }
1870
+ return str;
1871
+ }
1872
+ ];
1873
+ var tr = {
1874
+ for: (...params) => trFor(...params),
1875
+ use: (...params) => useTr(...params),
1876
+ hasKey: (language = fallbackLang ?? "", key) => hasKey(language, key),
1877
+ addTranslations,
1878
+ getTranslations,
1879
+ deleteTranslations,
1880
+ setFallbackLanguage,
1881
+ getFallbackLanguage,
1882
+ addTransform,
1883
+ deleteTransform,
1884
+ transforms: {
1885
+ templateLiteral: templateLiteralTransform,
1886
+ percent: percentTransform
1887
+ }
1888
+ };
1889
+ //# sourceMappingURL=UserUtils.cjs.map