@trunkjs/browser-utils 1.0.15 → 1.0.16

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,7 @@
1
+ ## 1.0.16 (2025-08-27)
2
+
3
+ This was a version bump only for browser-utils to align it with other projects, there were no code changes.
4
+
1
5
  ## 1.0.15 (2025-08-24)
2
6
 
3
7
  This was a version bump only for browser-utils to align it with other projects, there were no code changes.
package/README.md CHANGED
@@ -9,6 +9,8 @@ Exports:
9
9
  - waitFor, waitForDomContentLoaded, waitForLoad, sleep, waitForAnimationEnd: Promise-based event and timing helpers
10
10
  - LoggingMixin: Lightweight logging mixin for Custom Elements
11
11
 
12
+ - [Event Bindings for WebComponents](./docs/README_EventHandling.md)
13
+
12
14
  ## Installation
13
15
 
14
16
  Within this monorepo, the package is consumed via path aliases. If you publish or consume it externally, import from the package name:
package/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
+ export * from './lib/breakpoints';
1
2
  export * from './lib/create-element';
2
3
  export * from './lib/Debouncer';
3
4
  export * from './lib/get-error-location';
4
5
  export * from './lib/Logger';
5
6
  export * from './lib/Stopwatch';
6
7
  export * from './lib/wait-for';
8
+ export * from './mixins/EventBindingsMixin';
7
9
  export * from './mixins/LoggingMixin';
