@trunkjs/browser-utils 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 1.0.18 (2025-09-11)
2
+
3
+ This was a version bump only for browser-utils to align it with other projects, there were no code changes.
4
+
5
+ ## 1.0.17 (2025-09-11)
6
+
7
+ This was a version bump only for browser-utils to align it with other projects, there were no code changes.
8
+
1
9
  ## 1.0.16 (2025-08-27)
2
10
 
3
11
  This was a version bump only for browser-utils to align it with other projects, there were no code changes.
package/README.md CHANGED
@@ -16,24 +16,13 @@ Exports:
16
16
  Within this monorepo, the package is consumed via path aliases. If you publish or consume it externally, import from the package name:
17
17
 
18
18
  ```ts
19
- import {
20
- create_element,
21
- Debouncer,
22
- Stopwatch,
23
- waitFor,
24
- waitForDomContentLoaded,
25
- waitForLoad,
26
- sleep,
27
- waitForAnimationEnd,
28
- LoggingMixin,
29
- } from '@trunkjs/browser-utils';
19
+ import { } from '@trunkjs/browser-utils';
30
20
  ```
31
21
 
32
- Note: Several utilities depend on browser globals (window, document, performance). Use them in browser-like environments.
33
22
 
34
23
  ## Quick start
35
24
 
36
- ### Create and append an element
25
+ ### `function create_element()`: Create and append an element
37
26
 
38
27
  ```ts
39
28
  import { create_element } from '@trunkjs/browser-utils';
@@ -51,7 +40,7 @@ Notes:
51
40
  - Attributes with value true create boolean attributes (e.g. disabled becomes disabled="").
52
41
  - Attributes with null or undefined are omitted.
53
42
 
54
- ### Debounce input handling
43
+ ### `class Debouncer`:Debounce input handling
55
44
 
56
45
  ```ts
57
46
  import { Debouncer } from '@trunkjs/browser-utils';
@@ -77,7 +66,7 @@ window.addEventListener('resize', () => {
77
66
  });
78
67
  ```
79
68
 
80
- ### Measure performance with Stopwatch
69
+ ### `class Stopwatch`: Measure performance with Stopwatch
81
70
 
82
71
  ```ts
83
72
  import { Stopwatch } from '@trunkjs/browser-utils';
@@ -90,7 +79,7 @@ sw.lap('after step 2');
90
79
  console.debug('Total ms:', sw.stop());
91
80
  ```
92
81
 
93
- ### Enable conditional logging in custom elements (LoggingMixin)
82
+ ### `class LoggingMixin`: Enable conditional logging in custom elements (LoggingMixin)
94
83
 
95
84
  ```ts
96
85
  import { LoggingMixin } from '@trunkjs/browser-utils';
@@ -115,7 +104,37 @@ customElements.define('my-el', MyEl);
115
104
  Tip:
116
105
  - If you toggle the debug attribute at runtime, call el.invalidateDebugCache() so the mixin re-evaluates the attribute on the next log/warn/error call.
117
106
 
118
- ### Promise-based event helpers
107
+ ### `class EventBindingsMixin`: Auto-bind event listeners in custom elements
108
+
109
+ This mixin handles automatic registration and removal of event listeners in custom elements. It uses the `@Listen` decorator to bind class methods to events on specified targets.
110
+
111
+ It will register the events in connectedCallback and remove them in disconnectedCallback.
112
+
113
+ ```ts
114
+ import { EventBindingsMixin } from '@trunkjs/browser-utils';
115
+ import { Listen } from '@trunkjs/browser-utils';
116
+
117
+ class MyEl extends EventBindingsMixin(HTMLElement) {
118
+ @Listen('click', { target: 'this' }) // listens to clicks on the element itself
119
+ onClick(event: MouseEvent) {
120
+ this.log('Element clicked', event);
121
+ }
122
+
123
+ @Listen('resize', { target: 'window' }) // listens to window resize events
124
+ onResize(event: UIEvent) {
125
+ this.log('Window resized', event);
126
+ }
127
+ }
128
+ ```
129
+
130
+ Target options:
131
+ - 'host': the custom element itself
132
+ - 'window': the global window object
133
+ - 'document': the global document object
134
+ - 'shadowRoot': the shadow root of the element (if any)
135
+ - `(element) => EventTarget`: a function returning any EventTarget (e.g. another DOM element)
136
+
137
+ ### `async function waitForXYZ`: Promise-based event helpers
119
138
 
