@bquery/bquery 1.0.2 → 1.1.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.
- package/README.md +61 -7
- package/dist/component/index.d.ts +8 -0
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component.es.mjs +80 -53
- package/dist/component.es.mjs.map +1 -1
- package/dist/core/collection.d.ts +46 -0
- package/dist/core/collection.d.ts.map +1 -1
- package/dist/core/element.d.ts +124 -22
- package/dist/core/element.d.ts.map +1 -1
- package/dist/core/utils.d.ts +13 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core.es.mjs +298 -55
- package/dist/core.es.mjs.map +1 -1
- package/dist/full.d.ts +2 -2
- package/dist/full.d.ts.map +1 -1
- package/dist/full.es.mjs +38 -33
- package/dist/full.iife.js +1 -1
- package/dist/full.iife.js.map +1 -1
- package/dist/full.umd.js +1 -1
- package/dist/full.umd.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.es.mjs +38 -33
- package/dist/reactive/index.d.ts +2 -2
- package/dist/reactive/index.d.ts.map +1 -1
- package/dist/reactive/signal.d.ts +107 -0
- package/dist/reactive/signal.d.ts.map +1 -1
- package/dist/reactive.es.mjs +92 -55
- package/dist/reactive.es.mjs.map +1 -1
- package/dist/security/sanitize.d.ts.map +1 -1
- package/dist/security.es.mjs +136 -66
- package/dist/security.es.mjs.map +1 -1
- package/package.json +120 -120
- package/src/component/index.ts +414 -360
- package/src/core/collection.ts +454 -339
- package/src/core/element.ts +740 -493
- package/src/core/utils.ts +444 -425
- package/src/full.ts +106 -101
- package/src/index.ts +27 -27
- package/src/reactive/index.ts +22 -9
- package/src/reactive/signal.ts +506 -347
- package/src/security/sanitize.ts +553 -446
package/dist/core.es.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { sanitize as
|
|
2
|
-
const
|
|
1
|
+
import { sanitize as f } from "./security.es.mjs";
|
|
2
|
+
const p = (r) => Array.isArray(r) ? r : [r], o = (r, e) => {
|
|
3
3
|
for (const t of r)
|
|
4
4
|
e(t);
|
|
5
5
|
};
|
|
6
|
-
class
|
|
6
|
+
class a {
|
|
7
7
|
/**
|
|
8
8
|
* Creates a new BQueryElement wrapper.
|
|
9
9
|
* @param element - The DOM element to wrap
|
|
10
10
|
*/
|
|
11
11
|
constructor(e) {
|
|
12
|
-
this.element = e;
|
|
12
|
+
this.element = e, this.delegatedHandlers = /* @__PURE__ */ new Map();
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Exposes the raw DOM element when direct access is needed.
|
|
@@ -47,7 +47,7 @@ class o {
|
|
|
47
47
|
}
|
|
48
48
|
/** Read or write data attributes in camelCase. */
|
|
49
49
|
data(e, t) {
|
|
50
|
-
const n = e.replace(/[A-Z]/g, (
|
|
50
|
+
const n = e.replace(/[A-Z]/g, (s) => `-${s.toLowerCase()}`);
|
|
51
51
|
return t === void 0 ? this.element.getAttribute(`data-${n}`) ?? "" : (this.element.setAttribute(`data-${n}`, t), this);
|
|
52
52
|
}
|
|
53
53
|
/** Get or set text content. */
|
|
@@ -68,7 +68,7 @@ class o {
|
|
|
68
68
|
* ```
|
|
69
69
|
*/
|
|
70
70
|
html(e) {
|
|
71
|
-
return this.element.innerHTML =
|
|
71
|
+
return this.element.innerHTML = f(e), this;
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Sets HTML content without sanitization.
|
|
@@ -101,8 +101,8 @@ class o {
|
|
|
101
101
|
css(e, t) {
|
|
102
102
|
if (typeof e == "string")
|
|
103
103
|
return t !== void 0 && this.element.style.setProperty(e, t), this;
|
|
104
|
-
for (const [n,
|
|
105
|
-
this.element.style.setProperty(n,
|
|
104
|
+
for (const [n, s] of Object.entries(e))
|
|
105
|
+
this.element.style.setProperty(n, s);
|
|
106
106
|
return this;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
@@ -141,6 +141,74 @@ class o {
|
|
|
141
141
|
after(e) {
|
|
142
142
|
return this.insertContent(e, "afterend"), this;
|
|
143
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Wraps the element with the specified wrapper element or tag.
|
|
146
|
+
*
|
|
147
|
+
* @param wrapper - Tag name string or Element to wrap with
|
|
148
|
+
* @returns The instance for method chaining
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* $('#content').wrap('div'); // Wraps with <div>
|
|
153
|
+
* $('#content').wrap(document.createElement('section'));
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
wrap(e) {
|
|
157
|
+
const t = typeof e == "string" ? document.createElement(e) : e;
|
|
158
|
+
return this.element.parentNode?.insertBefore(t, this.element), t.appendChild(this.element), this;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Removes the parent element, keeping this element in its place.
|
|
162
|
+
* Essentially the opposite of wrap().
|
|
163
|
+
*
|
|
164
|
+
* @returns The instance for method chaining
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* // Before: <div><span id="text">Hello</span></div>
|
|
169
|
+
* $('#text').unwrap();
|
|
170
|
+
* // After: <span id="text">Hello</span>
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
unwrap() {
|
|
174
|
+
const e = this.element.parentElement;
|
|
175
|
+
return e && e.parentNode && (e.parentNode.insertBefore(this.element, e), e.remove()), this;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Replaces this element with new content.
|
|
179
|
+
*
|
|
180
|
+
* @param content - HTML string (sanitized) or Element to replace with
|
|
181
|
+
* @returns A new BQueryElement wrapping the replacement element
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* const newEl = $('#old').replaceWith('<div id="new">Replaced</div>');
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
replaceWith(e) {
|
|
189
|
+
let t;
|
|
190
|
+
if (typeof e == "string") {
|
|
191
|
+
const n = document.createElement("template");
|
|
192
|
+
n.innerHTML = f(e), t = n.content.firstElementChild ?? document.createElement("div");
|
|
193
|
+
} else
|
|
194
|
+
t = e;
|
|
195
|
+
return this.element.replaceWith(t), new a(t);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Scrolls the element into view with configurable behavior.
|
|
199
|
+
*
|
|
200
|
+
* @param options - ScrollIntoView options or boolean for legacy behavior
|
|
201
|
+
* @returns The instance for method chaining
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* $('#section').scrollTo(); // Smooth scroll
|
|
206
|
+
* $('#section').scrollTo({ behavior: 'instant', block: 'start' });
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
scrollTo(e = { behavior: "smooth" }) {
|
|
210
|
+
return this.element.scrollIntoView(e), this;
|
|
211
|
+
}
|
|
144
212
|
/**
|
|
145
213
|
* Removes the element from the DOM.
|
|
146
214
|
*
|
|
@@ -164,7 +232,7 @@ class o {
|
|
|
164
232
|
* @returns A new BQueryElement wrapping the cloned element
|
|
165
233
|
*/
|
|
166
234
|
clone(e = !0) {
|
|
167
|
-
return new
|
|
235
|
+
return new a(this.element.cloneNode(e));
|
|
168
236
|
}
|
|
169
237
|
/**
|
|
170
238
|
* Finds all descendant elements matching the selector.
|
|
@@ -274,6 +342,59 @@ class o {
|
|
|
274
342
|
trigger(e, t) {
|
|
275
343
|
return this.element.dispatchEvent(new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 })), this;
|
|
276
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Adds a delegated event listener that only triggers for matching descendants.
|
|
347
|
+
* More efficient than adding listeners to many elements individually.
|
|
348
|
+
*
|
|
349
|
+
* Use `undelegate()` to remove the listener later.
|
|
350
|
+
*
|
|
351
|
+
* @param event - Event type to listen for
|
|
352
|
+
* @param selector - CSS selector to match against event targets
|
|
353
|
+
* @param handler - Event handler function, receives the matched element as context
|
|
354
|
+
* @returns The instance for method chaining
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```ts
|
|
358
|
+
* // Instead of adding listeners to each button:
|
|
359
|
+
* const handler = (e, target) => console.log('Clicked:', target.textContent);
|
|
360
|
+
* $('#list').delegate('click', '.item', handler);
|
|
361
|
+
*
|
|
362
|
+
* // Later, remove the delegated listener:
|
|
363
|
+
* $('#list').undelegate('click', '.item', handler);
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
delegate(e, t, n) {
|
|
367
|
+
const s = `${e}:${t}`, i = (l) => {
|
|
368
|
+
const h = l.target.closest(t);
|
|
369
|
+
h && this.element.contains(h) && n(l, h);
|
|
370
|
+
};
|
|
371
|
+
return this.delegatedHandlers.has(s) || this.delegatedHandlers.set(s, /* @__PURE__ */ new Map()), this.delegatedHandlers.get(s).set(n, i), this.element.addEventListener(e, i), this;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Removes a delegated event listener previously added with `delegate()`.
|
|
375
|
+
*
|
|
376
|
+
* @param event - Event type that was registered
|
|
377
|
+
* @param selector - CSS selector that was used
|
|
378
|
+
* @param handler - The original handler function passed to delegate()
|
|
379
|
+
* @returns The instance for method chaining
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* const handler = (e, target) => console.log('Clicked:', target.textContent);
|
|
384
|
+
* $('#list').delegate('click', '.item', handler);
|
|
385
|
+
*
|
|
386
|
+
* // Remove the delegated listener:
|
|
387
|
+
* $('#list').undelegate('click', '.item', handler);
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
undelegate(e, t, n) {
|
|
391
|
+
const s = `${e}:${t}`, i = this.delegatedHandlers.get(s);
|
|
392
|
+
if (i) {
|
|
393
|
+
const l = i.get(n);
|
|
394
|
+
l && (this.element.removeEventListener(e, l), i.delete(n), i.size === 0 && this.delegatedHandlers.delete(s));
|
|
395
|
+
}
|
|
396
|
+
return this;
|
|
397
|
+
}
|
|
277
398
|
/**
|
|
278
399
|
* Checks if the element matches a CSS selector.
|
|
279
400
|
*
|
|
@@ -345,6 +466,53 @@ class o {
|
|
|
345
466
|
const t = this.element;
|
|
346
467
|
return e === void 0 ? t.value ?? "" : (t.value = e, this);
|
|
347
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* Serializes form data to a plain object.
|
|
471
|
+
* Only works on form elements; returns empty object for non-forms.
|
|
472
|
+
*
|
|
473
|
+
* @returns Object with form field names as keys and values
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```ts
|
|
477
|
+
* // For a form with <input name="email" value="test@example.com">
|
|
478
|
+
* const data = $('#myForm').serialize();
|
|
479
|
+
* // { email: 'test@example.com' }
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
serialize() {
|
|
483
|
+
const e = this.element;
|
|
484
|
+
if (e.tagName.toLowerCase() !== "form")
|
|
485
|
+
return {};
|
|
486
|
+
const t = {}, n = new FormData(e);
|
|
487
|
+
for (const [s, i] of n.entries())
|
|
488
|
+
if (typeof i == "string")
|
|
489
|
+
if (s in t) {
|
|
490
|
+
const l = t[s];
|
|
491
|
+
Array.isArray(l) ? l.push(i) : t[s] = [l, i];
|
|
492
|
+
} else
|
|
493
|
+
t[s] = i;
|
|
494
|
+
return t;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Serializes form data to a URL-encoded query string.
|
|
498
|
+
*
|
|
499
|
+
* @returns URL-encoded string suitable for form submission
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```ts
|
|
503
|
+
* const queryString = $('#myForm').serializeString();
|
|
504
|
+
* // 'email=test%40example.com&name=John'
|
|
505
|
+
* ```
|
|
506
|
+
*/
|
|
507
|
+
serializeString() {
|
|
508
|
+
const e = this.element;
|
|
509
|
+
if (e.tagName.toLowerCase() !== "form")
|
|
510
|
+
return "";
|
|
511
|
+
const t = new FormData(e), n = new URLSearchParams();
|
|
512
|
+
for (const [s, i] of t.entries())
|
|
513
|
+
typeof i == "string" && n.append(s, i);
|
|
514
|
+
return n.toString();
|
|
515
|
+
}
|
|
348
516
|
/**
|
|
349
517
|
* Gets the bounding client rectangle of the element.
|
|
350
518
|
*
|
|
@@ -373,22 +541,22 @@ class o {
|
|
|
373
541
|
*/
|
|
374
542
|
insertContent(e, t) {
|
|
375
543
|
if (typeof e == "string") {
|
|
376
|
-
this.element.insertAdjacentHTML(t,
|
|
544
|
+
this.element.insertAdjacentHTML(t, f(e));
|
|
377
545
|
return;
|
|
378
546
|
}
|
|
379
|
-
const n =
|
|
380
|
-
|
|
381
|
-
this.element.insertAdjacentElement(t,
|
|
547
|
+
const n = p(e);
|
|
548
|
+
o(n, (s) => {
|
|
549
|
+
this.element.insertAdjacentElement(t, s);
|
|
382
550
|
});
|
|
383
551
|
}
|
|
384
552
|
}
|
|
385
|
-
class
|
|
553
|
+
class m {
|
|
386
554
|
/**
|
|
387
555
|
* Creates a new collection wrapper.
|
|
388
556
|
* @param elements - Array of DOM elements to wrap
|
|
389
557
|
*/
|
|
390
558
|
constructor(e) {
|
|
391
|
-
this.elements = e;
|
|
559
|
+
this.elements = e, this.delegatedHandlers = /* @__PURE__ */ new WeakMap();
|
|
392
560
|
}
|
|
393
561
|
/**
|
|
394
562
|
* Gets the number of elements in the collection.
|
|
@@ -411,7 +579,7 @@ class l {
|
|
|
411
579
|
*/
|
|
412
580
|
eq(e) {
|
|
413
581
|
const t = this.elements[e];
|
|
414
|
-
return t ? new
|
|
582
|
+
return t ? new a(t) : void 0;
|
|
415
583
|
}
|
|
416
584
|
/**
|
|
417
585
|
* Gets the first element as a BQueryElement wrapper.
|
|
@@ -437,7 +605,7 @@ class l {
|
|
|
437
605
|
*/
|
|
438
606
|
each(e) {
|
|
439
607
|
return this.elements.forEach((t, n) => {
|
|
440
|
-
e(new
|
|
608
|
+
e(new a(t), n);
|
|
441
609
|
}), this;
|
|
442
610
|
}
|
|
443
611
|
/**
|
|
@@ -456,7 +624,7 @@ class l {
|
|
|
456
624
|
* @returns New BQueryCollection with matching elements
|
|
457
625
|
*/
|
|
458
626
|
filter(e) {
|
|
459
|
-
return new
|
|
627
|
+
return new m(this.elements.filter(e));
|
|
460
628
|
}
|
|
461
629
|
/**
|
|
462
630
|
* Reduces the collection to a single value.
|
|
@@ -474,19 +642,19 @@ class l {
|
|
|
474
642
|
* @returns Array of BQueryElement instances
|
|
475
643
|
*/
|
|
476
644
|
toArray() {
|
|
477
|
-
return this.elements.map((e) => new
|
|
645
|
+
return this.elements.map((e) => new a(e));
|
|
478
646
|
}
|
|
479
647
|
/** Add one or more classes to all elements. */
|
|
480
648
|
addClass(...e) {
|
|
481
|
-
return
|
|
649
|
+
return o(this.elements, (t) => t.classList.add(...e)), this;
|
|
482
650
|
}
|
|
483
651
|
/** Remove one or more classes from all elements. */
|
|
484
652
|
removeClass(...e) {
|
|
485
|
-
return
|
|
653
|
+
return o(this.elements, (t) => t.classList.remove(...e)), this;
|
|
486
654
|
}
|
|
487
655
|
/** Toggle a class on all elements. */
|
|
488
656
|
toggleClass(e, t) {
|
|
489
|
-
return
|
|
657
|
+
return o(this.elements, (n) => n.classList.toggle(e, t)), this;
|
|
490
658
|
}
|
|
491
659
|
/**
|
|
492
660
|
* Sets an attribute on all elements or gets from first.
|
|
@@ -496,7 +664,7 @@ class l {
|
|
|
496
664
|
* @returns Attribute value when getting, instance when setting
|
|
497
665
|
*/
|
|
498
666
|
attr(e, t) {
|
|
499
|
-
return t === void 0 ? this.first()?.getAttribute(e) ?? "" : (
|
|
667
|
+
return t === void 0 ? this.first()?.getAttribute(e) ?? "" : (o(this.elements, (n) => n.setAttribute(e, t)), this);
|
|
500
668
|
}
|
|
501
669
|
/**
|
|
502
670
|
* Removes an attribute from all elements.
|
|
@@ -505,7 +673,7 @@ class l {
|
|
|
505
673
|
* @returns The instance for method chaining
|
|
506
674
|
*/
|
|
507
675
|
removeAttr(e) {
|
|
508
|
-
return
|
|
676
|
+
return o(this.elements, (t) => t.removeAttribute(e)), this;
|
|
509
677
|
}
|
|
510
678
|
/**
|
|
511
679
|
* Sets text content on all elements or gets from first.
|
|
@@ -514,7 +682,7 @@ class l {
|
|
|
514
682
|
* @returns Text content when getting, instance when setting
|
|
515
683
|
*/
|
|
516
684
|
text(e) {
|
|
517
|
-
return e === void 0 ? this.first()?.textContent ?? "" : (
|
|
685
|
+
return e === void 0 ? this.first()?.textContent ?? "" : (o(this.elements, (t) => {
|
|
518
686
|
t.textContent = e;
|
|
519
687
|
}), this);
|
|
520
688
|
}
|
|
@@ -527,8 +695,8 @@ class l {
|
|
|
527
695
|
html(e) {
|
|
528
696
|
if (e === void 0)
|
|
529
697
|
return this.first()?.innerHTML ?? "";
|
|
530
|
-
const t =
|
|
531
|
-
return
|
|
698
|
+
const t = f(e);
|
|
699
|
+
return o(this.elements, (n) => {
|
|
532
700
|
n.innerHTML = t;
|
|
533
701
|
}), this;
|
|
534
702
|
}
|
|
@@ -540,7 +708,7 @@ class l {
|
|
|
540
708
|
* @warning Bypasses XSS protection
|
|
541
709
|
*/
|
|
542
710
|
htmlUnsafe(e) {
|
|
543
|
-
return
|
|
711
|
+
return o(this.elements, (t) => {
|
|
544
712
|
t.innerHTML = e;
|
|
545
713
|
}), this;
|
|
546
714
|
}
|
|
@@ -552,11 +720,11 @@ class l {
|
|
|
552
720
|
* @returns The instance for method chaining
|
|
553
721
|
*/
|
|
554
722
|
css(e, t) {
|
|
555
|
-
return typeof e == "string" ? (t !== void 0 &&
|
|
723
|
+
return typeof e == "string" ? (t !== void 0 && o(this.elements, (n) => {
|
|
556
724
|
n.style.setProperty(e, t);
|
|
557
|
-
}), this) : (
|
|
558
|
-
for (const [
|
|
559
|
-
n.style.setProperty(
|
|
725
|
+
}), this) : (o(this.elements, (n) => {
|
|
726
|
+
for (const [s, i] of Object.entries(e))
|
|
727
|
+
n.style.setProperty(s, i);
|
|
560
728
|
}), this);
|
|
561
729
|
}
|
|
562
730
|
/**
|
|
@@ -566,7 +734,7 @@ class l {
|
|
|
566
734
|
* @returns The instance for method chaining
|
|
567
735
|
*/
|
|
568
736
|
show(e = "") {
|
|
569
|
-
return
|
|
737
|
+
return o(this.elements, (t) => {
|
|
570
738
|
t.removeAttribute("hidden"), t.style.display = e;
|
|
571
739
|
}), this;
|
|
572
740
|
}
|
|
@@ -576,7 +744,7 @@ class l {
|
|
|
576
744
|
* @returns The instance for method chaining
|
|
577
745
|
*/
|
|
578
746
|
hide() {
|
|
579
|
-
return
|
|
747
|
+
return o(this.elements, (e) => {
|
|
580
748
|
e.style.display = "none";
|
|
581
749
|
}), this;
|
|
582
750
|
}
|
|
@@ -588,7 +756,7 @@ class l {
|
|
|
588
756
|
* @returns The instance for method chaining
|
|
589
757
|
*/
|
|
590
758
|
on(e, t) {
|
|
591
|
-
return
|
|
759
|
+
return o(this.elements, (n) => n.addEventListener(e, t)), this;
|
|
592
760
|
}
|
|
593
761
|
/**
|
|
594
762
|
* Adds a one-time event listener to all elements.
|
|
@@ -598,7 +766,7 @@ class l {
|
|
|
598
766
|
* @returns The instance for method chaining
|
|
599
767
|
*/
|
|
600
768
|
once(e, t) {
|
|
601
|
-
return
|
|
769
|
+
return o(this.elements, (n) => n.addEventListener(e, t, { once: !0 })), this;
|
|
602
770
|
}
|
|
603
771
|
/**
|
|
604
772
|
* Removes an event listener from all elements.
|
|
@@ -608,7 +776,7 @@ class l {
|
|
|
608
776
|
* @returns The instance for method chaining
|
|
609
777
|
*/
|
|
610
778
|
off(e, t) {
|
|
611
|
-
return
|
|
779
|
+
return o(this.elements, (n) => n.removeEventListener(e, t)), this;
|
|
612
780
|
}
|
|
613
781
|
/**
|
|
614
782
|
* Triggers a custom event on all elements.
|
|
@@ -618,17 +786,77 @@ class l {
|
|
|
618
786
|
* @returns The instance for method chaining
|
|
619
787
|
*/
|
|
620
788
|
trigger(e, t) {
|
|
621
|
-
return
|
|
789
|
+
return o(this.elements, (n) => {
|
|
622
790
|
n.dispatchEvent(new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 }));
|
|
623
791
|
}), this;
|
|
624
792
|
}
|
|
793
|
+
/**
|
|
794
|
+
* Adds a delegated event listener to all elements.
|
|
795
|
+
* Events are delegated to matching descendants.
|
|
796
|
+
*
|
|
797
|
+
* Use `undelegate()` to remove the listener later.
|
|
798
|
+
*
|
|
799
|
+
* @param event - Event type to listen for
|
|
800
|
+
* @param selector - CSS selector to match against event targets
|
|
801
|
+
* @param handler - Event handler function
|
|
802
|
+
* @returns The instance for method chaining
|
|
803
|
+
*
|
|
804
|
+
* @example
|
|
805
|
+
* ```ts
|
|
806
|
+
* const handler = (e, target) => console.log('Clicked:', target.textContent);
|
|
807
|
+
* $$('.container').delegate('click', '.item', handler);
|
|
808
|
+
*
|
|
809
|
+
* // Later, remove the delegated listener:
|
|
810
|
+
* $$('.container').undelegate('click', '.item', handler);
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
delegate(e, t, n) {
|
|
814
|
+
const s = `${e}:${t}`;
|
|
815
|
+
return o(this.elements, (i) => {
|
|
816
|
+
const l = (u) => {
|
|
817
|
+
const d = u.target.closest(t);
|
|
818
|
+
d && i.contains(d) && n(u, d);
|
|
819
|
+
};
|
|
820
|
+
this.delegatedHandlers.has(i) || this.delegatedHandlers.set(i, /* @__PURE__ */ new Map());
|
|
821
|
+
const h = this.delegatedHandlers.get(i);
|
|
822
|
+
h.has(s) || h.set(s, /* @__PURE__ */ new Map()), h.get(s).set(n, l), i.addEventListener(e, l);
|
|
823
|
+
}), this;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Removes a delegated event listener previously added with `delegate()`.
|
|
827
|
+
*
|
|
828
|
+
* @param event - Event type that was registered
|
|
829
|
+
* @param selector - CSS selector that was used
|
|
830
|
+
* @param handler - The original handler function passed to delegate()
|
|
831
|
+
* @returns The instance for method chaining
|
|
832
|
+
*
|
|
833
|
+
* @example
|
|
834
|
+
* ```ts
|
|
835
|
+
* const handler = (e, target) => console.log('Clicked:', target.textContent);
|
|
836
|
+
* $$('.container').delegate('click', '.item', handler);
|
|
837
|
+
*
|
|
838
|
+
* // Remove the delegated listener:
|
|
839
|
+
* $$('.container').undelegate('click', '.item', handler);
|
|
840
|
+
* ```
|
|
841
|
+
*/
|
|
842
|
+
undelegate(e, t, n) {
|
|
843
|
+
const s = `${e}:${t}`;
|
|
844
|
+
return o(this.elements, (i) => {
|
|
845
|
+
const l = this.delegatedHandlers.get(i);
|
|
846
|
+
if (!l) return;
|
|
847
|
+
const h = l.get(s);
|
|
848
|
+
if (!h) return;
|
|
849
|
+
const u = h.get(n);
|
|
850
|
+
u && (i.removeEventListener(e, u), h.delete(n), h.size === 0 && l.delete(s), l.size === 0 && this.delegatedHandlers.delete(i));
|
|
851
|
+
}), this;
|
|
852
|
+
}
|
|
625
853
|
/**
|
|
626
854
|
* Removes all elements from the DOM.
|
|
627
855
|
*
|
|
628
856
|
* @returns The instance for method chaining
|
|
629
857
|
*/
|
|
630
858
|
remove() {
|
|
631
|
-
return
|
|
859
|
+
return o(this.elements, (e) => e.remove()), this;
|
|
632
860
|
}
|
|
633
861
|
/**
|
|
634
862
|
* Clears all child nodes from all elements.
|
|
@@ -636,19 +864,19 @@ class l {
|
|
|
636
864
|
* @returns The instance for method chaining
|
|
637
865
|
*/
|
|
638
866
|
empty() {
|
|
639
|
-
return
|
|
867
|
+
return o(this.elements, (e) => {
|
|
640
868
|
e.innerHTML = "";
|
|
641
869
|
}), this;
|
|
642
870
|
}
|
|
643
871
|
}
|
|
644
|
-
const
|
|
872
|
+
const y = (r) => {
|
|
645
873
|
if (typeof r != "string")
|
|
646
|
-
return new
|
|
874
|
+
return new a(r);
|
|
647
875
|
const e = document.querySelector(r);
|
|
648
876
|
if (!e)
|
|
649
877
|
throw new Error(`bQuery: element not found for selector "${r}"`);
|
|
650
|
-
return new
|
|
651
|
-
},
|
|
878
|
+
return new a(e);
|
|
879
|
+
}, b = (r) => Array.isArray(r) ? new m(r) : r instanceof NodeList ? new m(Array.from(r)) : new m(Array.from(document.querySelectorAll(r))), c = {
|
|
652
880
|
/**
|
|
653
881
|
* Creates a deep clone using structuredClone if available, otherwise fallback to JSON.
|
|
654
882
|
*
|
|
@@ -684,17 +912,32 @@ const f = (r) => {
|
|
|
684
912
|
* );
|
|
685
913
|
* // Result: { a: 1, b: 2, nested: { x: 1, y: 2 } }
|
|
686
914
|
* ```
|
|
915
|
+
*
|
|
916
|
+
* @security This method is protected against prototype pollution attacks.
|
|
917
|
+
* Keys like `__proto__`, `constructor`, and `prototype` are ignored.
|
|
687
918
|
*/
|
|
688
919
|
merge(...r) {
|
|
689
920
|
const e = {};
|
|
690
921
|
for (const t of r)
|
|
691
|
-
for (const [n,
|
|
692
|
-
|
|
922
|
+
for (const [n, s] of Object.entries(t))
|
|
923
|
+
c.isPrototypePollutionKey(n) || (c.isPlainObject(s) && c.isPlainObject(e[n]) ? e[n] = c.merge(
|
|
693
924
|
e[n],
|
|
694
|
-
|
|
695
|
-
) : e[n] =
|
|
925
|
+
s
|
|
926
|
+
) : e[n] = s);
|
|
696
927
|
return e;
|
|
697
928
|
},
|
|
929
|
+
/**
|
|
930
|
+
* Checks if a key could cause prototype pollution.
|
|
931
|
+
* These keys are dangerous when used in object merging operations.
|
|
932
|
+
*
|
|
933
|
+
* @param key - The key to check
|
|
934
|
+
* @returns True if the key is a prototype pollution vector
|
|
935
|
+
*
|
|
936
|
+
* @internal
|
|
937
|
+
*/
|
|
938
|
+
isPrototypePollutionKey(r) {
|
|
939
|
+
return r === "__proto__" || r === "constructor" || r === "prototype";
|
|
940
|
+
},
|
|
698
941
|
/**
|
|
699
942
|
* Creates a debounced function that delays execution until after
|
|
700
943
|
* the specified delay has elapsed since the last call.
|
|
@@ -741,8 +984,8 @@ const f = (r) => {
|
|
|
741
984
|
throttle(r, e) {
|
|
742
985
|
let t = 0;
|
|
743
986
|
return (...n) => {
|
|
744
|
-
const
|
|
745
|
-
|
|
987
|
+
const s = Date.now();
|
|
988
|
+
s - t >= e && (t = s, r(...n));
|
|
746
989
|
};
|
|
747
990
|
},
|
|
748
991
|
/**
|
|
@@ -1006,10 +1249,10 @@ const f = (r) => {
|
|
|
1006
1249
|
}
|
|
1007
1250
|
};
|
|
1008
1251
|
export {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1252
|
+
y as $,
|
|
1253
|
+
b as $$,
|
|
1254
|
+
m as BQueryCollection,
|
|
1255
|
+
a as BQueryElement,
|
|
1256
|
+
c as utils
|
|
1014
1257
|
};
|
|
1015
1258
|
//# sourceMappingURL=core.es.mjs.map
|