@webalternatif/js-core 1.6.3 → 1.6.5

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.
Files changed (61) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/Mouse.js +26 -15
  3. package/dist/cjs/Translator.js +7 -1
  4. package/dist/cjs/array.js +5 -35
  5. package/dist/cjs/dom.js +820 -209
  6. package/dist/cjs/eventDispatcher.js +6 -1
  7. package/dist/cjs/index.js +6 -13
  8. package/dist/cjs/is.js +44 -1
  9. package/dist/cjs/math.js +56 -31
  10. package/dist/cjs/onOff.js +13 -9
  11. package/dist/cjs/traversal.js +2 -3
  12. package/dist/cjs/utils.js +155 -38
  13. package/dist/esm/Mouse.js +26 -15
  14. package/dist/esm/Translator.js +7 -1
  15. package/dist/esm/array.js +4 -35
  16. package/dist/esm/dom.js +819 -207
  17. package/dist/esm/eventDispatcher.js +7 -1
  18. package/dist/esm/index.js +7 -8
  19. package/dist/esm/is.js +43 -0
  20. package/dist/esm/math.js +58 -32
  21. package/dist/esm/onOff.js +13 -9
  22. package/dist/esm/traversal.js +2 -3
  23. package/dist/esm/utils.js +156 -39
  24. package/dist/umd/Translator.umd.js +1 -0
  25. package/dist/umd/dom.umd.js +1 -0
  26. package/dist/umd/eventDispatcher.umd.js +1 -0
  27. package/dist/umd/mouse.umd.js +1 -0
  28. package/dist/umd/webf.umd.js +1 -0
  29. package/docs/array.md +41 -8
  30. package/docs/dom.md +1063 -269
  31. package/docs/is.md +244 -0
  32. package/docs/math.md +87 -7
  33. package/docs/mouse.md +43 -0
  34. package/docs/translator.md +14 -14
  35. package/docs/traversal.md +16 -16
  36. package/docs/utils.md +173 -20
  37. package/package.json +10 -4
  38. package/src/Mouse.js +81 -0
  39. package/src/Translator.js +148 -0
  40. package/src/array.js +136 -0
  41. package/src/dom.js +1553 -0
  42. package/src/eventDispatcher.js +118 -0
  43. package/src/index.js +106 -0
  44. package/src/is.js +201 -0
  45. package/src/math.js +113 -0
  46. package/src/onOff.js +313 -0
  47. package/src/random.js +38 -0
  48. package/src/string.js +662 -0
  49. package/src/stringPrototype.js +16 -0
  50. package/src/traversal.js +236 -0
  51. package/src/utils.js +242 -0
  52. package/types/Mouse.d.ts +14 -3
  53. package/types/Translator.d.ts +6 -5
  54. package/types/array.d.ts +0 -1
  55. package/types/dom.d.ts +763 -204
  56. package/types/index.d.ts +22 -21
  57. package/types/is.d.ts +3 -0
  58. package/types/math.d.ts +6 -5
  59. package/types/traversal.d.ts +1 -1
  60. package/types/utils.d.ts +4 -4
  61. package/types/i18n.d.ts +0 -4
package/dist/esm/dom.js CHANGED
@@ -4,82 +4,74 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
4
4
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
5
5
  function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
6
6
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
7
- import { isArray, isArrayLike, isObject, isPlainObject, isString } from './is.js';
7
+ import { isArray, isArrayLike, isDocument, isFunction, isPlainObject, isString, isWindow } from './is.js';
8
8
  import { camelCase } from './string.js';
9
9
  import { each, foreach, map } from './traversal.js';
10
10
  import { inArray } from './array.js';
11
11
  import { on, off, __resetCustomEventsForTests } from './onOff.js';
12
12
  var cssNumber = ['animationIterationCount', 'aspectRatio', 'borderImageSlice', 'columnCount', 'flexGrow', 'flexShrink', 'fontWeight', 'gridArea', 'gridColumn', 'gridColumnEnd', 'gridColumnStart', 'gridRow', 'gridRowEnd', 'gridRowStart', 'lineHeight', 'opacity', 'order', 'orphans', 'scale', 'widows', 'zIndex', 'zoom', 'fillOpacity', 'floodOpacity', 'stopOpacity', 'strokeMiterlimit', 'strokeOpacity'];
