tiny-essentials 1.19.3 → 1.20.1

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 (57) hide show
  1. package/dist/v1/TinyBasicsEs.min.js +1 -1
  2. package/dist/v1/TinyDragger.min.js +1 -1
  3. package/dist/v1/TinyEssentials.min.js +1 -1
  4. package/dist/v1/TinyHtml.min.js +1 -1
  5. package/dist/v1/TinyIframeEvents.min.js +1 -0
  6. package/dist/v1/TinyNewWinEvents.min.js +1 -0
  7. package/dist/v1/TinySmartScroller.min.js +1 -1
  8. package/dist/v1/TinyUploadClicker.min.js +1 -1
  9. package/dist/v1/build/TinyIframeEvents.cjs +7 -0
  10. package/dist/v1/build/TinyIframeEvents.d.mts +3 -0
  11. package/dist/v1/build/TinyIframeEvents.mjs +2 -0
  12. package/dist/v1/build/TinyNewWinEvents.cjs +7 -0
  13. package/dist/v1/build/TinyNewWinEvents.d.mts +3 -0
  14. package/dist/v1/build/TinyNewWinEvents.mjs +2 -0
  15. package/dist/v1/index.cjs +4 -0
  16. package/dist/v1/index.d.mts +3 -1
  17. package/dist/v1/index.mjs +3 -1
  18. package/dist/v1/libs/TinyDragger.cjs +1 -1
  19. package/dist/v1/libs/TinyDragger.mjs +1 -1
  20. package/dist/v1/libs/TinyHtml.cjs +292 -103
  21. package/dist/v1/libs/TinyHtml.d.mts +142 -39
  22. package/dist/v1/libs/TinyHtml.mjs +266 -94
  23. package/dist/v1/libs/TinyIframeEvents.cjs +410 -0
  24. package/dist/v1/libs/TinyIframeEvents.d.mts +193 -0
  25. package/dist/v1/libs/TinyIframeEvents.mjs +348 -0
  26. package/dist/v1/libs/TinyNewWinEvents.cjs +488 -0
  27. package/dist/v1/libs/TinyNewWinEvents.d.mts +241 -0
  28. package/dist/v1/libs/TinyNewWinEvents.mjs +437 -0
  29. package/docs/v1/README.md +2 -0
  30. package/docs/v1/libs/TinyHtml.md +128 -6
  31. package/docs/v1/libs/TinyIframeEvents.md +149 -0
  32. package/docs/v1/libs/TinyNewWinEvents.md +186 -0
  33. package/docs/v1/libs/TinyNotifyCenter.md +1 -1
  34. package/package.json +1 -1
  35. package/dist/v1/ColorSafeStringify.js +0 -235
  36. package/dist/v1/TinyAfterScrollWatcher.js +0 -219
  37. package/dist/v1/TinyBasicsEs.js +0 -9334
  38. package/dist/v1/TinyClipboard.js +0 -459
  39. package/dist/v1/TinyColorConverter.js +0 -617
  40. package/dist/v1/TinyDomReadyManager.js +0 -213
  41. package/dist/v1/TinyDragDropDetector.js +0 -307
  42. package/dist/v1/TinyDragger.js +0 -6569
  43. package/dist/v1/TinyEssentials.js +0 -19893
  44. package/dist/v1/TinyEvents.js +0 -402
  45. package/dist/v1/TinyHtml.js +0 -5545
  46. package/dist/v1/TinyLevelUp.js +0 -291
  47. package/dist/v1/TinyLocalStorage.js +0 -1440
  48. package/dist/v1/TinyNotifications.js +0 -408
  49. package/dist/v1/TinyNotifyCenter.js +0 -493
  50. package/dist/v1/TinyPromiseQueue.js +0 -299
  51. package/dist/v1/TinyRateLimiter.js +0 -611
  52. package/dist/v1/TinySmartScroller.js +0 -7039
  53. package/dist/v1/TinyTextRangeEditor.js +0 -497
  54. package/dist/v1/TinyTimeout.js +0 -233
  55. package/dist/v1/TinyToastNotify.js +0 -441
  56. package/dist/v1/TinyUploadClicker.js +0 -13456
  57. package/dist/v1/UltraRandomMsgGen.js +0 -995