120
139
  ```ts
121
140
  import { waitFor, waitForDomContentLoaded, waitForLoad, sleep, waitForAnimationEnd } from '@trunkjs/browser-utils';
@@ -133,137 +152,7 @@ await sleep(250);
133
152
  await waitForAnimationEnd(document.querySelector('.animate')!);
134
153
  ```
135
154
 
136
- ## API Reference
137
-
138
- ### create_element(tag, attrs?, children?)
139
-
140
- - Signature:
141
- - create_element(tag: string, attrs?: Record<string, string | true | null | undefined>, children?: (Node | string)[] | string | Node): HTMLElement
142
- - Behavior:
143
- - Creates an element, sets provided attributes, and appends children.
144
- - children can be a single Node/string or an array.
145
- - Attribute values:
146
- - true → renders as a boolean attribute with an empty value (e.g. disabled="")
147
- - null/undefined → attribute is omitted
148
- - string → sets the attribute to the given string
149
-
150
- Example:
151
- ```ts
152
- create_element('input', { type: 'checkbox', checked: true });
153
- ```
154
-
155
- ### class Debouncer
156
-
157
- - constructor(delay: number, max_delay: number | false = false)
158
- - delay: debounce window in ms
159
- - max_delay: maximum time a call may be deferred. If false, no max is applied.
160
- - wait(): Promise<true>
161
- - Returns a promise that resolves after delay ms since the last call.
162
- - If max_delay is set and exceeded, the pending timer is not cleared and will resolve soon.
163
- - debounce(callback: () => void): void
164
- - Schedules callback to run after delay ms since the last call.
165
-
166
- Use cases:
167
- - User input throttling (search boxes)
168
- - Resize or scroll handlers
169
- - Preventing excessive network calls
170
-
171
- ### class Stopwatch
172
-
173
- - constructor(label: string, enabled: boolean = true)
174
- - lap(msg?: string): void
175
- - Logs a lap line to console.debug in format: [label] msg +Xs
176
- - elapsed(): number
177
- - Milliseconds since start
178
- - reset(): void
179
- - stop(): number
180
- - Stops the stopwatch and returns elapsed ms
181
- - start(): void
182
- - Starts (or restarts) and resets timings
183
- - isRunning(): boolean
184
-
185
- Notes:
186
- - Uses performance.now() for high-resolution timing
187
- - If enabled is false, lap is a no-op
188
-
189
- ### LoggingMixin(Base)
190
-
191
- - Signature:
192
- - LoggingMixin<TBase extends abstract new (...args: any[]) => object>(Base: TBase): class extends Base
193
- - Adds methods and properties to your Custom Element base class:
194
- - log(...args: any[]): void
195
- - Logs to console.log only when debug is enabled.
196
- - warn(...args: any[]): void
197
- - Always logs to console.warn (independent of debug).
198
- - error(...args: any[]): void
199
- - Always logs to console.error (independent of debug).
200
- - get _debug(): boolean
201
- - Indicates whether debug logging is enabled for the instance.
202
- - invalidateDebugCache(): void
203
- - Clears the cached debug flag. Call this after changing the debug attribute dynamically.
204
-
205
- How debug is determined:
206
- - On first call to log/warn/error, the mixin checks the element’s debug attribute and caches the result.
207
- - The attribute is considered truthy if present and not one of: "false", "0", "off", "no".
208
- - Examples:
209
- - <my-el debug></my-el> → debug ON
210
- - <my-el debug="true"></my-el> → debug ON
211
- - <my-el debug="false"></my-el> → debug OFF
212
- - <my-el></my-el> → debug OFF
213
- - If you toggle the attribute at runtime, call invalidateDebugCache() so the next call re-evaluates it.
214
-
215
- Usage:
216
- ```ts
217
- class MyEl extends LoggingMixin(HTMLElement) {
218
- connectedCallback() {
219
- this.log('connected'); // prints only if debug is ON
220
- this.warn('warning'); // always prints
221
- this.error('error'); // always prints
222
- }
223
- }
224
- ```
225
-
226
- ### waitFor<T>(target, eventName, options?)
227
-
228
- - Signature:
229
- - waitFor<T>(target: EventTarget, eventName: string, options?: AddEventListenerOptions): Promise<T>
230
- - Resolves with the event object T upon first occurrence.
231
-
232
- ### waitForDomContentLoaded()
233
-
234
- - Resolves once the DOM is ready (DOMContentLoaded).
235
- - If the document is already past loading, resolves immediately.
236
-
237
- ### waitForLoad()
238
-
239
- - Resolves once the window load event fires.
240
- - If the document is already complete, resolves immediately.
241
155
 