13
-
14
- /**
15
- * @param {any} o
16
- * @returns {boolean}
17
- */
18
- export var isWindow = function isWindow(o) {
19
- return !!o && o === o.window;
20
- };
21
-
22
- /**
23
- * @param {any} o
24
- * @returns {boolean}
25
- */
26
- export var isDocument = function isDocument(o) {
27
- return !!o && o.nodeType === 9;
28
- };
29
-
30
- /**
31
- * @param {any} o
32
- * @returns {boolean}
33
- */
34
- export var isDomElement = function isDomElement(o) {
35
- return isObject(o) && o instanceof HTMLElement;
36
- };
37
-
38
- /**
39
- * @param {Element} el
40
- * @param {string} cssRule
41
- * @returns {string}
42
- */
43
- export var getStyle = function getStyle(el, cssRule) {
44
- if (!isDomElement(el)) {
45
- return '';
46
- }
47
- if (window.getComputedStyle) {
48
- var computedStyle = window.getComputedStyle(el, null);
49
- return computedStyle.getPropertyValue(cssRule) || computedStyle[camelCase(cssRule)] || '';
50
- }
51
- return el.style[camelCase(cssRule)] || '';
52
- };
53
13
  var dom = {
54
14
  /**
55
- * @param {Element} el
56
- * @param {string} [selector]
57
- * @returns {NodeList|Element[]}
15
+ * Returns the direct children of an element.
16
+ * If a selector is provided, only children matching the selector are returned.
17
+ *
18
+ * @example
19
+ * // <ul id="list"><li class="a"></li><li class="b"></li></ul>
20
+ * const list = document.getElementById('list')
21
+ *
22
+ * dom.children(list) // [[<li class="a">], [<li class="b">]]
23
+ * dom.children(list, '.a') // [<li class="a">]
24
+ *
25
+ * @param {Element} el - Parent element
26
+ * @param {string} [selector] - Optional CSS selector to filter direct children
27
+ * @returns {Element[]} Direct children, optionally filtered
58
28
  */
59
29
  children: function children(el, selector) {
60
- return selector ? this.find(el, ":scope > ".concat(selector)) : el.children;
30
+ return selector ? this.find(el, ":scope > ".concat(selector)) : Array.from(el.children);
61
31
  },
62
32
  /**
63
- * @param {Element} el
64
- * @param {string} [selector]
65
- * @returns {Element|null}
33
+ * Returns the first direct child of an element matching `selector`.
34
+ *
35
+ * @example
36
+ * // <ul id="list"><li class="a"></li><li class="b"></li></ul>
37
+ * const list = document.getElementById('list')
38
+ *
39
+ * dom.child(list) // <li class="a">
40
+ * dom.child(list, '.b') // <li class="b">
41
+ * dom.child(list, '.c') // null
42
+ *
43
+ * @param {Element} el - Parent element
44
+ * @param {string} [selector] - Optional CSS selector to filter direct children
45
+ * @returns {Element|null} - The first matching direct child, or null if none found
66
46
  */
67
47
  child: function child(el, selector) {
68
48
  return this.first(this.children(el, selector));
69
49
  },
70
50
  /**
71
- * @param {Element|Document|string} refEl
72
- * @param {string|Element|NodeList|Array<Element>} [selector]
73
- * @returns {Element}
74
- */
75
- findOne: function findOne(refEl, selector) {
76
- var _this$find$;
77
- return (_this$find$ = this.find(refEl, selector)[0]) !== null && _this$find$ !== void 0 ? _this$find$ : null;
78
- },
79
- /**
80
- * @param {Element|Document|string} refEl
81
- * @param {string|Element|NodeList|Array<Element>} [selector]
82
- * @returns {Element[]}
51
+ * Finds elements based on a selector or a collection
52
+ *
53
+ * If only one argument is provided, the search is performed from `document`.
54
+ *
55
+ * The `selector` can be:
56
+ * - a CSS selector string
57
+ * - a single Element
58
+ * - a NodeList or array-like collection of Elements
59
+ *
60
+ * @example
61
+ * dom.find('.item') // All elements matching .item in document
62
+ *
63
+ * const container = document.getElementById('box')
64
+ * dom.find(container, '.item') // All .item inside #box
65
+ *
66
+ * const el = document.querySelector('.item')
67
+ * dom.find(container, el) // [el] if inside container, otherwise []
68
+ *
69
+ * const list = document.querySelectorAll('.item')
70
+ * dom.find(container, list) // Only those inside container
71
+ *
72
+ * @param {Element|Document|DocumentFragment|string} refEl - Reference element or selector (if used alone)
73
+ * @param {string|Element|NodeList|Array<Element>} [selector] - What to find
74
+ * @returns {Element[]} - An array of matched elements
83
75
  */
84
76
  find: function find(refEl, selector) {
85
77
  if (undefined === selector) {
@@ -104,29 +96,80 @@ var dom = {
104
96
  }
105
97
  },
106
98
  /**
107
- * @param {Element|string} el
108
- * @param {string} data
109
- * @param {string} [value]
110
- * @returns {Element|null}
99
+ * Finds the first element matching a selector or collection.
100
+ *
101
+ * Behaves like `dom.find` but returns only the first matched element.
102
+ * Returns `null` if no element matches.
103
+ *
104
+ * @param {Element|Document|DocumentFragment|string} refEl - Reference element or selector (if used alone)
105
+ * @param {string|Element|NodeList|Array<Element>} [selector] - What to find
106
+ * @returns {Element|null} - The first matched Element, or null if none found
111
107
  */
112
- findOneByData: function findOneByData(el, data, value) {
113
- var _this$findByData$;
114
- return (_this$findByData$ = this.findByData(el, data, value)[0]) !== null && _this$findByData$ !== void 0 ? _this$findByData$ : null;
108
+ findOne: function findOne(refEl, selector) {
109
+ var _this$find$;
110
+ return (_this$find$ = this.find(refEl, selector)[0]) !== null && _this$find$ !== void 0 ? _this$find$ : null;
115
111
  },
116
112
  /**
117
- * @param {Element|string} el
118
- * @param {string} data
119
- * @param {string} [value]
120
- * @returns {Element[]}
113
+ * Finds elements by a data-* attribute.
114
+ *
115
+ * If `value` is provided, only elements with an exact matching value are returned.
116
+ * If `value` is omitted, all elements having the data attribute are returned.
117
+ *
118
+ * @example
119
+ * // <div data-user-id="42"></div>
120
+ *
121
+ * dom.findByData(document, 'user-id') // all elements with [data-user-id]
122
+ * dom.findByData(document, 'user-id', '42') // elements with [data-user-id="42"]
123
+ *
124
+ * @param {Element|Document|string} el - Reference element or selector (if used alone)
125
+ * @param {string} data - The data-* key without the "data-" prefix
126
+ * @param {string} [value] - Optional value to match exactly
127
+ * @returns {Element[]} - Matching elements
121
128
  */
122
129
  findByData: function findByData(el, data, value) {
123
- var escapeValue = CSS.escape(value);
130
+ if (undefined === value) return this.find(el, "[data-".concat(data, "]"));
131
+ var escapeValue = CSS.escape(value + '');
124
132
  return this.find(el, "[data-".concat(data, "=\"").concat(escapeValue, "\"]"));
125
133
  },
126
134
  /**
127
- * @param {Element|NodeList|Array<Element>} el
128
- * @param {string} className
129
- * @returns {Element|NodeList|Array<Element>}
135
+ * Finds the first element matching a data-* attribute.
136
+ *
137
+ * If `value` is provided, returns the first element whose data attribute
138
+ * exactly matches the given value. If omitted, returns the first element
139
+ * that has the data attribute.
140
+ *
141
+ * @example
142
+ * // <div data-user-id="42"></div>
143
+ *
144
+ * dom.findOneByData(document, 'user-id') // first element with [data-user-id]
145
+ * dom.findOneByData(document, 'user-id', '42') // element with [data-user-id="42"]
146
+ * dom.findOneByData(document, 'user-id', '99') // null
147
+ *
148
+ * @param {Element|Document|string} el - Reference element or selector (if used alone)
149
+ * @param {string} data - The data-* key without the "data-" prefix
150
+ * @param {string} [value] - Optional value to match exactly
151
+ * @returns {Element|null} The first matching element, or null if none found
152
+ */
153
+ findOneByData: function findOneByData(el, data, value) {
154
+ var _this$findByData$;
155
+ return (_this$findByData$ = this.findByData(el, data, value)[0]) !== null && _this$findByData$ !== void 0 ? _this$findByData$ : null;
156
+ },
157
+ /**
158
+ * Adds one or more CSS classes to one or multiple elements.
159
+ *
160
+ * Multiple classes can be provided as a space-separated string.
161
+ * Accepts a single Element, a NodeList, or an array of Elements.
162
+ *
163
+ * @example
164
+ * const el = document.querySelector('#box')
165
+ * dom.addClass(el, 'active')
166
+ *
167
+ * const items = document.querySelectorAll('.item')
168
+ * dom.addClass(items, 'selected active')
169
+ *
170
+ * @param {Element|NodeList|Element[]} el - Element(s) to update
171
+ * @param {string} className - One or more class names separated by spaces
172
+ * @returns {Element|NodeList|Element[]} The original input
130
173
  */
131
174
  addClass: function addClass(el, className) {
132
175
  if (!className) return el;
@@ -143,12 +186,24 @@ var dom = {
143
186
  return el;
144
187
  },
145
188
  /**
146
- * @param {Element|NodeList|Array<Element>} el
147
- * @param {string} className
148
- * @returns {Element|NodeList|Array<Element>}
189
+ * Removes one or more CSS classes from one or multiple elements.
190
+ *
191
+ * Multiple classes can be provided as a space-separated string.
192
+ * Accepts a single Element, a NodeList, or an array of Elements.
193
+ *
194
+ * @example
195
+ * const el = document.querySelector('#box')
196
+ * dom.removeClass(el, 'active')
197
+ *
198
+ * const items = document.querySelectorAll('.item')
199
+ * dom.removeClass(items, 'selected highlighted')
200
+ *
201
+ * @param {Element|NodeList|Array<Element>} el - Element(s) to update
202
+ * @param {string} className - One or more class names separated by spaces
203
+ * @returns {Element|NodeList|Array<Element>} The original input
149
204
  */
150
205
  removeClass: function removeClass(el, className) {
151
- if (!className) return;
206
+ if (!className) return el;
152
207
  var classNames = className.split(' ').map(function (c) {
153
208
  return c.trim();
154
209
  }).filter(Boolean);
@@ -162,10 +217,24 @@ var dom = {
162
217
  return el;
163
218
  },
164
219
  /**
165
- * @param {Element} el
166
- * @param {string} classNames
167
- * @param {boolean} [force]
168
- * @returns {Element}
220
+ * Toggles one or more CSS classes on an element.
221
+ *
222
+ * Multiple classes can be provided as a space-separated string.
223
+ * If `force` is provided, it explicitly adds (`true`) or removes (`false`)
224
+ * the class instead of toggling it.
225
+ *
226
+ * @example
227
+ * const el = document.querySelector('#box')
228
+ *
229
+ * dom.toggleClass(el, 'active') // toggles "active"
230
+ * dom.toggleClass(el, 'a b') // toggles both classes
231
+ * dom.toggleClass(el, 'active', true) // ensures "active" is present
232
+ * dom.toggleClass(el, 'active', false) // ensures "active" is removed
233
+ *
234
+ * @param {Element} el - Element to update
235
+ * @param {string} classNames - One or more class names separated by spaces
236
+ * @param {boolean} [force] - Optional force flag passed to classList.toggle
237
+ * @returns {Element} The element
169
238
  */
170
239
  toggleClass: function toggleClass(el, classNames, force) {
171
240
  foreach(classNames.split(' ').map(function (c) {
@@ -176,9 +245,22 @@ var dom = {
176
245
  return el;
177
246
  },
178
247
  /**
179
- * @param {Element} el
180
- * @param {string} classNames
181
- * @returns {boolean}
248
+ * Checks whether an element has all the given CSS classes.
249
+ *
250
+ * Multiple classes can be provided as a space-separated string.
251
+ * Returns `true` only if the element contains every class.
252
+ *
253
+ * @example
254
+ * // <div class="box active large"></div>
255
+ *
256
+ * dom.hasClass(el, 'active') // true
257
+ * dom.hasClass(el, 'active large') // true
258
+ * dom.hasClass(el, 'active missing') // false
259
+ * dom.hasClass(el, '') // false
260
+ *
261
+ * @param {Element} el - Element to test
262
+ * @param {string} classNames - One or more class names separated by spaces
263
+ * @returns {boolean} - `true` if the element has all the classes
182
264
  */
183
265
  hasClass: function hasClass(el, classNames) {
184
266
  if (!classNames) return false;
@@ -186,18 +268,25 @@ var dom = {
186
268
  foreach(classNames.split(' ').map(function (c) {
187
269
  return c.trim();
188
270
  }).filter(Boolean), function (c) {
189
- if (el.classList.contains(c)) {
190
- return true;
191
- }
271
+ if (inArray(c, Array.from(el.classList))) return;
192
272
  foundClasses = false;
193
273
  return false;
194
274
  });
195
275
  return foundClasses;
196
276
  },
197
277
  /**
198
- * @param {Node} node
199
- * @param {...(Node|string)} children
200
- * @returns {Node}
278
+ * Appends one or more children to a node.
279
+ *
280
+ * Children can be DOM nodes or HTML strings.
281
+ *
282
+ * @example
283
+ * const box = document.createElement('div')
284
+ * dom.append(box, document.createElement('span'))
285
+ * dom.append(box, '<b>Hello</b>', '<i>world</i>')
286
+ *
287
+ * @param {Node} node - The parent node
288
+ * @param {...(Node|string)} children - Nodes or HTML strings to append
289
+ * @returns {Node} The parent node
201
290
  */
202
291
  append: function append(node) {
203
292
  var _this = this;
@@ -213,9 +302,21 @@ var dom = {
213
302
  return node;
214
303
  },
215
304
  /**
216
- * @param {Node} node
217
- * @param {...(Node|string)} children
218
- * @returns {Node}
305
+ * Prepends one or more children to a node.
306
+ *
307
+ * Children can be DOM nodes or HTML strings.
308
+ * HTML strings are converted to nodes using `dom.create`.
309
+ * When multiple children are provided, their original order is preserved.
310
+ *
311
+ * @example
312
+ * const box = document.createElement('div')
313
+ *
314
+ * dom.prepend(box, document.createElement('span'))
315
+ * dom.prepend(box, '<b>Hello</b>', '<i>world</i>')
316
+ *
317
+ * @param {Node} node - The parent node
318
+ * @param {...(Node|string)} children - Nodes or HTML strings to prepend
319
+ * @returns {Node} - The parent node
219
320
  */
220
321
  prepend: function prepend(node) {
221
322
  var _this2 = this;
@@ -231,7 +332,7 @@ var dom = {
231
332
  return node;
232
333
  },
233
334
  /**
234
- * @param {Element|NodeList|Array<Element>|string} els
335
+ * @param {...(Element|NodeListOf<Element>|Iterable<Element>|string)} els
235
336
  * @returns {void}
236
337
  */
237
338
  remove: function remove() {
@@ -247,14 +348,31 @@ var dom = {
247
348
  return e.remove();
248
349
  });
249
350
  } else {
250
- _this3.remove(_this3.find(el));
351
+ _this3.find(el).forEach(function (e) {
352
+ return e.remove();
353
+ });
251
354
  }
252
355
  });
253
356
  },
254
357
  /**
255
- * @param {Element} el
256
- * @param {string|Element} [selector]
257
- * @returns {Element|null}
358
+ * Returns the closest ancestor of an element matching a selector or a specific element.
359
+ *
360
+ * If a DOM element is provided as `selector`, the function walks up the DOM
361
+ * tree and returns it if found among the ancestors (or the element itself).
362
+ * If a CSS selector string is provided, it delegates to `Element.closest()`.
363
+ * If `selector` is omitted, the element itself is returned.
364
+ *
365
+ * @example
366
+ * const item = document.querySelector('.item')
367
+ * const container = document.querySelector('.container')
368
+ *
369
+ * dom.closest(item, '.container') // container
370
+ * dom.closest(item, container) // container
371
+ * dom.closest(item) // item
372
+ *
373
+ * @param {Element} el - The starting element
374
+ * @param {string|Element} [selector] - CSS selector or specific ancestor element
375
+ * @returns {Element|null} - The matching ancestor, or null if none found
258
376
  */
259
377
  closest: function closest(el, selector) {
260
378
  if (selector instanceof Element) {
@@ -274,9 +392,22 @@ var dom = {
274
392
  return el.closest(selector);
275
393
  },
276
394
  /**
277
- * @param {Element} el
278
- * @param {string} [selector]
279
- * @returns {Element|null}
395
+ * Returns the next sibling element of a node.
396
+ *
397
+ * If a selector is provided, the next sibling is returned only if it matches
398
+ * the selector. This function does not search beyond the immediate sibling.
399
+ *
400
+ * @example
401
+ * // <div class="a"></div><div class="b"></div><div class="c"></div>
402
+ * const a = document.querySelector('.a')
403
+ *
404
+ * dom.next(a) // <div class="b">
405
+ * dom.next(a, '.b') // <div class="b">
406
+ * dom.next(a, '.c') // null
407
+ *
408
+ * @param {Element} el - Reference element
409
+ * @param {string|null} [selector] - CSS selector to filter the sibling
410
+ * @returns {Element|null} - The next sibling element, or null if not found/matching
280
411
  */
281
412
  next: function next(el) {
282
413
  var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
@@ -288,9 +419,22 @@ var dom = {
288
419
  return null;
289
420
  },
290
421
  /**
291
- * @param {Element} el
292
- * @param {string|null} [selector]
293
- * @returns {Element|null}
422
+ * Returns the previous sibling element of a node.
423
+ *
424
+ * If a selector is provided, the previous sibling is returned only if it matches
425
+ * the selector. This function does not search beyond the immediate sibling.
426
+ *
427
+ * @example
428
+ * // <div class="a"></div><div class="b"></div><div class="c"></div>
429
+ * const c = document.querySelector('.c')
430
+ *
431
+ * dom.prev(c) // <div class="b">
432
+ * dom.prev(c, '.b') // <div class="b">
433
+ * dom.prev(c, '.a') // null
434
+ *
435
+ * @param {Element} el - Reference element
436
+ * @param {string|null} [selector] - CSS selector to filter the sibling
437
+ * @returns {Element|null} - The previous sibling element, or null if not found/matching
294
438
  */
295
439
  prev: function prev(el) {
296
440
  var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
@@ -302,9 +446,21 @@ var dom = {
302
446
  return null;
303
447
  },
304
448
  /**
305
- * @param {Element} el
306
- * @param {string} [selector]
307
- * @returns {Element[]}
449
+ * Returns all following sibling elements of a node.
450
+ *
451
+ * If a selector is provided, only siblings matching the selector are included.
452
+ * Traversal continues through all next siblings in document order.
453
+ *
454
+ * @example
455
+ * // <div class="a"></div><div class="b"></div><div class="c"></div>
456
+ * const a = document.querySelector('.a')
457
+ *
458
+ * dom.nextAll(a) // [<div class="b">, <div class="c">]
459
+ * dom.nextAll(a, '.c') // [<div class="c">]
460
+ *
461
+ * @param {Element} el - Reference element
462
+ * @param {string} [selector] - CSS selector to filter siblings
463
+ * @returns {Element[]} - Array of matching following siblings
308
464
  */
309
465
  nextAll: function nextAll(el, selector) {
310
466
  var siblings = [];
@@ -318,9 +474,21 @@ var dom = {
318
474
  return siblings;
319
475
  },
320
476
  /**
321
- * @param {Element} el
322
- * @param {string} [selector]
323
- * @returns {Element[]}
477
+ * Returns all preceding sibling elements of a node.
478
+ *
479
+ * If a selector is provided, only siblings matching the selector are included.
480
+ * Traversal continues through all previous siblings in reverse document order.
481
+ *
482
+ * @example
483
+ * // <div class="a"></div><div class="b"></div><div class="c"></div>
484
+ * const c = document.querySelector('.c')
485
+ *
486
+ * dom.prevAll(c) // [<div class="b">, <div class="a">]
487
+ * dom.prevAll(c, '.a') // [<div class="a">]
488
+ *
489
+ * @param {Element} el - Reference element
490
+ * @param {string} [selector] - CSS selector to filter siblings
491
+ * @returns {Element[]} - Array of matching preceding siblings
324
492
  */
325
493
  prevAll: function prevAll(el, selector) {
326
494
  var siblings = [];
@@ -334,9 +502,42 @@ var dom = {
334
502
  return siblings;
335
503
  },
336
504
  /**
337
- * @param {Element} el
338
- * @param {Element|string} selector
339
- * @returns {Element[]}
505
+ * Returns the index of a node among its preceding siblings.
506
+ *
507
+ * If a selector is provided, only matching siblings are considered.
508
+ *
509
+ * @example
510
+ * // <div class="a"></div><div class="b"></div><div class="c"></div>
511
+ * const c = document.querySelector('.c')
512
+ *
513
+ * dom.index(a) // 0
514
+ * dom.index(c) // 2
515
+ * dom.prevAll(c, '.a') // 1
516
+ *
517
+ * @param {Element} el - Reference element
518
+ * @param {string} [selector] - CSS selector to filter siblings
519
+ * @returns {number} - The index of `el`
520
+ */
521
+ index: function index(el, selector) {
522
+ return this.prevAll(el, selector).length;
523
+ },
524
+ /**
525
+ * Returns all following sibling elements until a matching element is reached.
526
+ *
527
+ * Traversal stops before the first sibling that matches the given selector
528
+ * or equals the provided element. That matching element is not included.
529
+ *
530
+ * @example
531
+ * // <div class="a"></div><div class="b"></div><div class="c"></div><div class="d"></div>
532
+ * const a = document.querySelector('.a')
533
+ * const d = document.querySelector('.d')
534
+ *
535
+ * dom.nextUntil(a, '.d') // [<div class="b">, <div class="c">]
536
+ * dom.nextUntil(a, d) // [<div class="b">, <div class="c">]
537
+ *
538
+ * @param {Element} el - Reference element
539
+ * @param {Element|string} selector - CSS selector or element to stop at
540
+ * @returns {Element[]} - Array of siblings until the stop condition
340
541
  */
341
542
  nextUntil: function nextUntil(el, selector) {
342
543
  var selectorIsElement = false;
@@ -354,9 +555,23 @@ var dom = {
354
555
  return list;
355
556
  },
356
557
  /**
357
- * @param {Element} el
358
- * @param {Element|string} selector
359
- * @returns {Element[]}
558
+ * Returns all preceding sibling elements until a matching element is reached.
559
+ *
560
+ * Traversal stops before the first sibling that matches the given selector
561
+ * or equals the provided element. That matching element is not included.
562
+ *
563
+ * @example
564
+ * // <div class="a"></div><div class="b"></div><div class="c"></div><div class="d"></div>
565
+ *
566
+ * const d = document.querySelector('.d')
567
+ * const a = document.querySelector('.a')
568
+ *
569
+ * dom.prevUntil(d, '.a') // [<div class="c">, <div class="b">]
570
+ * dom.prevUntil(d, a) // [<div class="c">, <div class="b">]
571
+ *
572
+ * @param {Element} el - Reference element
573
+ * @param {Element|string} selector - CSS selector or element to stop at
574
+ * @returns {Element[]} - Array of siblings until the stop condition
360
575
  */
361
576
  prevUntil: function prevUntil(el, selector) {
362
577
  var selectorIsElement = false;
@@ -374,9 +589,22 @@ var dom = {
374
589
  return list;
375
590
  },
376
591
  /**
377
- * @param {Element} el
378
- * @param {Element} wrappingElement
379
- * @returns {Element}
592
+ * Wraps an element inside another element.
593
+ *
594
+ * If the wrapping element is not already in the DOM, it is inserted
595
+ * just before the target element. The target element is then appended
596
+ * inside the wrapper.
597
+ *
598
+ * @example
599
+ * const el = document.querySelector('.item')
600
+ * const wrapper = document.createElement('div')
601
+ *
602
+ * dom.wrap(el, wrapper)
603
+ * // <div><div class="item"></div></div>
604
+ *
605
+ * @param {Element} el - The element to wrap
606
+ * @param {Element} wrappingElement - The wrapper element
607
+ * @returns {Element} - The original wrapped element
380
608
  */
381
609
  wrap: function wrap(el, wrappingElement) {
382
610
  if (!wrappingElement.isConnected) {
@@ -386,10 +614,21 @@ var dom = {
386
614
  return el;
387
615
  },
388
616
  /**
389
- * @param {Element} el
390
- * @param {string} name
391
- * @param {*} [value]
392
- * @returns {Element|*}
617
+ * Gets, sets, or removes an attribute on an element.
618
+ *
619
+ * - If `value` is omitted, returns the attribute value (or null if not present).
620
+ * - If `value` is `null`, the attribute is removed.
621
+ * - Otherwise, the attribute is set to the provided value.
622
+ *
623
+ * @example
624
+ * dom.attr(el, 'id') // "my-id"
625
+ * dom.attr(el, 'title', 'Hello') // sets title="Hello"
626
+ * dom.attr(el, 'disabled', null) // removes the attribute
627
+ *
628
+ * @param {Element} el - Target element
629
+ * @param {string} name - Attribute name
630
+ * @param {string|null} [value] - Value to set, or null to remove
631
+ * @returns {Element|string|null} - The attribute value when reading, otherwise the element
393
632
  */
394
633
  attr: function attr(el, name, value) {
395
634
  if (undefined === value) return el.getAttribute(name);
@@ -401,10 +640,24 @@ var dom = {
401
640
  return el;
402
641
  },
403
642
  /**
404
- * @param {Element} el
405
- * @param {string} name
406
- * @param {*} [value]
407
- * @returns {*|Element}
643
+ * Gets or sets a property directly on a DOM element.
644
+ *
645
+ * Unlike `dom.attr`, this interacts with the live DOM property,
646
+ * not the HTML attribute.
647
+ *
648
+ * - If `value` is omitted, returns the property value.
649
+ * - Otherwise, sets the property.
650
+ *
651
+ * @example
652
+ * dom.prop(input, 'checked') // true/false
653
+ * dom.prop(input, 'checked', true) // checks the checkbox
654
+ *
655
+ * dom.prop(img, 'src') // full resolved URL
656
+ *
657
+ * @param {Element} el - Target element
658
+ * @param {string} name - Property name
659
+ * @param {any} [value] - Value to set
660
+ * @returns {*|Element} - The property value when reading, otherwise the element
408
661
  */
409
662
  prop: function prop(el, name, value) {
410
663
  if (undefined === value) {
@@ -414,9 +667,18 @@ var dom = {
414
667
  return el;
415
668
  },
416
669
  /**
417
- * @param {Element} el
418
- * @param {string} [html]
419
- * @returns {Element|string}
670
+ * Gets or sets the HTML content of an element.
671
+ *
672
+ * - If `html` is omitted, returns the element's current `innerHTML`.
673
+ * - Otherwise, replaces the element's content with the provided HTML string.
674
+ *
675
+ * @example
676
+ * dom.html(el) // "<span>Hello</span>"
677
+ * dom.html(el, '<b>Hi</b>') // sets inner HTML
678
+ *
679
+ * @param {Element} el - Target element
680
+ * @param {string} [html] - HTML string to set
681
+ * @returns {Element|string} The HTML string when reading, otherwise the element
420
682
  */
421
683
  html: function html(el, _html) {
422
684
  if (undefined === _html) return el.innerHTML;
@@ -424,9 +686,18 @@ var dom = {
424
686
  return el;
425
687
  },
426
688
  /**
427
- * @param {Element} el
428
- * @param {string} [text]
429
- * @returns {Element|string}
689
+ * Gets or sets the text content of an element.
690
+ *
691
+ * - If `text` is omitted, returns the element's visible text (`innerText`).
692
+ * - Otherwise, replaces the element's text content.
693
+ *
694
+ * @example
695
+ * dom.text(el) // "Hello world"
696
+ * dom.text(el, 'New text') // sets visible text content
697
+ *
698
+ * @param {Element} el - Target element
699
+ * @param {string} [text] - Text to set
700
+ * @returns {Element|string} - The text when reading, otherwise the element
430
701
  */
431
702
  text: function text(el, _text) {
432
703
  if (undefined === _text) return el.innerText;
@@ -434,20 +705,43 @@ var dom = {
434
705
  return el;
435
706
  },
436
707
  /**
437
- * @param {Element} el
438
- * @returns {Element}
708
+ * Hides an element by setting `display: none`, while preserving its original display value.
709
+ *
710
+ * The original computed `display` value is stored internally so it can be
711
+ * restored later (typically by the corresponding `show()` method).
712
+ *
713
+ * @example
714
+ * dom.hide(el) // element becomes hidden
715
+ *
716
+ * @param {Element} el - Element to hide
717
+ * @returns {Element} The element
439
718
  */
440
719
  hide: function hide(el) {
441
720
  if (undefined === this.data(el, '__display__')) {
442
- var display = getComputedStyle(el).display;
721
+ var display = '';
722
+ if (isFunction(window.getComputedStyle)) {
723
+ display = window.getComputedStyle(el).display;
724
+ } else {
725
+ display = el.style.display;
726
+ }
443
727
  this.data(el, '__display__', display);
444
728
  }
445
729
  el.style.display = 'none';
446
730
  return el;
447
731
  },
448
732
  /**
449
- * @param {Element} el
450
- * @returns {Element}
733
+ * Shows an element by restoring its original `display` value.
734
+ *
735
+ * If the element was previously hidden using `hide`, its original
736
+ * computed display value is restored. Otherwise, the inline `display`
737
+ * style is simply removed.
738
+ *
739
+ * @example
740
+ * dom.hide(el)
741
+ * dom.show(el) // element becomes visible again with its original display
742
+ *
743
+ * @param {Element} el - Element to show
744
+ * @returns {Element} - The element
451
745
  */
452
746
  show: function show(el) {
453
747
  var dataDisplay = this.data(el, '__display__');
@@ -460,17 +754,47 @@ var dom = {
460
754
  return el;
461
755
  },
462
756
  /**
463
- * @param {Element} el
464
- * @returns {Element}
757
+ * Toggles the visibility of an element using `dom.hide` and `dom.show`.
758
+ *
759
+ * The visibility state is determined from the computed display value,
760
+ * not only the inline style.
761
+ *
762
+ * @example
763
+ * dom.toggle(el) // hides if visible, shows if hidden
764
+ *
765
+ * @param {Element} el - Element to toggle
766
+ * @returns {Element} - The element
465
767
  */
466
768
  toggle: function toggle(el) {
467
- return 'none' === el.style.display ? this.show(el) : this.hide(el);
769
+ return 'none' === this.css(el, 'display') ? this.show(el) : this.hide(el);
468
770
  },
469
771
  /**
470
- * @param {Element} el
471
- * @param {Object<string, string>|string} name
472
- * @param {string} [value]
473
- * @returns {Element|DOMStringMap}
772
+ * Gets, sets, or removes data-* attributes on an element.
773
+ *
774
+ * - If called with no arguments, returns the element's `dataset`.
775
+ * - If `name` is an object, sets multiple data entries.
776
+ * - If `value` is omitted, returns the value of the data key.
777
+ * - If `value` is `null`, removes the data attribute.
778
+ * - Otherwise, sets the data value.
779
+ *
780
+ * Keys can be provided in camelCase (`userId`) or kebab-case with `data-` prefix (`data-user-id`).
781
+ *
782
+ * @example
783
+ * dom.data(el) // DOMStringMap of all data attributes
784
+ *
785
+ * dom.data(el, 'userId') // value of data-user-id
786
+ * dom.data(el, 'userId', '42') // sets data-user-id="42"
787
+ *
788
+ * dom.data(el, 'data-role', 'admin') // also works
789
+ *
790
+ * dom.data(el, { userId: '42', role: 'admin' }) // sets multiple values
791
+ *
792
+ * dom.data(el, 'userId', null) // removes data-user-id
793
+ *
794
+ * @param {Element} el - Target element
795
+ * @param {Object<string, string>|string} [name] - Data key or object of key/value pairs
796
+ * @param {string|null} [value] - Value to set, or null to remove
797
+ * @returns {Element|DOMStringMap|string|undefined} - Dataset, value, or element
474
798
  */
475
799
  data: function data(el, name, value) {
476
800
  var _this4 = this;
@@ -487,34 +811,69 @@ var dom = {
487
811
  var key = camelCase(isAttr ? (name + '').replace(/^data-/, '') : name + '');
488
812
  if (undefined === value) return el.dataset[key];
489
813
  if (null === value) {
490
- this.removeData(el, key);
814
+ delete el.dataset[key];
491
815
  return el;
492
816
  }
493
817
  el.dataset[key] = value;
494
818
  return el;
495
819
  },
496
820
  /**
497
- * @param {Element} el
498
- * @param {string} name
499
- * @returns {Element|*}
821
+ * Removes a data-* attribute from an element.
822
+ *
823
+ * The key can be provided in camelCase, kebab-case, or with the `data-` prefix.
824
+ *
825
+ * @example
826
+ * dom.removeData(el, 'userId') // removes data-user-id
827
+ * dom.removeData(el, 'user-id') // removes data-user-id
828
+ * dom.removeData(el, 'data-role') // removes data-role
829
+ *
830
+ * @param {Element} el - Target element
831
+ * @param {string} name - Data key to remove
832
+ * @returns {Element} - The element
500
833
  */
501
834
  removeData: function removeData(el, name) {
502
- var key = camelCase((name + '').replace(/^data-/, ''));
503
- delete el.dataset[key];
504
- return el;
835
+ return this.data(el, name, null);
505
836
  },
506
837
  /**
507
- * @param {HTMLElement} el
508
- * @param {Object<string, string>|string} style
509
- * @param {string} [value]
510
- * @returns {Element}
838
+ * Gets or sets CSS styles on an element.
839
+ *
840
+ * - If `style` is a string and `value` is omitted, returns the computed style value.
841
+ * - If `style` is a string and `value` is provided, sets the style.
842
+ * - If `style` is an object, sets multiple styles at once.
843
+ *
844
+ * handles :
845
+ * - camelCase and kebab-case properties
846
+ * - CSS custom properties (`--var`)
847
+ * - Adding `px` to numeric values where appropriate
848
+ *
849
+ * @example
850
+ * dom.css(el, 'color') // "rgb(255, 0, 0)"
851
+ * dom.css(el, 'background-color', 'blue')
852
+ * dom.css(el, 'width', 200) // sets "200px"
853
+ *
854
+ * dom.css(el, {
855
+ * width: 100,
856
+ * height: 50,
857
+ * backgroundColor: 'red'
858
+ * })
859
+ *
860
+ * dom.css(el, '--my-var', '10px') // CSS custom property
861
+ *
862
+ * @param {HTMLElement} el - Target element
863
+ * @param {Object<string, string|number>|string} style - CSS property or object of properties
864
+ * @param {string|number} [value] - Value to set
865
+ * @returns {Element|string} - The style value when reading, otherwise the element
511
866
  */
512
867
  css: function css(el, style, value) {
513
868
  var _this5 = this;
514
869
  if (isString(style)) {
515
870
  var prop = style.startsWith('--') ? style : camelCase(style);
516
871
  if (undefined === value) {
517
- return getStyle(el, prop);
872
+ if (window.getComputedStyle) {
873
+ var computedStyle = window.getComputedStyle(el, null);
874
+ return computedStyle.getPropertyValue(style) || computedStyle[camelCase(style)] || '';
875
+ }
876
+ return el.style[camelCase(style)] || '';
518
877
  }
519
878
  if (prop.startsWith('--')) {
520
879
  el.style.setProperty(prop, String(value));
@@ -530,10 +889,22 @@ var dom = {
530
889
  return el;
531
890
  },
532
891
  /**
533
- * @param {Element} el
534
- * @param {string} selectorClosest
535
- * @param {string} selectorFind
536
- * @returns {Array<Element>}
892
+ * Finds elements matching a selector inside the closest ancestor
893
+ * that matches another selector.
894
+ *
895
+ * First finds the closest ancestor of `el` matching `selectorClosest`,
896
+ * then searches inside it for elements matching `selectorFind`.
897
+ *
898
+ * @example
899
+ * // <div class="card"><button class="btn"></button><span class="label"></span></div>
900
+ *
901
+ * dom.closestFind(button, '.card', '.label')
902
+ * // => finds .label inside the closest .card ancestor
903
+ *
904
+ * @param {Element} el - Starting element
905
+ * @param {string} selectorClosest - Selector used to find the closest ancestor
906
+ * @param {string} selectorFind - Selector used to find elements inside that ancestor
907
+ * @returns {Element[]} - Array of matched elements, or empty array if none found
537
908
  */
538
909
  closestFind: function closestFind(el, selectorClosest, selectorFind) {
539
910
  var closest = this.closest(el, selectorClosest);
@@ -543,10 +914,22 @@ var dom = {
543
914
  return [];
544
915
  },
545
916
  /**
546
- * @param {Element} el
547
- * @param {string} selectorClosest
548
- * @param {string} selectorFindOne
549
- * @returns {Element|null}
917
+ * Finds the first element matching a selector inside the closest ancestor
918
+ * that matches another selector.
919
+ *
920
+ * First finds the closest ancestor of `el` matching `selectorClosest`,
921
+ * then searches inside it for the first element matching `selectorFindOne`.
922
+ *
923
+ * @example
924
+ * // <div class="card"><button class="btn"></button><span class="label"></span></div>
925
+ *
926
+ * dom.closestFindOne(button, '.card', '.label')
927
+ * // => finds the first .label inside the closest .card ancestor
928
+ *
929
+ * @param {Element} el - Starting element
930
+ * @param {string} selectorClosest - Selector used to find the closest ancestor
931
+ * @param {string} selectorFindOne - Selector used to find a single element inside that ancestor
932
+ * @returns {Element|null} - The matched element, or null if none found
550
933
  */
551
934
  closestFindOne: function closestFindOne(el, selectorClosest, selectorFindOne) {
552
935
  var closest = this.closest(el, selectorClosest);
@@ -556,8 +939,18 @@ var dom = {
556
939
  return null;
557
940
  },
558
941
  /**
559
- * @param {NodeList|Element|Array<Element>} nodeList
560
- * @returns {Element|null}
942
+ * Returns the first element from a collection or the element itself.
943
+ *
944
+ * Accepts a single Element, a NodeList, or an array of Elements.
945
+ * Returns `null` if the collection is empty.
946
+ *
947
+ * @example
948
+ * dom.first(document.querySelectorAll('.item')) // first .item
949
+ * dom.first([el1, el2]) // el1
950
+ * dom.first(el) // el
951
+ *
952
+ * @param {NodeList|Element|Element[]} nodeList - Collection or single element
953
+ * @returns {Element|null} - The first element, or null if none found
561
954
  */
562
955
  first: function first(nodeList) {
563
956
  var _Array$from$;
@@ -565,8 +958,17 @@ var dom = {
565
958
  return (_Array$from$ = Array.from(nodeList)[0]) !== null && _Array$from$ !== void 0 ? _Array$from$ : null;
566
959
  },
567
960
  /**
568
- * @param {NodeList|Array<Element>} nodeList
569
- * @returns {Element|null}
961
+ * Returns the last element from a collection or the element itself.
962
+ *
963
+ * Accepts a NodeList or an array of Elements.
964
+ * Returns `null` if the collection is empty.
965
+ *
966
+ * @example
967
+ * dom.last(document.querySelectorAll('.item')) // last .item
968
+ * dom.last([el1, el2]) // el2
969
+ *
970
+ * @param {NodeList|Element|Element[]} nodeList - Collection or single element
971
+ * @returns {Element|null} - The last element, or null if none found
570
972
  */
571
973
  last: function last(nodeList) {
572
974
  var _arr;
@@ -575,8 +977,20 @@ var dom = {
575
977
  return (_arr = arr[arr.length - 1]) !== null && _arr !== void 0 ? _arr : null;
576
978
  },
577
979
  /**
578
- * @param {string} html
579
- * @returns {Element|DocumentFragment|null}
980
+ * Creates DOM node(s) from a tag name or an HTML string.
981
+ *
982
+ * - If a simple tag name is provided (e.g. `"div"`), a new element is created.
983
+ * - If an HTML string is provided, it is parsed using a `<template>` element.
984
+ * - If the HTML contains a single root element, that element is returned.
985
+ * - If multiple root nodes are present, a `DocumentFragment` is returned.
986
+ *
987
+ * @example
988
+ * dom.create('div') // <div></div>
989
+ * dom.create('<span>Hello</span>') // <span>Hello</span>
990
+ * dom.create('<li>One</li><li>Two</li>') // DocumentFragment containing both <li>
991
+ *
992
+ * @param {string} html - Tag name or HTML string
993
+ * @returns {Element|DocumentFragment|null} - Created node(s), or null if input is invalid
580
994
  */
581
995
  create: function create(html) {
582
996
  if (!isString(html)) return null;
@@ -595,9 +1009,22 @@ var dom = {
595
1009
  return frag.cloneNode(true);
596
1010
  },
597
1011
  /**
598
- * @param {NodeList|Array<Element>} nodeList
599
- * @param {number} [index=0]
600
- * @returns {Element|null}
1012
+ * Returns the element at a given index from a collection.
1013
+ *
1014
+ * Supports negative indexes to count from the end of the list.
1015
+ * Returns `null` if the index is out of bounds.
1016
+ *
1017
+ * @example
1018
+ * const items = document.querySelectorAll('.item')
1019
+ *
1020
+ * dom.eq(items, 0) // first element
1021
+ * dom.eq(items, 2) // third element
1022
+ * dom.eq(items, -1) // last element
1023
+ * dom.eq(items, -2) // second to last
1024
+ *
1025
+ * @param {NodeList|Element[]} nodeList - Collection of elements
1026
+ * @param {number} [index=0] - Index of the element (can be negative)
1027
+ * @returns {Element|null} - The element at the given index, or null if not found
601
1028
  */
602
1029
  eq: function eq(nodeList) {
603
1030
  var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
@@ -609,9 +1036,18 @@ var dom = {
609
1036
  return nodeList[index];
610
1037
  },
611
1038
  /**
612
- * @param {Element} el
613
- * @param {Element|string} newEl
614
- * @returns {Element|null}
1039
+ * Inserts a new element or HTML string immediately after a reference element.
1040
+ *
1041
+ * If `newEl` is a string, it is converted to a node using `dom.create`.
1042
+ * Returns the inserted node, or `null` if the reference element has no parent.
1043
+ *
1044
+ * @example
1045
+ * dom.after(el, '<span>New</span>')
1046
+ * dom.after(el, document.createElement('div'))
1047
+ *
1048
+ * @param {Element} el - Reference element
1049
+ * @param {Element|string} newEl - Element or HTML string to insert
1050
+ * @returns {Element|DocumentFragment|null} - The inserted node, or null if insertion failed
615
1051
  */
616
1052
  after: function after(el, newEl) {
617
1053
  if (!el.parentElement) return null;
@@ -621,9 +1057,18 @@ var dom = {
621
1057
  return el.parentElement.insertBefore(newEl, el.nextElementSibling);
622
1058
  },
623
1059
  /**
624
- * @param {Element} el
625
- * @param {Element|string} newEl
626
- * @returns {Element|null}
1060
+ * Inserts a new element or HTML string immediately before a reference element.
1061
+ *
1062
+ * If `newEl` is a string, it is converted to a node using `dom.create`.
1063
+ * Returns the inserted node, or `null` if the reference element has no parent.
1064
+ *
1065
+ * @example
1066
+ * dom.before(el, '<span>New</span>')
1067
+ * dom.before(el, document.createElement('div'))
1068
+ *
1069
+ * @param {Element} el - Reference element
1070
+ * @param {Element|string} newEl - Element or HTML string to insert
1071
+ * @returns {Element|DocumentFragment|null} - The inserted node, or null if insertion failed
627
1072
  */
628
1073
  before: function before(el, newEl) {
629
1074
  if (!el.parentElement) return null;
@@ -633,8 +1078,13 @@ var dom = {
633
1078
  return el.parentElement.insertBefore(newEl, el);
634
1079
  },
635
1080
  /**
636
- * @param {Element} el
637
- * @returns {Element}
1081
+ * Removes all child nodes from an element.
1082
+ *
1083
+ * @example
1084
+ * dom.empty(el) // el now has no children
1085
+ *
1086
+ * @param {Element} el - Element to clear
1087
+ * @returns {Element} - The element
638
1088
  */
639
1089
  empty: function empty(el) {
640
1090
  while (el.firstChild) {
@@ -643,23 +1093,45 @@ var dom = {
643
1093
  return el;
644
1094
  },
645
1095
  /**
646
- * @param {Element|NodeList|Array<Element>} el
647
- * @param {string|Element} selector
648
- * @return {Array<Element>}
1096
+ * Filters a collection of elements by excluding those matching a selector
1097
+ * or a specific element.
1098
+ *
1099
+ * Accepts a single Element, a NodeList, or an array of Elements.
1100
+ * If `selector` is a string, elements matching it are excluded.
1101
+ * If `selector` is an Element, that exact element is excluded.
1102
+ *
1103
+ * @example
1104
+ * const items = document.querySelectorAll('.item')
1105
+ *
1106
+ * dom.not(items, '.active') // all .item elements except those with .active
1107
+ * dom.not(items, someElement) // all elements except that specific one
1108
+ *
1109
+ * dom.not(el, '.hidden') // returns [] if el matches, otherwise [el]
1110
+ *
1111
+ * @param {Element|NodeList|Element[]} el - Element(s) to filter
1112
+ * @param {string|Element} selector - CSS selector or element to exclude
1113
+ * @returns {Element[]} - Filtered array of elements
649
1114
  */
650
1115
  not: function not(el, selector) {
651
1116
  var elements = el instanceof Element ? [el] : Array.from(el);
652
1117
  var selectorIsString = isString(selector);
653
1118
  return elements.filter(function (e) {
654
- // if (!(e instanceof Element)) return false
655
-
656
1119
  return selectorIsString ? !e.matches(selector) : e !== selector;
657
1120
  });
658
1121
  },
659
1122
  /**
660
- * @param {Element} elem1
661
- * @param {Element} elem2
662
- * @returns {boolean}
1123
+ * Checks whether two elements visually collide (overlap) in the viewport.
1124
+ *
1125
+ * Returns `true` if their rectangles intersect.
1126
+ *
1127
+ * @example
1128
+ * if (dom.collide(box1, box2)) {
1129
+ * console.log('Elements overlap')
1130
+ * }
1131
+ *
1132
+ * @param {Element} elem1 - First element
1133
+ * @param {Element} elem2 - Second element
1134
+ * @returns {boolean} - `true` if the elements overlap, otherwise false
663
1135
  */
664
1136
  collide: function collide(elem1, elem2) {
665
1137
  var rect1 = elem1.getBoundingClientRect();
@@ -667,25 +1139,49 @@ var dom = {
667
1139
  return rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y;
668
1140
  },
669
1141
  /**
670
- * @param {Element} el
671
- * @param {string|Element} selector
1142
+ * Checks whether an element matches a selector or is equal to another element.
1143
+ *
1144
+ * If `selector` is a string, uses `Element.matches()`.
1145
+ * If `selector` is an Element, checks strict equality.
1146
+ *
1147
+ * @example
1148
+ * dom.matches(el, '.active') // true if el has class "active"
1149
+ * dom.matches(el, otherEl) // true if el === otherEl
1150
+ *
1151
+ * @param {Element} el - Element to test
1152
+ * @param {string|Element} selector - CSS selector or element to compare
1153
+ * @returns {boolean} - `true` if the element matches, otherwise false
672
1154
  */
673
1155
  matches: function matches(el, selector) {
674
1156
  if (!el) return false;
675
1157
  return selector instanceof Element ? selector === el : el.matches(selector);
676
1158
  },
677
1159
  /**
678
- * @param {Element} el
679
- * @param {Element} child
680
- * @param {Element} oldChild
1160
+ * Replaces a child node of an element with another node.
1161
+ *
1162
+ * @example
1163
+ * dom.replaceChild(parent, newEl, oldEl)
1164
+ *
1165
+ * @param {Element} el - Parent element
1166
+ * @param {Element} child - New child node
1167
+ * @param {Element} oldChild - Existing child node to replace
1168
+ * @returns {Element} - The replaced node
681
1169
  */
682
1170
  replaceChild: function replaceChild(el, child, oldChild) {
683
1171
  return el.replaceChild(child, oldChild);
684
1172
  },
685
1173
  /**
686
- * @param {Element} el
687
- * @param {NodeList|Array<Element>|string[]} children
688
- * @returns {Element}
1174
+ * Replaces all children of an element with new nodes or HTML strings.
1175
+ *
1176
+ * Strings are converted to DOM nodes using `dom.create`.
1177
+ *
1178
+ * @example
1179
+ * dom.replaceChildren(el, '<span>A</span>', '<span>B</span>')
1180
+ * dom.replaceChildren(el, document.createElement('div'))
1181
+ *
1182
+ * @param {Element} el - Target element
1183
+ * @param {...(Element|string)} children - New children to insert
1184
+ * @returns {Element} - The element
689
1185
  */
690
1186
  replaceChildren: function replaceChildren(el) {
691
1187
  var _this6 = this;
@@ -703,8 +1199,19 @@ var dom = {
703
1199
  return el;
704
1200
  },
705
1201
  /**
706
- * @param {Element|Document|Window} el
707
- * @returns {{top: number, left: number}}
1202
+ * Returns the page offset of an element, document, or window.
1203
+ *
1204
+ * - For `window`, returns the current scroll position.
1205
+ * - For `document`, returns the scroll position of the root element.
1206
+ * - For an element, returns its position relative to the top-left of the page.
1207
+ *
1208
+ * @example
1209
+ * dom.offset(window) // { top: scrollY, left: scrollX }
1210
+ * dom.offset(document) // { top: scrollTop, left: scrollLeft }
1211
+ * dom.offset(el) // position of el relative to the page
1212
+ *
1213
+ * @param {Element|Document|Window} el - Target element, document, or window
1214
+ * @returns {{top: number, left: number}} - The offset relative to the page
708
1215
  */
709
1216
  offset: function offset(el) {
710
1217
  if (isWindow(el)) {
@@ -726,8 +1233,24 @@ var dom = {
726
1233
  };
727
1234
  },
728
1235
  /**
729
- * @param {Node} el
730
- * @returns {boolean}
1236
+ * Checks whether a node is inside an editable context.
1237
+ *
1238
+ * Returns true if the element itself, or one of its ancestors,
1239
+ * is an editable form control or has `contenteditable="true"`.
1240
+ * Text nodes are automatically resolved to their parent element.
1241
+ *
1242
+ * @example
1243
+ * dom.isEditable(inputEl) // true
1244
+ * dom.isEditable(textareaEl) // true
1245
+ * dom.isEditable(selectEl) // true
1246
+ *
1247
+ * dom.isEditable(divWithContentEditable) // true
1248
+ * dom.isEditable(spanInsideContentEditable) // true
1249
+ *
1250
+ * dom.isEditable(document.body) // false
1251
+ *
1252
+ * @param {Node} el - Node to test
1253
+ * @returns {boolean} True if the node is in an editable context
731
1254
  */
732
1255
  isEditable: function isEditable(el) {
733
1256
  var _el;
@@ -736,8 +1259,16 @@ var dom = {
736
1259
  return inArray(el.tagName, ['INPUT', 'TEXTAREA', 'SELECT']) || el.isContentEditable || !!this.closest(el, '[contenteditable="true"]');
737
1260
  },
738
1261
  /**
739
- * @param {Node} node
740
- * @returns {boolean}
1262
+ * Checks whether a node is currently attached to the main document.
1263
+ *
1264
+ * @example
1265
+ * dom.isInDOM(el) // true if element is in the document
1266
+ *
1267
+ * const frag = document.createDocumentFragment()
1268
+ * dom.isInDOM(frag) // false
1269
+ *
1270
+ * @param {Node} node - Node to test
1271
+ * @returns {boolean} - `true` if the node is attached to the document
741
1272
  */
742
1273
  isInDOM: function isInDOM(node) {
743
1274
  if (!(node instanceof Node)) return false;
@@ -746,7 +1277,82 @@ var dom = {
746
1277
  });
747
1278
  return root === document;
748
1279
  },
1280
+ /**
1281
+ * Attaches one or more event listeners to an element, document, or window.
1282
+ *
1283
+ * Supports:
1284
+ * - Multiple events (space-separated)
1285
+ * - Event namespaces (e.g. "click.menu")
1286
+ * - Event delegation via CSS selector
1287
+ * - Custom events
1288
+ *
1289
+ * Custom Events :
1290
+ *
1291
+ * The following custom events are available:
1292
+ *
1293
+ * `longtap`
1294
+ * Fired when the user presses and holds on an element for a short duration
1295
+ * (useful for touch interfaces and long-press interactions).
1296
+ *
1297
+ * `dbltap`
1298
+ * Fired when the user performs a quick double tap on touch devices.
1299
+ *
1300
+ * These events are automatically enabled the first time they are used.
1301
+ *
1302
+ * @example
1303
+ * // Simple binding
1304
+ * dom.on(button, 'click', (ev) => {})
1305
+ *
1306
+ * // Multiple events
1307
+ * dom.on(input, 'focus blur', handler)
1308
+ *
1309
+ * // Namespaced event
1310
+ * dom.on(button, 'click.menu', handler)
1311
+ *
1312
+ * // Delegated event
1313
+ * dom.on(list, 'click', '.item', (ev) => {})
1314
+ *
1315
+ * // With options
1316
+ * dom.on(window, 'scroll', handler, { passive: true })
1317
+ *
1318
+ * @example
1319
+ * dom.on(el, 'longtap', handler)
1320
+ * dom.on(el, 'dbltap', handler)
1321
+ *
1322
+ * @param {Element|Document|Window} el - Element to bind the listener to
1323
+ * @param {string} events - Space-separated list of events (optionally namespaced)
1324
+ * @param {string|function} [selector] - CSS selector for delegation, or handler if no delegation
1325
+ * @param {function|AddEventListenerOptions|boolean} [handler] - Event handler
1326
+ * @param {AddEventListenerOptions|boolean} [options] - Native event listener options
1327
+ * @returns {Element} - The element
1328
+ */
749
1329
  on: on,
1330
+ /**
1331
+ * Removes event listeners previously attached with `dom.on`.
1332
+ *
1333
+ * You can remove listeners by:
1334
+ * - Event type
1335
+ * - Namespace
1336
+ * - Handler reference
1337
+ * - Selector (for delegated events)
1338
+ * - Options
1339
+ *
1340
+ * If no event is provided, all listeners on the element are removed.
1341
+ *
1342
+ * @example
1343
+ * dom.off(button, 'click')
1344
+ * dom.off(button, 'click.menu')
1345
+ * dom.off(button, 'click', handler)
1346
+ * dom.off(list, 'click', '.item', handler)
1347
+ * dom.off(button) // removes all listeners
1348
+ *
1349
+ * @param {Element|Document|Window} el - Element to unbind listeners from
1350
+ * @param {string} [events] - Space-separated events (optionally namespaced)
1351
+ * @param {string|function} [selector] - Delegation selector or handler
1352
+ * @param {function|AddEventListenerOptions|boolean} [handler] - Specific handler to remove
1353
+ * @param {AddEventListenerOptions|boolean} [options] - Listener options to match
1354
+ * @returns {Element} - The element
1355
+ */
750
1356
  off: off
751
1357
  };
752
1358
 
@@ -756,4 +1362,10 @@ if ('test' === process.env.NODE_ENV) {
756
1362
  __resetCustomEventsForTests();
757
1363
  };
758
1364
  }
759
- export default dom;
1365
+ export default dom;
1366
+
1367
+ /* istanbul ignore next */
1368
+ if ('undefined' !== typeof window) {
1369
+ window.webf = window.webf || {};
1370
+ window.webf.dom = dom;
1371
+ }