@@ -240,11 +240,39 @@ class TinyHtml {
240
240
 
241
241
  static Utils = { ...collision };
242
242
 
243
+ /**
244
+ * Creates a new TinyHtml element from a tag name and optional attributes.
245
+ *
246
+ * You can alias this method for convenience:
247
+ * ```js
248
+ * const createElement = TinyHtml.createFrom;
249
+ * const myDiv = createElement('div', { class: 'box' });
250
+ * ```
251
+ *
252
+ * @param {string} tagName - The HTML tag name (e.g., 'div', 'span', 'button').
253
+ * @param {Record<string, string|null>} [attrs] - Optional key-value pairs representing HTML attributes.
254
+ * If the value is `null`, the attribute will still be set with an empty value.
255
+ * @returns {TinyHtml} - A new instance of TinyHtml representing the created element.
256
+ * @throws {TypeError} - If `tagName` is not a string, or `attrs` is not a plain object when defined.
257
+ */
258
+ static createFrom(tagName, attrs) {
259
+ if (typeof tagName !== 'string') throw new TypeError('The "tagName" must be a string.');
260
+ if (typeof attrs !== 'undefined' && typeof attrs !== 'object')
261
+ throw new TypeError('The "attrs" must be a object.');
262
+ const elem = TinyHtml.createElement(tagName);
263
+ if (typeof attrs === 'object') {
264
+ for (const attrName in attrs) {
265
+ elem.setAttr(attrName, attrs[attrName]);
266
+ }
267
+ }
268
+ return elem;
269
+ }
270
+
243
271
  /**
244
272
  * Creates a new DOM element with the specified tag name and options, then wraps it in a TinyHtml instance.
245
273
  *
246
274
  * @param {string} tagName - The tag name of the element to create (e.g., 'div', 'span').
247
- * @param {ElementCreationOptions} ops - Optional settings for creating the element.
275
+ * @param {ElementCreationOptions} [ops] - Optional settings for creating the element.
248
276
  * @returns {TinyHtml} A TinyHtml instance wrapping the newly created DOM element.
249
277
  * @throws {TypeError} If tagName is not a string or ops is not an object.
250
278
  */
@@ -290,7 +318,8 @@ class TinyHtml {
290
318
  }
291
319
 
292
320
  template.innerHTML = htmlString;
293
- if (!(template.content.firstChild instanceof Element)) throw new Error('');
321
+ if (!(template.content.firstChild instanceof Element))
322
+ throw new Error('The HTML string must contain a valid HTML element.');
294
323
  return new TinyHtml(template.content.firstChild);
295
324
  }
296
325
 