242
- ### sleep(ms)
243
156
 
244
- - Signature: sleep(ms: number): Promise<void>
245
- - Resolves after the given delay.
246
157
 
247
- ### waitForAnimationEnd(element)
248
-
249
- - Signature: waitForAnimationEnd(element: HTMLElement): Promise<AnimationEvent>
250
- - Resolves when the element fires animationend.
251
-
252
- ## Building
253
-
254
- Run `nx build browser-utils` to build the library.
255
-
256
- The library is configured for:
257
- - ES module output
258
- - TypeScript declaration generation via vite-plugin-dts
259
- - Vite rollup bundling
260
-
261
- ## Running unit tests
262
-
263
- Run `nx test browser-utils` to execute the unit tests via Vitest.
264
-
265
- ## Notes and caveats
266
-
267
- - Environment: Some utilities require browser globals (window, document, performance). Use them in a DOM-capable environment (browser or a DOM-enabled test runner).
268
- - Types: Debouncer uses NodeJS.Timeout type in typings; in browsers, the runtime value is still a timeout handle and works as expected.
269
- - LoggingMixin: Designed for Custom Elements (HTMLElement or frameworks like Lit’s ReactiveElement). The debug attribute is cached for performance; call invalidateDebugCache() after toggling it dynamically. warn and error always log regardless of debug state.
158
+ ## API Reference
package/index.js CHANGED
@@ -1,38 +1,38 @@
1
- var D = Object.defineProperty;
2
- var L = (e) => {
3
- throw TypeError(e);
1
+ var W = Object.defineProperty;
2
+ var L = (t) => {
3
+ throw TypeError(t);
4
4
  };
5
- var M = (e, t, n) => t in e ? D(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
6
- var u = (e, t, n) => M(e, typeof t != "symbol" ? t + "" : t, n), w = (e, t, n) => t.has(e) || L("Cannot " + n);
7
- var a = (e, t, n) => (w(e, t, "read from private field"), n ? n.call(e) : t.get(e)), l = (e, t, n) => t.has(e) ? L("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, n), d = (e, t, n, i) => (w(e, t, "write to private field"), i ? i.call(e, n) : t.set(e, n), n), v = (e, t, n) => (w(e, t, "access private method"), n);
8
- const m = [
5
+ var x = (t, e, n) => e in t ? W(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
6
+ var u = (t, e, n) => x(t, typeof e != "symbol" ? e + "" : e, n), w = (t, e, n) => e.has(t) || L("Cannot " + n);
7
+ var a = (t, e, n) => (w(t, e, "read from private field"), n ? n.call(t) : e.get(t)), l = (t, e, n) => e.has(t) ? L("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, n), c = (t, e, n, i) => (w(t, e, "write to private field"), i ? i.call(t, n) : e.set(t, n), n), v = (t, e, n) => (w(t, e, "access private method"), n);
8
+ const h = [
9
9
  { name: "xs", minWidth: 0 },
10
10
  { name: "sm", minWidth: 576 },
11
11
  { name: "md", minWidth: 768 },
12
12
  { name: "lg", minWidth: 992 },
13
13
  { name: "xl", minWidth: 1200 },
14
14
  { name: "xxl", minWidth: 1400 }
15
- ], y = m.reduce(
16
- (e, t) => (e[t.name] = t.minWidth, e),
15
+ ], y = h.reduce(
16
+ (t, e) => (t[e.name] = e.minWidth, t),
17
17
  {}
18
18
  );
19
- function B(e) {
20
- if (!(e in y))
21
- throw new Error(`Unknown breakpoint: ${e}`);
22
- return y[e];
19
+ function P(t) {
20
+ if (!(t in y))
21
+ throw new Error(`Unknown breakpoint: ${t}`);
22
+ return y[t];
23
23
  }
24
- function P(e) {
25
- e === void 0 && (e = window.innerWidth);
26
- for (let t = m.length - 1; t >= 0; t--)
27
- if (e >= m[t].minWidth)
28
- return m[t].name;
24
+ function B(t) {
25
+ t === void 0 && (t = window.innerWidth);
26
+ for (let e = h.length - 1; e >= 0; e--)
27
+ if (t >= h[e].minWidth)
28
+ return h[e].name;
29
29
  return "xs";
30
30
  }
31
- function _(e, t = {}, n = []) {
31
+ function _(t, e = {}, n = []) {
32
32
  Array.isArray(n) || (n = [n]);
33
- const i = document.createElement(e);
34
- for (const r in t)
35
- t[r] !== null && t[r] !== void 0 && i.setAttribute(r, t[r] !== !0 ? t[r] : "");
33
+ const i = document.createElement(t);
34
+ for (const r in e)
35
+ e[r] !== null && e[r] !== void 0 && i.setAttribute(r, e[r] !== !0 ? e[r] : "");
36
36
  for (const r of n)
37
37
  i.append(typeof r == "string" ? document.createTextNode(r) : r);
38
38
  return i;
@@ -43,77 +43,77 @@ class N {
43
43
  * @param delay Debounce delay in milliseconds
44
44
  * @param max_delay Maximum delay in milliseconds, if false then no maximum delay is applied
45
45
  */
46
- constructor(t, n = !1) {
46
+ constructor(e, n = !1) {
47
47
  u(this, "timeout", null);
48
48
  u(this, "startTimeWithMs", 0);
49
- this.delay = t, this.max_delay = n;
49
+ this.delay = e, this.max_delay = n;
50
50
  }
51
51
  async wait() {
52
- return this.startTimeWithMs === 0 && (this.startTimeWithMs = Date.now()), this.timeout && (this.max_delay === !1 || this.startTimeWithMs + this.max_delay > Date.now()) && clearTimeout(this.timeout), new Promise((t) => {
52
+ return this.startTimeWithMs === 0 && (this.startTimeWithMs = Date.now()), this.timeout && (this.max_delay === !1 || this.startTimeWithMs + this.max_delay > Date.now()) && clearTimeout(this.timeout), new Promise((e) => {
53
53
  this.timeout = setTimeout(() => {
54
- this.startTimeWithMs = 0, t(!0);
54
+ this.startTimeWithMs = 0, e(!0);
55
55
  }, this.delay);
56
56
  });
57
57
  }
58
- debounce(t) {
58
+ debounce(e) {
59
59
  this.timeout && clearTimeout(this.timeout), this.timeout = setTimeout(() => {
60
- t();
60
+ e();
61
61
  }, this.delay);
62
62
  }
63
63
  }
64
- function F(e) {
65
- if (typeof e.lineNumber == "number")
64
+ function F(t) {
65
+ if (typeof t.lineNumber == "number")
66
66
  return {
67
- file: e.fileName || e.sourceURL,
68
- line: e.lineNumber,
69
- column: e.columnNumber ?? void 0
67
+ file: t.fileName || t.sourceURL,
68
+ line: t.lineNumber,
69
+ column: t.columnNumber ?? void 0
70
70
  };
71
- if (typeof e.line == "number")
71
+ if (typeof t.line == "number")
72
72
  return {
73
- file: e.sourceURL,
74
- line: e.line,
75
- column: e.column
73
+ file: t.sourceURL,
74
+ line: t.line,
75
+ column: t.column
76
76
  };
77
- const n = String(e.stack || e.message || "").split(`
77
+ const n = String(t.stack || t.message || "").split(`
78
78
  `), i = /(.*?)(?:\(|@)?(.*?):(\d+):(\d+)\)?$/;
79
79
  for (const r of n) {
80
- const o = r.match(i);
81
- if (o)
82
- return { file: o[2], line: +o[3], column: +o[4] };
80
+ const s = r.match(i);
81
+ if (s)
82
+ return { file: s[2], line: +s[3], column: +s[4] };
83
83
  }
84
- return { file: e.fileName || e.sourceURL };
84
+ return { file: t.fileName || t.sourceURL };
85
85
  }
86
86
  class k {
87
- constructor(t, n, i = "main") {
88
- this._debug = t, this.myElementId = n, this.instanceId = i;
87
+ constructor(e, n, i = "main") {
88
+ this._debug = e, this.myElementId = n, this.instanceId = i;
89
89
  }
90
- log(...t) {
91
- this._debug && console.log(`[LOG][ID:${this.myElementId}:${this.instanceId}]`, ...t);
90
+ log(...e) {
91
+ this._debug && console.log(`[LOG][ID:${this.myElementId}:${this.instanceId}]`, ...e);
92
92
  }
93
- warn(...t) {
94
- console.warn(`[WARN][ID:${this.myElementId}:${this.instanceId}]`, ...t);
93
+ warn(...e) {
94
+ console.warn(`[WARN][ID:${this.myElementId}:${this.instanceId}]`, ...e);
95
95
  }
96
- error(...t) {
97
- console.error(`[ERROR][ID:${this.myElementId}:${this.instanceId}]`, ...t);
96
+ error(...e) {
97
+ console.error(`[ERROR][ID:${this.myElementId}:${this.instanceId}]`, ...e);
98
98
  }
99
- throwError(...t) {
100
- const n = `[ERROR][ID:${this.myElementId}:${this.instanceId}] ${t.join(" ")}`;
101
- throw this.error(...t), new Error(n);
99
+ throwError(...e) {
100
+ const n = `[ERROR][ID:${this.myElementId}:${this.instanceId}] ${e.join(" ")}`;
101
+ throw this.error(...e), new Error(n);
102
102
  }
103
103
  }
104
104
  class O {
105
- constructor(t, n = !0) {
105
+ constructor(e, n = !0) {
106
106
  u(this, "label");
107
107
  u(this, "last");
108
108
  u(this, "startTime");
109
109
  u(this, "running", !1);
110
110
  u(this, "enabled");
111
- this.label = t, this.enabled = n, this.startTime = this.last = performance.now(), this.running = !0;
111
+ this.label = e, this.enabled = n, this.startTime = this.last = performance.now(), this.running = !0;
112
112
  }
113
- lap(t = "") {
113
+ lap(e = "") {
114
114
  if (!this.enabled) return;
115
115
  const n = performance.now(), i = (n - this.last) / 1e3;
116
- this.last = n, console.debug(`[${this.label}] ${t} +${i.toFixed(3)}s`);
116
+ this.last = n, console.debug(`[${this.label}] ${e} +${i.toFixed(3)}s`);
117
117
  }
118
118
  elapsed() {
119
119
  return performance.now() - this.startTime;
@@ -131,95 +131,105 @@ class O {
131
131
  return this.running;
132
132
  }
133
133
  }
134
- function U(e, t, n) {
134
+ function S(t, e, n) {
135
135
  return new Promise((i, r) => {
136
- const o = (g) => {
137
- e.removeEventListener(t, o, n), i(g);
136
+ const s = (g) => {
137
+ t.removeEventListener(e, s, n), i(g);
138
138
  };
139
- e.addEventListener(t, o, n);
139
+ t.addEventListener(e, s, n);
140
140
  });
141
141
  }
142
- function S() {
143
- return document.readyState === "loading" ? new Promise((e) => {
144
- document.addEventListener("DOMContentLoaded", () => e());
142
+ function U() {
143
+ return document.readyState === "loading" ? new Promise((t) => {
144
+ document.addEventListener("DOMContentLoaded", () => t());
145
145
  }) : Promise.resolve();
146
146
  }
147
- function G() {
148
- return document.readyState === "complete" ? Promise.resolve() : new Promise((e) => {
147
+ function H(t = null) {
148
+ if (t || (t = document), t instanceof Document) {
149
+ if (document.readyState === "complete")
150
+ return Promise.resolve();
151
+ } else if (t instanceof HTMLImageElement) {
152
+ if (t.complete)
153
+ return Promise.resolve();
154
+ } else if (t instanceof HTMLVideoElement || t instanceof HTMLAudioElement)
155
+ return t.readyState >= 3 ? Promise.resolve() : new Promise((e) => {
156
+ t.addEventListener("loadeddata", () => e(), { once: !0 });
157
+ });
158
+ return new Promise((e) => {
149
159
  window.addEventListener("load", () => e());
150
160
  });
151
161
  }
152
- function j(e) {
153
- return new Promise((t) => setTimeout(t, e));
162
+ function G(t) {
163
+ return new Promise((e) => setTimeout(e, t));
154
164
  }
155
- function q(e) {
156
- return new Promise((t) => {
165
+ function j(t) {
166
+ return new Promise((e) => {
157
167
  const n = (i) => {
158
- e.removeEventListener("animationend", n), t(i);
168
+ t.removeEventListener("animationend", n), e(i);
159
169
  };
160
- e.addEventListener("animationend", n);
170
+ t.addEventListener("animationend", n);
161
171
  });
162
172
  }
163
173
  const f = Symbol("listenerDefs"), p = Symbol("withEventBindings");
164
- function z(e, t) {
165
- const n = Array.isArray(e) ? e : [e];
174
+ function V(t, e) {
175
+ const n = Array.isArray(t) ? t : [t];
166
176
  return function(i, r) {
167
177
  if (r.kind !== "method") throw new Error("@Listen nur für Methoden");
168
178
  return r.addInitializer(function() {
169
- const o = this.constructor;
170
- (o[f] || (o[f] = [])).push({
179
+ const s = this.constructor;
180
+ (s[f] || (s[f] = [])).push({
171
181
  method: r.name,
172
182
  events: n,
173
- opts: t
183
+ opts: e
174
184
  });
175
- }), function(...o) {
185
+ }), function(...s) {
176
186
  if (!this[p])
177
187
  throw new Error("[EventBindings] @Listen - decorator requires EventBindingMixin.");
178
- return i.apply(this, o);
188
+ return i.apply(this, s);
179
189
  };
180
190
  };
181
191
  }
182
- function A(e, t) {
192
+ function A(t, e) {
183
193
  var n;
184
- return !t || t === "host" ? e : t === "document" ? e.ownerDocument ?? document : t === "window" ? ((n = e.ownerDocument) == null ? void 0 : n.defaultView) ?? window : typeof t == "function" ? t(e) : t;
194
+ return !e || e === "host" ? t : e === "document" ? t.ownerDocument ?? document : e === "window" ? ((n = t.ownerDocument) == null ? void 0 : n.defaultView) ?? window : e === "shadowRoot" ? t.shadowRoot ?? t : typeof e == "function" ? e(t) : e;
185
195
  }
186
- function H(e) {
196
+ function q(t) {
187
197
  var n, i, I;
188
- class t extends e {
189
- constructor(...s) {
190
- super(...s);
198
+ class e extends t {
199
+ constructor(...o) {
200
+ super(...o);
191
201
  l(this, i);
192
202
  l(this, n);
193
203
  this[p] = !0;
194
204
  }
195
205
  connectedCallback() {
196
- var s;
197
- (s = super.connectedCallback) == null || s.call(this), v(this, i, I).call(this);
206
+ var o;
207
+ (o = super.connectedCallback) == null || o.call(this), v(this, i, I).call(this);
198
208
  }
199
209
  disconnectedCallback() {
200
- var s, c;
201
- (s = a(this, n)) == null || s.abort(), (c = super.disconnectedCallback) == null || c.call(this);
210
+ var o, d;
211
+ (o = a(this, n)) == null || o.abort(), (d = super.disconnectedCallback) == null || d.call(this);
202
212
  }
203
213
  }
204
214
  return n = new WeakMap(), i = new WeakSet(), I = function() {
205
- var c, b, E;
206
- (c = a(this, n)) == null || c.abort(), d(this, n, new AbortController());
207
- const s = this.constructor[f] || [];
208
- for (const h of s) {
209
- const $ = A(this, (b = h.opts) == null ? void 0 : b.target), T = ((E = h.opts) == null ? void 0 : E.options) ?? {}, W = this[h.method].bind(this);
210
- for (const x of h.events)
211
- $.addEventListener(x, W, { ...T, signal: a(this, n).signal });
215
+ var d, b, E;
216
+ (d = a(this, n)) == null || d.abort(), c(this, n, new AbortController());
217
+ const o = this.constructor[f] || [];
218
+ for (const m of o) {
219
+ const T = A(this, (b = m.opts) == null ? void 0 : b.target), M = ((E = m.opts) == null ? void 0 : E.options) ?? {}, $ = this[m.method].bind(this);
220
+ for (const D of m.events)
221
+ T.addEventListener(D, $, { ...M, signal: a(this, n).signal });
212
222
  }
213
- }, t;
223
+ }, e;
214
224
  }
215
- let C = 1;
216
- function V(e) {
225
+ let R = 1;
226
+ function z(t) {
217
227
  var n, i, r;
218
- class t extends e {
228
+ class e extends t {
219
229
  constructor() {
220
230
  super(...arguments);
221
231
  l(this, n, null);
222
- l(this, i, C++);
232
+ l(this, i, R++);
223
233
  l(this, r, null);
224
234
  }
225
235
  /**
@@ -227,45 +237,45 @@ function V(e) {
227
237
  * on the next log/warn/error call.
228
238
  */
229
239
  invalidateDebugCache() {
230
- d(this, n, null);
240
+ c(this, n, null);
231
241
  }
232
242
  get _debug() {
233
- return a(this, n) !== null ? a(this, n) : (this instanceof HTMLElement && d(this, n, this.hasAttribute("debug") && !["false", "0", "off", "no"].includes(this.getAttribute("debug") || "")), a(this, n) === !0 && console.log(`[DEBUG][ID:${a(this, i)}] LoggingMixin: Debug mode is enabled for <${this.tagName}>`, this), a(this, n) ?? !1);
243
+ return a(this, n) !== null ? a(this, n) : (this instanceof HTMLElement && c(this, n, this.hasAttribute("debug") && !["false", "0", "off", "no"].includes(this.getAttribute("debug") || "")), a(this, n) === !0 && console.log(`[DEBUG][ID:${a(this, i)}] LoggingMixin: Debug mode is enabled for <${this.tagName}>`, this), a(this, n) ?? !1);
234
244
  }
235
- getLogger(s = "main") {
236
- return a(this, r) || d(this, r, new k(this._debug, `${a(this, i)}`, s)), a(this, r);
245
+ getLogger(o = "main") {
246
+ return a(this, r) || c(this, r, new k(this._debug, `${a(this, i)}`, o)), a(this, r);
237
247
  }
238
- log(...s) {
239
- this.getLogger().log(...s);
248
+ log(...o) {
249
+ this.getLogger().log(...o);
240
250
  }
241
- warn(...s) {
242
- this.getLogger().warn(...s);
251
+ warn(...o) {
252
+ this.getLogger().warn(...o);
243
253
  }
244
- error(...s) {
245
- this.getLogger().error(...s);
254
+ error(...o) {
255
+ this.getLogger().error(...o);
246
256
  }
247
- throwError(...s) {
248
- return this.getLogger().throwError(...s);
257
+ throwError(...o) {
258
+ return this.getLogger().throwError(...o);
249
259
  }
250
260
  }
251
- return n = new WeakMap(), i = new WeakMap(), r = new WeakMap(), t;
261
+ return n = new WeakMap(), i = new WeakMap(), r = new WeakMap(), e;
252
262
  }
253
263
  export {
254
264
  N as Debouncer,
255
- H as EventBindingsMixin,
256
- z as Listen,
265
+ q as EventBindingsMixin,
266
+ V as Listen,
257
267
  k as Logger,
258
- V as LoggingMixin,
268
+ z as LoggingMixin,
259
269
  O as Stopwatch,
260
270
  y as breakpointMap,
261
- m as breakpoints,
271
+ h as breakpoints,
262
272
  _ as create_element,
263
- B as getBreakpointMinWidth,
264
- P as getCurrentBreakpoint,
273
+ P as getBreakpointMinWidth,
274
+ B as getCurrentBreakpoint,
265
275
  F as getErrorLocation,
266
- j as sleep,
267
- U as waitFor,
268
- q as waitForAnimationEnd,
269
- S as waitForDomContentLoaded,
270
- G as waitForLoad
276
+ G as sleep,
277
+ S as waitFor,
278
+ j as waitForAnimationEnd,
279
+ U as waitForDomContentLoaded,
280
+ H as waitForLoad
271
281
  };
package/lib/wait-for.d.ts CHANGED
@@ -1,5 +1,16 @@
1
1
  export declare function waitFor<T>(target: EventTarget, eventName: string, options?: AddEventListenerOptions): Promise<T>;
2
2
  export declare function waitForDomContentLoaded(): Promise<void>;
3
- export declare function waitForLoad(): Promise<void>;
3
+ /**
4
+ * Waits for the load event of the given element or the window if no element is provided.
5
+ *
6
+ * Hanles:
7
+ * - Document: waits for 'load' event if not already loaded
8
+ * - HTMLImageElement: waits for 'load' event if not already complete
9
+ * - HTMLVideoElement and HTMLAudioElement: waits for 'loadeddata' event if not
10
+ *
11
+ *
12
+ * @param element
13
+ */
14
+ export declare function waitForLoad(element?: HTMLElement | Document | null): Promise<void>;
4
15
  export declare function sleep(ms: number): Promise<void>;
5
16
  export declare function waitForAnimationEnd(element: HTMLElement): Promise<AnimationEvent>;
@@ -1,5 +1,5 @@
1
1
  type Ctor<T = object> = new (...args: any[]) => T;
2
- type TargetSpec = 'host' | 'document' | 'window' | EventTarget | ((host: HTMLElement) => EventTarget);
2
+ type TargetSpec = 'host' | 'document' | 'window' | 'shadowRoot' | EventTarget | ((host: HTMLElement) => EventTarget);
3
3
  type ListenOpts = {
4
4
  target?: TargetSpec;
5
5
  options?: AddEventListenerOptions;
@@ -9,9 +9,9 @@ type OneOrMany<N extends EventName> = N | readonly N[];
9
9
  type EventFromInput<I extends OneOrMany<EventName>> = I extends readonly (infer K)[] ? K extends EventName ? DocumentEventMap[K] : never : I extends EventName ? DocumentEventMap[I] : never;
10
10
  export declare function Listen<I extends OneOrMany<EventName>>(type: I, opts?: ListenOpts): <This, Fn extends (this: This, ev: EventFromInput<I>, ...args: any[]) => any>(value: Fn, context: ClassMethodDecoratorContext<This, Fn>) => Fn;
11
11
  export declare function EventBindingsMixin<TBase extends Ctor<object>>(Base: TBase): (abstract new (...a: any[]) => {
12
- "__#2023@#ac"?: AbortController;
12
+ "__#2347@#ac"?: AbortController;
13
13
  connectedCallback(): void;
14
14
  disconnectedCallback(): void;
15
- "__#2023@#bindEventListeners"(): void;
15
+ "__#2347@#bindEventListeners"(): void;
16
16
  }) & TBase;
17
17
  export {};
@@ -26,14 +26,14 @@ type Constructor<T = object> = abstract new (...args: any[]) => T;
26
26
  * <my-element debug></my-element> // enables debug logging
27
27
  */
28
28
  export declare function LoggingMixin<TBase extends Constructor<object>>(Base: TBase): (abstract new (...args: any[]) => {
29
- "__#2024@#debugCached": boolean | null;
30
- "__#2024@#myElementId": number;
29
+ "__#2348@#debugCached": boolean | null;
30
+ "__#2348@#myElementId": number;
31
31
  /**
32
32
  * Clears the cached debug flag so the attribute will be checked again
33
33
  * on the next log/warn/error call.
34
34
  */
35
35
  invalidateDebugCache(): void;
36
- "__#2024@#myLoggerInstance": Logger | null;
36
+ "__#2348@#myLoggerInstance": Logger | null;
37
37
  readonly _debug: boolean;
38
38
  getLogger(instanceId?: string): Logger;
39
39
  log(...args: any[]): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trunkjs/browser-utils",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "main": "./index.js",
5
5
  "dependencies": {},
6
6
  "type": "module",