package/index.js CHANGED
@@ -1,96 +1,119 @@
1
- var g = Object.defineProperty;
2
- var c = (t) => {
3
- throw TypeError(t);
1
+ var D = Object.defineProperty;
2
+ var L = (e) => {
3
+ throw TypeError(e);
4
4
  };
5
- var f = (t, e, n) => e in t ? g(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
6
- var l = (t, e, n) => f(t, typeof e != "symbol" ? e + "" : e, n), d = (t, e, n) => e.has(t) || c("Cannot " + n);
7
- var r = (t, e, n) => (d(t, e, "read from private field"), n ? n.call(t) : e.get(t)), u = (t, e, n) => e.has(t) ? c("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, n), m = (t, e, n, i) => (d(t, e, "write to private field"), i ? i.call(t, n) : e.set(t, n), n);
8
- function E(t, e = {}, n = []) {
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 = [
9
+ { name: "xs", minWidth: 0 },
10
+ { name: "sm", minWidth: 576 },
11
+ { name: "md", minWidth: 768 },
12
+ { name: "lg", minWidth: 992 },
13
+ { name: "xl", minWidth: 1200 },
14
+ { name: "xxl", minWidth: 1400 }
15
+ ], y = m.reduce(
16
+ (e, t) => (e[t.name] = t.minWidth, e),
17
+ {}
18
+ );
19
+ function B(e) {
20
+ if (!(e in y))
21
+ throw new Error(`Unknown breakpoint: ${e}`);
22
+ return y[e];
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;
29
+ return "xs";
30
+ }
31
+ function _(e, t = {}, n = []) {
9
32
  Array.isArray(n) || (n = [n]);
10
- const i = document.createElement(t);
11
- for (const s in e)
12
- e[s] !== null && e[s] !== void 0 && i.setAttribute(s, e[s] !== !0 ? e[s] : "");
13
- for (const s of n)
14
- i.append(typeof s == "string" ? document.createTextNode(s) : s);
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] : "");
36
+ for (const r of n)
37
+ i.append(typeof r == "string" ? document.createTextNode(r) : r);
15
38
  return i;
16
39
  }
17
- class y {
40
+ class N {
18
41
  /**
19
42
  *
20
43
  * @param delay Debounce delay in milliseconds
21
44
  * @param max_delay Maximum delay in milliseconds, if false then no maximum delay is applied
22
45
  */
23
- constructor(e, n = !1) {
24
- l(this, "timeout", null);
25
- l(this, "startTimeWithMs", 0);
26
- this.delay = e, this.max_delay = n;
46
+ constructor(t, n = !1) {
47
+ u(this, "timeout", null);
48
+ u(this, "startTimeWithMs", 0);
49
+ this.delay = t, this.max_delay = n;
27
50
  }
28
51
  async wait() {
29
- 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) => {
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) => {
30
53
  this.timeout = setTimeout(() => {
31
- this.startTimeWithMs = 0, e(!0);
54
+ this.startTimeWithMs = 0, t(!0);
32
55
  }, this.delay);
33
56
  });
34
57
  }
35
- debounce(e) {
58
+ debounce(t) {
36
59
  this.timeout && clearTimeout(this.timeout), this.timeout = setTimeout(() => {
37
- e();
60
+ t();
38
61
  }, this.delay);
39
62
  }
40
63
  }
41
- function I(t) {
42
- if (typeof t.lineNumber == "number")
64
+ function F(e) {
65
+ if (typeof e.lineNumber == "number")
43
66
  return {
44
- file: t.fileName || t.sourceURL,
45
- line: t.lineNumber,
46
- column: t.columnNumber ?? void 0
67
+ file: e.fileName || e.sourceURL,
68
+ line: e.lineNumber,
69
+ column: e.columnNumber ?? void 0
47
70
  };
48
- if (typeof t.line == "number")
71
+ if (typeof e.line == "number")
49
72
  return {
50
- file: t.sourceURL,
51
- line: t.line,
52
- column: t.column
73
+ file: e.sourceURL,
74
+ line: e.line,
75
+ column: e.column
53
76
  };
54
- const n = String(t.stack || t.message || "").split(`
77
+ const n = String(e.stack || e.message || "").split(`
55
78
  `), i = /(.*?)(?:\(|@)?(.*?):(\d+):(\d+)\)?$/;
56
- for (const s of n) {
57
- const a = s.match(i);
58
- if (a)
59
- return { file: a[2], line: +a[3], column: +a[4] };
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] };
60
83
  }
61
- return { file: t.fileName || t.sourceURL };
84
+ return { file: e.fileName || e.sourceURL };
62
85
  }
63
- class w {
64
- constructor(e, n, i = "main") {
65
- this._debug = e, this.myElementId = n, this.instanceId = i;
86
+ class k {
87
+ constructor(t, n, i = "main") {
88
+ this._debug = t, this.myElementId = n, this.instanceId = i;
66
89
  }
67
- log(...e) {
68
- this._debug && console.log(`[LOG][ID:${this.myElementId}:${this.instanceId}]`, ...e);
90
+ log(...t) {
91
+ this._debug && console.log(`[LOG][ID:${this.myElementId}:${this.instanceId}]`, ...t);
69
92
  }
70
- warn(...e) {
71
- console.warn(`[WARN][ID:${this.myElementId}:${this.instanceId}]`, ...e);
93
+ warn(...t) {
94
+ console.warn(`[WARN][ID:${this.myElementId}:${this.instanceId}]`, ...t);
72
95
  }
73
- error(...e) {
74
- console.error(`[ERROR][ID:${this.myElementId}:${this.instanceId}]`, ...e);
96
+ error(...t) {
97
+ console.error(`[ERROR][ID:${this.myElementId}:${this.instanceId}]`, ...t);
75
98
  }
76
- throwError(...e) {
77
- const n = `[ERROR][ID:${this.myElementId}:${this.instanceId}] ${e.join(" ")}`;
78
- throw this.error(...e), new Error(n);
99
+ throwError(...t) {
100
+ const n = `[ERROR][ID:${this.myElementId}:${this.instanceId}] ${t.join(" ")}`;
101
+ throw this.error(...t), new Error(n);
79
102
  }
80
103
  }
81
- class p {
82
- constructor(e, n = !0) {
83
- l(this, "label");
84
- l(this, "last");
85
- l(this, "startTime");
86
- l(this, "running", !1);
87
- l(this, "enabled");
88
- this.label = e, this.enabled = n, this.startTime = this.last = performance.now(), this.running = !0;
104
+ class O {
105
+ constructor(t, n = !0) {
106
+ u(this, "label");
107
+ u(this, "last");
108
+ u(this, "startTime");
109
+ u(this, "running", !1);
110
+ u(this, "enabled");
111
+ this.label = t, this.enabled = n, this.startTime = this.last = performance.now(), this.running = !0;
89
112
  }
90
- lap(e = "") {
113
+ lap(t = "") {
91
114
  if (!this.enabled) return;
92
115
  const n = performance.now(), i = (n - this.last) / 1e3;
93
- this.last = n, console.debug(`[${this.label}] ${e} +${i.toFixed(3)}s`);
116
+ this.last = n, console.debug(`[${this.label}] ${t} +${i.toFixed(3)}s`);
94
117
  }
95
118
  elapsed() {
96
119
  return performance.now() - this.startTime;
@@ -108,83 +131,141 @@ class p {
108
131
  return this.running;
109
132
  }
110
133
  }
111
- function T(t, e, n) {
112
- return new Promise((i, s) => {
113
- const a = (h) => {
114
- t.removeEventListener(e, a, n), i(h);
134
+ function U(e, t, n) {
135
+ return new Promise((i, r) => {
136
+ const o = (g) => {
137
+ e.removeEventListener(t, o, n), i(g);
115
138
  };
116
- t.addEventListener(e, a, n);
139
+ e.addEventListener(t, o, n);
117
140
  });
118
141
  }
119
- function $() {
120
- return document.readyState === "loading" ? new Promise((t) => {
121
- document.addEventListener("DOMContentLoaded", () => t());
142
+ function S() {
143
+ return document.readyState === "loading" ? new Promise((e) => {
144
+ document.addEventListener("DOMContentLoaded", () => e());
122
145
  }) : Promise.resolve();
123
146
  }
124
- function D() {
125
- return document.readyState === "complete" ? Promise.resolve() : new Promise((t) => {
126
- window.addEventListener("load", () => t());
147
+ function G() {
148
+ return document.readyState === "complete" ? Promise.resolve() : new Promise((e) => {
149
+ window.addEventListener("load", () => e());
127
150
  });
128
151
  }
129
- function v(t) {
130
- return new Promise((e) => setTimeout(e, t));
152
+ function j(e) {
153
+ return new Promise((t) => setTimeout(t, e));
131
154
  }
132
- function R(t) {
133
- return new Promise((e) => {
155
+ function q(e) {
156
+ return new Promise((t) => {
134
157
  const n = (i) => {
135
- t.removeEventListener("animationend", n), e(i);
158
+ e.removeEventListener("animationend", n), t(i);
136
159
  };
137
- t.addEventListener("animationend", n);
160
+ e.addEventListener("animationend", n);
138
161
  });
139
162
  }
140
- let b = 1;
141
- function x(t) {
142
- var n, i, s;
143
- class e extends t {
163
+ const f = Symbol("listenerDefs"), p = Symbol("withEventBindings");
164
+ function z(e, t) {
165
+ const n = Array.isArray(e) ? e : [e];
166
+ return function(i, r) {
167
+ if (r.kind !== "method") throw new Error("@Listen nur für Methoden");
168
+ return r.addInitializer(function() {
169
+ const o = this.constructor;
170
+ (o[f] || (o[f] = [])).push({
171
+ method: r.name,
172
+ events: n,
173
+ opts: t
174
+ });
175
+ }), function(...o) {
176
+ if (!this[p])
177
+ throw new Error("[EventBindings] @Listen - decorator requires EventBindingMixin.");
178
+ return i.apply(this, o);
179
+ };
180
+ };
181
+ }
182
+ function A(e, t) {
183
+ 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;
185
+ }
186
+ function H(e) {
187
+ var n, i, I;
188
+ class t extends e {
189
+ constructor(...s) {
190
+ super(...s);
191
+ l(this, i);
192
+ l(this, n);
193
+ this[p] = !0;
194
+ }
195
+ connectedCallback() {
196
+ var s;
197
+ (s = super.connectedCallback) == null || s.call(this), v(this, i, I).call(this);
198
+ }
199
+ disconnectedCallback() {
200
+ var s, c;
201
+ (s = a(this, n)) == null || s.abort(), (c = super.disconnectedCallback) == null || c.call(this);
202
+ }
203
+ }
204
+ 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 });
212
+ }
213
+ }, t;
214
+ }
215
+ let C = 1;
216
+ function V(e) {
217
+ var n, i, r;
218
+ class t extends e {
144
219
  constructor() {
145
220
  super(...arguments);
146
- u(this, n, null);
147
- u(this, i, b++);
148
- u(this, s, null);
221
+ l(this, n, null);
222
+ l(this, i, C++);
223
+ l(this, r, null);
149
224
  }
150
225
  /**
151
226
  * Clears the cached debug flag so the attribute will be checked again
152
227
  * on the next log/warn/error call.
153
228
  */
154
229
  invalidateDebugCache() {
155
- m(this, n, null);
230
+ d(this, n, null);
156
231
  }
157
232
  get _debug() {
158
- return r(this, n) !== null ? r(this, n) : (this instanceof HTMLElement && m(this, n, this.hasAttribute("debug") && !["false", "0", "off", "no"].includes(this.getAttribute("debug") || "")), r(this, n) === !0 && console.log(`[DEBUG][ID:${r(this, i)}] LoggingMixin: Debug mode is enabled for <${this.tagName}>`, this), r(this, n) ?? !1);
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);
159
234
  }
160
- getLogger(o = "main") {
161
- return r(this, s) || m(this, s, new w(this._debug, `${r(this, i)}`, o)), r(this, s);
235
+ getLogger(s = "main") {
236
+ return a(this, r) || d(this, r, new k(this._debug, `${a(this, i)}`, s)), a(this, r);
162
237
  }
163
- log(...o) {
164
- this.getLogger().log(...o);
238
+ log(...s) {
239
+ this.getLogger().log(...s);
165
240
  }
166
- warn(...o) {
167
- this.getLogger().warn(...o);
241
+ warn(...s) {
242
+ this.getLogger().warn(...s);
168
243
  }
169
- error(...o) {
170
- this.getLogger().error(...o);
244
+ error(...s) {
245
+ this.getLogger().error(...s);
171
246
  }
172
- throwError(...o) {
173
- return this.getLogger().throwError(...o);
247
+ throwError(...s) {
248
+ return this.getLogger().throwError(...s);
174
249
  }
175
250
  }
176
- return n = new WeakMap(), i = new WeakMap(), s = new WeakMap(), e;
251
+ return n = new WeakMap(), i = new WeakMap(), r = new WeakMap(), t;
177
252
  }
178
253
  export {
179
- y as Debouncer,
180
- w as Logger,
181
- x as LoggingMixin,
182
- p as Stopwatch,
183
- E as create_element,
184
- I as getErrorLocation,
185
- v as sleep,
186
- T as waitFor,
187
- R as waitForAnimationEnd,
188
- $ as waitForDomContentLoaded,
189
- D as waitForLoad
254
+ N as Debouncer,
255
+ H as EventBindingsMixin,
256
+ z as Listen,
257
+ k as Logger,
258
+ V as LoggingMixin,
259
+ O as Stopwatch,
260
+ y as breakpointMap,
261
+ m as breakpoints,
262
+ _ as create_element,
263
+ B as getBreakpointMinWidth,
264
+ P as getCurrentBreakpoint,
265
+ F as getErrorLocation,
266
+ j as sleep,
267
+ U as waitFor,
268
+ q as waitForAnimationEnd,
269
+ S as waitForDomContentLoaded,
270
+ G as waitForLoad
190
271
  };
@@ -0,0 +1,24 @@
1
+ export declare const breakpoints: readonly [{
2
+ readonly name: "xs";
3
+ readonly minWidth: 0;
4
+ }, {
5
+ readonly name: "sm";
6
+ readonly minWidth: 576;
7
+ }, {
8
+ readonly name: "md";
9
+ readonly minWidth: 768;
10
+ }, {
11
+ readonly name: "lg";
12
+ readonly minWidth: 992;
13
+ }, {
14
+ readonly name: "xl";
15
+ readonly minWidth: 1200;
16
+ }, {
17
+ readonly name: "xxl";
18
+ readonly minWidth: 1400;
19
+ }];
20
+ export declare const breakpointMap: {
21
+ [key: string]: number;
22
+ };
23
+ export declare function getBreakpointMinWidth(breakpoint: string): number;
24
+ export declare function getCurrentBreakpoint(width?: number): string;
@@ -0,0 +1,17 @@
1
+ type Ctor<T = object> = new (...args: any[]) => T;
2
+ type TargetSpec = 'host' | 'document' | 'window' | EventTarget | ((host: HTMLElement) => EventTarget);
3
+ type ListenOpts = {
4
+ target?: TargetSpec;
5
+ options?: AddEventListenerOptions;
6
+ };
7
+ type EventName = keyof DocumentEventMap;
8
+ type OneOrMany<N extends EventName> = N | readonly N[];
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
+ 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
+ export declare function EventBindingsMixin<TBase extends Ctor<object>>(Base: TBase): (abstract new (...a: any[]) => {
12
+ "__#2023@#ac"?: AbortController;
13
+ connectedCallback(): void;
14
+ disconnectedCallback(): void;
15
+ "__#2023@#bindEventListeners"(): void;
16
+ }) & TBase;
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
- "__#1729@#debugCached": boolean | null;
30
- "__#1729@#myElementId": number;
29
+ "__#2024@#debugCached": boolean | null;
30
+ "__#2024@#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
- "__#1729@#myLoggerInstance": Logger | null;
36
+ "__#2024@#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.15",
3
+ "version": "1.0.16",
4
4
  "main": "./index.js",
5
5
  "dependencies": {},
6
6
  "type": "module",