@@ -322,18 +351,17 @@ class TinyHtml {
322
351
  *
323
352
  * @param {string} selector - A valid CSS selector string.
324
353
  * @param {Document|Element} elem - Target element.
325
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the matched elements.
354
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the matched elements.
326
355
  */
327
356
  static queryAll(selector, elem = document) {
328
- const newEls = elem.querySelectorAll(selector);
329
- return TinyHtml.toTinyElm([...newEls]);
357
+ return new TinyHtml(elem.querySelectorAll(selector));
330
358
  }
331
359
 
332
360
  /**
333
361
  * Queries the element for all elements matching the CSS selector and wraps them in TinyHtml instances.
334
362
  *
335
363
  * @param {string} selector - A valid CSS selector string.
336
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the matched elements.
364
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the matched elements.
337
365
  */
338
366
  querySelectorAll(selector) {
339
367
  return TinyHtml.queryAll(selector, TinyHtml._preElem(this, 'queryAll'));
@@ -356,18 +384,17 @@ class TinyHtml {
356
384
  *
357
385
  * @param {string} selector - The class name to search for.
358
386
  * @param {Document|Element} elem - Target element.
359
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the found elements.
387
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
360
388
  */
361
389
  static getByClassName(selector, elem = document) {
362
- const newEls = elem.getElementsByClassName(selector);
363
- return TinyHtml.toTinyElm([...newEls]);
390
+ return new TinyHtml(elem.getElementsByClassName(selector));
364
391
  }
365
392
 
366
393
  /**
367
394
  * Retrieves all elements with the specified class name and wraps them in TinyHtml instances.
368
395
  *
369
396
  * @param {string} selector - The class name to search for.
370
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the found elements.
397
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
371
398
  */
372
399
  getElementsByClassName(selector) {
373
400
  return TinyHtml.getByClassName(selector, TinyHtml._preElem(this, 'getByClassName'));
@@ -377,11 +404,10 @@ class TinyHtml {
377
404
  * Retrieves all elements with the specified name attribute and wraps them in TinyHtml instances.
378
405
  *
379
406
  * @param {string} selector - The name attribute to search for.
380
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the found elements.
407
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
381
408
  */
382
409
  static getByName(selector) {
383
- const newEls = document.getElementsByName(selector);
384
- return TinyHtml.toTinyElm([...newEls]);
410
+ return new TinyHtml(document.getElementsByName(selector));
385
411
  }
386
412
 
387
413
  /**
@@ -391,11 +417,10 @@ class TinyHtml {
391
417
  * @param {string} localName - The local name (tag) of the elements to search for.
392
418
  * @param {string|null} [namespaceURI='http://www.w3.org/1999/xhtml'] - The namespace URI to search within.
393
419
  * @param {Document|Element} elem - Target element.
394
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the found elements.
420
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
395
421
  */
396
422
  static getByTagNameNS(localName, namespaceURI = 'http://www.w3.org/1999/xhtml', elem = document) {
397
- const newEls = elem.getElementsByTagNameNS(namespaceURI, localName);
398
- return TinyHtml.toTinyElm([...newEls]);
423
+ return new TinyHtml(elem.getElementsByTagNameNS(namespaceURI, localName));
399
424
  }
400
425
 
401
426
  /**
@@ -404,7 +429,7 @@ class TinyHtml {
404
429
  *
405
430
  * @param {string} localName - The local name (tag) of the elements to search for.
406
431
  * @param {string|null} [namespaceURI='http://www.w3.org/1999/xhtml'] - The namespace URI to search within.
407
- * @returns {TinyHtml[]} An array of TinyHtml instances wrapping the found elements.
432
+ * @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
408
433
  */
409
434
  getElementsByTagNameNS(localName, namespaceURI = 'http://www.w3.org/1999/xhtml') {
410
435
  return TinyHtml.getByTagNameNS(
@@ -419,85 +444,156 @@ class TinyHtml {
419
444
  /**
420
445
  * Returns the current target held by this instance.
421
446
  *
447
+ * @param {number} index - The index of the element to retrieve.
422
448
  * @returns {ConstructorElValues} - The instance's target element.
423
449
  */
424
- get() {
425
- return this.#el;
450
+ get(index) {
451
+ if (typeof index !== 'number') throw new TypeError('The index must be a number.');
452
+ if (!this.#el[index]) throw new Error(`No element found at index ${index}.`);
453
+ return this.#el[index];
454
+ }
455
+
456
+ /**
457
+ * Extracts a single DOM element from the internal list at the specified index.
458
+ *
459
+ * @param {number} index - The index of the element to extract.
460
+ * @returns {TinyHtml} A new TinyHtml instance wrapping the extracted element.
461
+ */
462
+ extract(index) {
463
+ if (typeof index !== 'number') throw new TypeError('The index must be a number.');
464
+ if (!this.#el[index]) throw new Error(`Cannot extract: no element exists at index ${index}.`);
465
+ return new TinyHtml(this.#el[index]);
466
+ }
467
+
468
+ /**
469
+ * Checks whether the element exists at the given index.
470
+ *
471
+ * @param {number} index - The index to check.
472
+ * @returns {boolean} - True if the element exists; otherwise, false.
473
+ */
474
+ exists(index) {
475
+ if (typeof index !== 'number') throw new TypeError('The index must be a number.');
476
+ if (!this.#el[index]) return false;
477
+ return true;
478
+ }
479
+
480
+ /**
481
+ * Returns the current targets held by this instance.
482
+ *
483
+ * @returns {ConstructorElValues[]} - The instance's targets element.
484
+ */
485
+ getAll() {
486
+ return [...this.#el];
426
487
  }
427
488
 
428
489
  /**
429
490
  * Returns the current Element held by this instance.
430
491
  *
431
492
  * @param {string} where - The method name or context calling this.
493
+ * @param {number} index - The index of the element to retrieve.
432
494
  * @returns {ConstructorElValues} - The instance's element.
433
495
  * @readonly
434
496
  */
435
- _getElement(where) {
497
+ _getElement(where, index) {
436
498
  if (
437
- !(this.#el instanceof Element) &&
438
- !(this.#el instanceof Window) &&
439
- !(this.#el instanceof Document)
499
+ !(this.#el[index] instanceof Element) &&
500
+ !(this.#el[index] instanceof Window) &&
501
+ !(this.#el[index] instanceof Document)
440
502
  )
441
503
  throw new Error(`[TinyHtml] Invalid Element in ${where}().`);
442
- return this.#el;
504
+ return this.#el[index];
505
+ }
506
+
507
+ /**
508
+ * Returns the current Elements held by this instance.
509
+ *
510
+ * @param {string} where - The method name or context calling this.
511
+ * @returns {ConstructorElValues[]} - The instance's elements.
512
+ * @readonly
513
+ */
514
+ _getElements(where) {
515
+ if (
516
+ !this.#el.every(
517
+ (el) => el instanceof Element || el instanceof Window || el instanceof Document,
518
+ )
519
+ )
520
+ throw new Error(`[TinyHtml] Invalid Element in ${where}().`);
521
+ return [...this.#el];
443
522
  }
444
523
 
445
524
  //////////////////////////////////////////////////////
446
525
 
447
526
  /**
448
- * @param {TinyElement|EventTarget|null|(TinyElement|EventTarget|null)[]} elems
449
- * @param {string} where
450
- * @param {any[]} TheTinyElements
451
- * @param {string[]} elemName
452
- * @returns {any[]}
527
+ * Prepares and validates multiple elements against allowed types.
528
+ *
529
+ * @param {TinyElement | EventTarget | null | (TinyElement | EventTarget | null)[]} elems - The input elements to validate.
530
+ * @param {string} where - The method name or context calling this.
531
+ * @param {any[]} TheTinyElements - The list of allowed constructors (e.g., Element, Document).
532
+ * @param {string[]} elemName - The list of expected element names for error reporting.
533
+ * @returns {any[]} - A flat array of validated elements.
534
+ * @throws {Error} - If any element is not an instance of one of the allowed types.
453
535
  * @readonly
454
536
  */
455
537
  static _preElemsTemplate(elems, where, TheTinyElements, elemName) {
456
538
  /** @param {(TinyElement|EventTarget|null)[]} item */
457
- const checkElement = (item) =>
458
- item.map((elem) => {
459
- const result = elem instanceof TinyHtml ? elem._getElement(where) : elem;
460
- let allowed = false;
461
- for (const TheTinyElement of TheTinyElements) {
462
- if (result instanceof TheTinyElement) {
463
- allowed = true;
464
- break;
539
+ const checkElement = (item) => {
540
+ /** @type {any[]} */
541
+ const results = [];
542
+ item.map((elem) =>
543
+ (elem instanceof TinyHtml ? elem._getElements(where) : [elem]).map((result) => {
544
+ let allowed = false;
545
+ for (const TheTinyElement of TheTinyElements) {
546
+ if (result instanceof TheTinyElement) {
547
+ allowed = true;
548
+ break;
549
+ }
465
550
  }
466
- }
467
- if (!allowed)
468
- throw new Error(
469
- `[TinyHtml] Invalid element of the list "${elemName.join(',')}" in ${where}().`,
470
- );
471
- return result;
472
- });
551
+ if (!allowed)
552
+ throw new Error(
553
+ `[TinyHtml] Invalid element of the list "${elemName.join(',')}" in ${where}().`,
554
+ );
555
+ results.push(result);
556
+ return result;
557
+ }),
558
+ );
559
+ return results;
560
+ };
473
561
  if (!Array.isArray(elems)) return checkElement([elems]);
474
562
  return checkElement(elems);
475
563
  }
476
564
 
477
565
  /**
478
- * @param {TinyElement|EventTarget|null|(TinyElement|EventTarget|null)[]} elems
479
- * @param {string} where
480
- * @param {any[]} TheTinyElements
481
- * @param {string[]} elemName
482
- * @param {boolean} [canNull=false]
483
- * @returns {any}
566
+ * Prepares and validates a single element against allowed types.
567
+ *
568
+ * @param {TinyElement | EventTarget | null | (TinyElement | EventTarget | null)[]} elems - The input element or list to validate.
569
+ * @param {string} where - The method name or context calling this.
570
+ * @param {any[]} TheTinyElements - The list of allowed constructors (e.g., Element, Document).
571
+ * @param {string[]} elemName - The list of expected element names for error reporting.
572
+ * @param {boolean} [canNull=false] - Whether `null` is allowed as a valid value.
573
+ * @returns {any} - The validated element or `null` if allowed.
574
+ * @throws {Error} - If the element is not valid or if multiple elements are provided.
484
575
  * @readonly
485
576
  */
486
577
  static _preElemTemplate(elems, where, TheTinyElements, elemName, canNull = false) {
487
578
  /** @param {(TinyElement|EventTarget|null)[]} item */
488
579
  const checkElement = (item) => {
489
580
  const elem = item[0];
490
- let result = elem instanceof TinyHtml ? elem._getElement(where) : elem;
581
+ const result = elem instanceof TinyHtml ? elem._getElements(where) : [elem];
582
+ if (result.length > 1)
583
+ throw new Error(
584
+ `[TinyHtml] Invalid element amount in ${where}() (Received ${result.length}/1).`,
585
+ );
586
+
491
587
  let allowed = false;
492
588
  for (const TheTinyElement of TheTinyElements) {
493
- if (result instanceof TheTinyElement) {
589
+ if (result[0] instanceof TheTinyElement) {
494
590
  allowed = true;
495
591
  break;
496
592
  }
497
593
  }
498
594
 
499
- if (canNull && (result === null || typeof result === 'undefined')) {
500
- result = null;
595
+ if (canNull && (result[0] === null || typeof result[0] === 'undefined')) {
596
+ result[0] = null;
501
597
  allowed = true;
502
598
  }
503
599
 
@@ -505,7 +601,7 @@ class TinyHtml {
505
601
  throw new Error(
506
602
  `[TinyHtml] Invalid element of the list "${elemName.join(',')}" in ${where}().`,
507
603
  );
508
- return result;
604
+ return result[0];
509
605
  };
510
606
  if (!Array.isArray(elems)) return checkElement([elems]);
511
607
  if (elems.length > 1)
@@ -798,13 +894,16 @@ class TinyHtml {
798
894
  */
799
895
  static fromTinyElm(elems) {
800
896
  /** @param {TinyElement[]} item */
801
- const checkElement = (item) =>
802
- item.map(
803
- (elem) =>
804
- /** @type {Element} */ (
805
- elem instanceof TinyHtml ? elem._getElement('fromTinyElm') : elem
806
- ),
897
+ const checkElement = (item) => {
898
+ /** @type {Element[]} */
899
+ const result = [];
900
+ item.map((elem) =>
901
+ /** @type {Element[]} */ (
902
+ elem instanceof TinyHtml ? elem._getElements('fromTinyElm') : [elem]
903
+ ).map((elem) => result.push(elem)),
807
904
  );
905
+ return result;
906
+ };
808
907
  if (!Array.isArray(elems)) return checkElement([elems]);
809
908
  return checkElement(elems);
810
909
  }
@@ -1648,7 +1747,8 @@ class TinyHtml {
1648
1747
  const elem = TinyHtml._preNodeElem(el, 'insertBefore');
1649
1748
  const targ = TinyHtml._preNodeElem(target, 'insertBefore');
1650
1749
  const childNode = TinyHtml._preNodeElemWithNull(child, 'insertBefore');
1651
- if (!targ.parentNode) throw new Error('');
1750
+ if (!targ.parentNode)
1751
+ throw new Error('The target element has no parent node to insert before.');
1652
1752
  targ.parentNode.insertBefore(elem, childNode || targ);
1653
1753
  return el;
1654
1754
  }
@@ -1676,7 +1776,7 @@ class TinyHtml {
1676
1776
  const elem = TinyHtml._preNodeElem(el, 'insertAfter');
1677
1777
  const targ = TinyHtml._preNodeElem(target, 'insertBefore');
1678
1778
  const childNode = TinyHtml._preNodeElemWithNull(child, 'insertBefore');
1679
- if (!targ.parentNode) throw new Error('');
1779
+ if (!targ.parentNode) throw new Error('The target element has no parent node to insert after.');
1680
1780
  targ.parentNode.insertBefore(elem, childNode || targ.nextSibling);
1681
1781
  return el;
1682
1782
  }
@@ -1728,28 +1828,48 @@ class TinyHtml {
1728
1828
 
1729
1829
  /**
1730
1830
  * The target HTML element for instance-level operations.
1731
- * @type {ConstructorElValues}
1831
+ * @type {ConstructorElValues[]}
1732
1832
  */
1733
1833
  #el;
1734
1834
 
1735
1835
  /**
1736
1836
  * Creates an instance of TinyHtml for a specific Element.
1737
1837
  * Useful when you want to operate repeatedly on the same element using instance methods.
1738
- * @param {ConstructorElValues} el - The element to wrap and manipulate.
1838
+ * @param {ConstructorElValues|ConstructorElValues[]|NodeListOf<Element>|HTMLCollectionOf<Element>|NodeListOf<HTMLElement>} el - The element to wrap and manipulate.
1739
1839
  */
1740
1840
  constructor(el) {
1741
1841
  if (el instanceof TinyHtml)
1742
1842
  throw new Error(
1743
1843
  `[TinyHtml] You are trying to put a TinyHtml inside another TinyHtml in constructor.`,
1744
1844
  );
1745
- if (
1746
- !(el instanceof Element) &&
1747
- !(el instanceof Window) &&
1748
- !(el instanceof Document) &&
1749
- !(el instanceof Text)
1750
- )
1751
- throw new Error(`[TinyHtml] Invalid Target in constructor.`);
1752
- this.#el = el;
1845
+
1846
+ /** @param {any[]} els */
1847
+ const elCheck = (els) => {
1848
+ if (
1849
+ !els.every(
1850
+ (el) =>
1851
+ el instanceof Element ||
1852
+ el instanceof Window ||
1853
+ el instanceof Document ||
1854
+ el instanceof Text,
1855
+ )
1856
+ )
1857
+ throw new Error(`[TinyHtml] Invalid Target in constructor.`);
1858
+ };
1859
+
1860
+ if (Array.isArray(el)) {
1861
+ elCheck(el);
1862
+ this.#el = el;
1863
+ } else if (el instanceof NodeList || el instanceof HTMLCollection) {
1864
+ const els = [...el];
1865
+ elCheck(els);
1866
+ this.#el = els;
1867
+ } else {
1868
+ const els = [el];
1869
+ elCheck(els);
1870
+ // @ts-ignore
1871
+ this.#el = els;
1872
+ }
1753
1873
  }
1754
1874
 
1755
1875
  /**
@@ -2153,7 +2273,13 @@ class TinyHtml {
2153
2273
  msTransition: '-ms-transition',
2154
2274
  };
2155
2275
 
2156
- /** @type {Record<string | symbol, string>} */
2276
+ /**
2277
+ * Public proxy to manage camelCase ➝ kebab-case CSS property aliasing.
2278
+ *
2279
+ * Modifying this object ensures that the reverse mapping in `cssPropRevAliases` is updated accordingly.
2280
+ *
2281
+ * @type {Record<string | symbol, string>}
2282
+ */
2157
2283
  static cssPropAliases = new Proxy(TinyHtml.#cssPropAliases, {
2158
2284
  set(target, camelCaseKey, kebabValue) {
2159
2285
  target[camelCaseKey] = kebabValue;
@@ -2163,7 +2289,13 @@ class TinyHtml {
2163
2289
  },
2164
2290
  });
2165
2291
 
2166
- /** @type {Record<string | symbol, string>} */
2292
+ /**
2293
+ * Reverse map of `cssPropAliases`, mapping kebab-case back to camelCase CSS property names.
2294
+ *
2295
+ * This enables consistent bidirectional lookups of style properties.
2296
+ *
2297
+ * @type {Record<string | symbol, string>}
2298
+ */
2167
2299
  static cssPropRevAliases = Object.fromEntries(
2168
2300
  Object.entries(TinyHtml.#cssPropAliases).map(([camel, kebab]) => [kebab, camel]),
2169
2301
  );
@@ -3804,7 +3936,7 @@ class TinyHtml {
3804
3936
  static _getValByType(elem, type, where) {
3805
3937
  if (typeof type !== 'string') throw new TypeError('The "type" must be a string.');
3806
3938
  if (typeof where !== 'string') throw new TypeError('The "where" must be a string.');
3807
- if (!(elem instanceof HTMLInputElement))
3939
+ if (!(elem instanceof HTMLInputElement) && !(elem instanceof HTMLTextAreaElement))
3808
3940
  throw new Error(`Provided element is not an HTMLInputElement in ${where}().`);
3809
3941
  if (typeof TinyHtml._valTypes[type] !== 'function')
3810
3942
  throw new Error(`No handler found for type "${type}" in ${where}().`);
@@ -4345,14 +4477,77 @@ class TinyHtml {
4345
4477
  ///////////////////////////////////////////////////////////////
4346
4478
 
4347
4479
  /**
4348
- * Property name normalization similar to jQuery's propFix.
4349
- * @readonly
4480
+ * Internal property name normalization map (similar to jQuery's `propFix`).
4481
+ * Maps attribute-like names to their JavaScript DOM property equivalents.
4482
+ *
4483
+ * Example: `'for'` ➝ `'htmlFor'`, `'class'` ➝ `'className'`.
4484
+ *
4485
+ * ⚠️ Do not modify this object directly. Use `TinyHtml.propFix` to ensure reverse mapping (`attrFix`) remains in sync.
4486
+ *
4487
+ * @type {Record<string | symbol, string>}
4350
4488
  */
4351
- static _propFix = {
4489
+ static #propFix = {
4352
4490
  for: 'htmlFor',
4353
4491
  class: 'className',
4354
4492
  };
4355
4493
 
4494
+ /**
4495
+ * Public proxy for normalized DOM property names.
4496
+ *
4497
+ * Setting a new entry here will also automatically update the reverse map in `TinyHtml.attrFix`.
4498
+ *
4499
+ * @type {Record<string | symbol, string>}
4500
+ */
4501
+ static propFix = new Proxy(TinyHtml.#propFix, {
4502
+ set(target, val1, val2) {
4503
+ target[val1] = val2;
4504
+ // @ts-ignore
4505
+ TinyHtml.attrFix[val2] = val1;
4506
+ return true;
4507
+ },
4508
+ });
4509
+
4510
+ /**
4511
+ * Reverse map of `propFix`, mapping property names back to their attribute equivalents.
4512
+ *
4513
+ * Used when converting DOM property names into HTML attribute names.
4514
+ *
4515
+ * @type {Record<string | symbol, string>}
4516
+ */
4517
+ static attrFix = Object.fromEntries(
4518
+ Object.entries(TinyHtml.#propFix).map(([val1, val2]) => [val2, val1]),
4519
+ );
4520
+
4521
+ /**
4522
+ * Normalizes an attribute name to its corresponding DOM property name.
4523
+ *
4524
+ * Example: `'class'` ➝ `'className'`, `'for'` ➝ `'htmlFor'`.
4525
+ * If the name is not mapped, it returns the original name.
4526
+ *
4527
+ * @param {string} name - The attribute name to normalize.
4528
+ * @returns {string} - The corresponding property name.
4529
+ */
4530
+ static getPropName(name) {
4531
+ // @ts-ignore
4532
+ const propName = typeof TinyHtml.propFix[name] === 'string' ? TinyHtml.propFix[name] : name;
4533
+ return propName;
4534
+ }
4535
+
4536
+ /**
4537
+ * Converts a DOM property name back to its corresponding attribute name.
4538
+ *
4539
+ * Example: `'className'` ➝ `'class'`, `'htmlFor'` ➝ `'for'`.
4540
+ * If the name is not mapped, it returns the original name.
4541
+ *
4542
+ * @param {string} name - The property name to convert.
4543
+ * @returns {string} - The corresponding attribute name.
4544
+ */
4545
+ static getAttrName(name) {
4546
+ // @ts-ignore
4547
+ const propName = typeof TinyHtml.attrFix[name] === 'string' ? TinyHtml.attrFix[name] : name;
4548
+ return propName;
4549
+ }
4550
+
4356
4551
  /**
4357
4552
  * Get an attribute on an element.
4358
4553
  * @param {TinyElement} el
@@ -4362,7 +4557,7 @@ class TinyHtml {
4362
4557
  static attr(el, name) {
4363
4558
  if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
4364
4559
  const elem = TinyHtml._preElem(el, 'attr');
4365
- return elem.getAttribute(name);
4560
+ return elem.getAttribute(TinyHtml.getAttrName(name));
4366
4561
  }
4367
4562
 
4368
4563
  /**
@@ -4386,8 +4581,8 @@ class TinyHtml {
4386
4581
  if (value !== null && typeof value !== 'string')
4387
4582
  throw new TypeError('The "value" must be a string.');
4388
4583
  TinyHtml._preElems(el, 'setAttr').forEach((elem) => {
4389
- if (value === null) elem.removeAttribute(name);
4390
- else elem.setAttribute(name, value);
4584
+ if (value === null) elem.removeAttribute(TinyHtml.getAttrName(name));
4585
+ else elem.setAttribute(TinyHtml.getAttrName(name), value);
4391
4586
  });
4392
4587
  return el;
4393
4588
  }
@@ -4410,7 +4605,9 @@ class TinyHtml {
4410
4605
  */
4411
4606
  static removeAttr(el, name) {
4412
4607
  if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
4413
- TinyHtml._preElems(el, 'removeAttr').forEach((elem) => elem.removeAttribute(name));
4608
+ TinyHtml._preElems(el, 'removeAttr').forEach((elem) =>
4609
+ elem.removeAttribute(TinyHtml.getAttrName(name)),
4610
+ );
4414
4611
  return el;
4415
4612
  }
4416
4613
 
@@ -4432,7 +4629,7 @@ class TinyHtml {
4432
4629
  static hasAttr(el, name) {
4433
4630
  if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
4434
4631
  const elem = TinyHtml._preElem(el, 'hasAttr');
4435
- return elem.hasAttribute(name);
4632
+ return elem.hasAttribute(TinyHtml.getAttrName(name));
4436
4633
  }
4437
4634
 
4438
4635
  /**
@@ -4454,9 +4651,7 @@ class TinyHtml {
4454
4651
  if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
4455
4652
  const elem = TinyHtml._preElem(el, 'hasProp');
4456
4653
  // @ts-ignore
4457
- const propName = TinyHtml._propFix[name] || name;
4458
- // @ts-ignore
4459
- return !!elem[propName];
4654
+ return !!elem[TinyHtml.getPropName(name)];
4460
4655
  }
4461
4656
 
4462
4657
  /**
@@ -4478,9 +4673,7 @@ class TinyHtml {
4478
4673
  if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
4479
4674
  TinyHtml._preElems(el, 'addProp').forEach((elem) => {
4480
4675
  // @ts-ignore
4481
- name = TinyHtml._propFix[name] || name;
4482
- // @ts-ignore
4483
- elem[name] = true;
4676
+ elem[TinyHtml.getPropName(name)] = true;
4484
4677
  });
4485
4678
  return el;
4486
4679
  }
@@ -4504,9 +4697,7 @@ class TinyHtml {
4504
4697
  if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
4505
4698
  TinyHtml._preElems(el, 'removeProp').forEach((elem) => {
4506
4699
  // @ts-ignore
4507
- name = TinyHtml._propFix[name] || name;
4508
- // @ts-ignore
4509
- elem[name] = false;
4700
+ elem[TinyHtml.getPropName(name)] = false;
4510
4701
  });
4511
4702
  return el;
4512
4703
  }
@@ -4532,9 +4723,7 @@ class TinyHtml {
4532
4723
  throw new TypeError('The "force" must be a boolean.');
4533
4724
  TinyHtml._preElems(el, 'toggleProp').forEach((elem) => {
4534
4725
  // @ts-ignore
4535
- const propName = TinyHtml._propFix[name] || name;
4536
- // @ts-ignore
4537
- const shouldEnable = force === undefined ? !elem[propName] : force;
4726
+ const shouldEnable = force === undefined ? !elem[TinyHtml.getPropName(name)] : force;
4538
4727
  // @ts-ignore
4539
4728
  if (shouldEnable) TinyHtml.addProp(elem, name);
4540
4729
  else TinyHtml.removeProp(elem, name);
@@ -4637,14 +4826,14 @@ class TinyHtml {
4637
4826
  }
4638
4827
 
4639
4828
  if (typeof extraRect !== 'object' || extraRect === null || Array.isArray(extraRect))
4640
- throw new Error('');
4829
+ throw new Error('extraRect must be a non-null object.');
4641
4830
  const { height = 0, width = 0, top = 0, bottom = 0, left = 0, right = 0 } = extraRect;
4642
- if (typeof height !== 'number') throw new Error('');
4643
- if (typeof width !== 'number') throw new Error('');
4644
- if (typeof top !== 'number') throw new Error('');
4645
- if (typeof bottom !== 'number') throw new Error('');
4646
- if (typeof left !== 'number') throw new Error('');
4647
- if (typeof right !== 'number') throw new Error('');
4831
+ if (typeof height !== 'number') throw new Error('extraRect.height must be a number.');
4832
+ if (typeof width !== 'number') throw new Error('extraRect.width must be a number.');
4833
+ if (typeof top !== 'number') throw new Error('extraRect.top must be a number.');
4834
+ if (typeof bottom !== 'number') throw new Error('extraRect.bottom must be a number.');
4835
+ if (typeof left !== 'number') throw new Error('extraRect.left must be a number.');
4836
+ if (typeof right !== 'number') throw new Error('extraRect.right must be a number.');
4648
4837
 
4649
4838
  // @ts-ignore
4650
4839
  result.height += height;