tiny-essentials 1.20.2 → 1.21.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 +13 -11
- package/dist/_/numbers.cjs +136 -0
- package/dist/_/numbers.d.mts +24 -0
- package/dist/_/numbers.mjs +102 -0
- package/dist/v1/TinyAdvancedRaffle.min.js +1 -0
- package/dist/v1/TinyArrayPaginator.min.js +1 -0
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyCookieConsent.min.js +1 -0
- package/dist/v1/TinyDayNightCycle.min.js +1 -0
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyGamepad.min.js +1 -0
- package/dist/v1/TinyI18.min.js +1 -0
- package/dist/v1/TinyInventory.min.js +1 -0
- package/dist/v1/TinyInventoryTrader.min.js +1 -0
- package/dist/v1/TinyLocalStorage.min.js +1 -1
- package/dist/v1/TinyRateLimiter.min.js +1 -1
- package/dist/v1/TinySmartScroller.min.js +1 -1
- package/dist/v1/TinyTextarea.min.js +1 -0
- package/dist/v1/TinyToastNotify.min.js +1 -1
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/basics/array.cjs +21 -0
- package/dist/v1/basics/array.d.mts +8 -0
- package/dist/v1/basics/array.mjs +18 -0
- package/dist/v1/basics/index.cjs +2 -8
- package/dist/v1/basics/index.d.mts +3 -8
- package/dist/v1/basics/index.mjs +2 -3
- package/dist/v1/basics/simpleMath.cjs +46 -0
- package/dist/v1/basics/simpleMath.d.mts +27 -0
- package/dist/v1/basics/simpleMath.mjs +42 -0
- package/dist/v1/build/TinyAdvancedRaffle.cjs +7 -0
- package/dist/v1/build/TinyAdvancedRaffle.d.mts +3 -0
- package/dist/v1/build/TinyAdvancedRaffle.mjs +2 -0
- package/dist/v1/build/TinyArrayPaginator.cjs +7 -0
- package/dist/v1/build/TinyArrayPaginator.d.mts +3 -0
- package/dist/v1/build/TinyArrayPaginator.mjs +2 -0
- package/dist/v1/build/TinyCookieConsent.cjs +7 -0
- package/dist/v1/build/TinyCookieConsent.d.mts +3 -0
- package/dist/v1/build/TinyCookieConsent.mjs +2 -0
- package/dist/v1/build/TinyDayNightCycle.cjs +7 -0
- package/dist/v1/build/TinyDayNightCycle.d.mts +3 -0
- package/dist/v1/build/TinyDayNightCycle.mjs +2 -0
- package/dist/v1/build/TinyGamepad.cjs +7 -0
- package/dist/v1/build/TinyGamepad.d.mts +3 -0
- package/dist/v1/build/TinyGamepad.mjs +2 -0
- package/dist/v1/build/TinyI18.cjs +7 -0
- package/dist/v1/build/TinyI18.d.mts +3 -0
- package/dist/v1/build/TinyI18.mjs +2 -0
- package/dist/v1/build/TinyInventory.cjs +7 -0
- package/dist/v1/build/TinyInventory.d.mts +3 -0
- package/dist/v1/build/TinyInventory.mjs +2 -0
- package/dist/v1/build/TinyInventoryTrader.cjs +7 -0
- package/dist/v1/build/TinyInventoryTrader.d.mts +3 -0
- package/dist/v1/build/TinyInventoryTrader.mjs +2 -0
- package/dist/v1/build/TinyTextarea.cjs +7 -0
- package/dist/v1/build/TinyTextarea.d.mts +3 -0
- package/dist/v1/build/TinyTextarea.mjs +2 -0
- package/dist/v1/css/TinyCookieConsent.min.css +1 -0
- package/dist/v1/index.cjs +20 -8
- package/dist/v1/index.d.mts +12 -8
- package/dist/v1/index.mjs +11 -3
- package/dist/v1/libs/TinyAdvancedRaffle.cjs +1654 -0
- package/dist/v1/libs/TinyAdvancedRaffle.d.mts +851 -0
- package/dist/v1/libs/TinyAdvancedRaffle.mjs +1477 -0
- package/dist/v1/libs/TinyArrayPaginator.cjs +132 -0
- package/dist/v1/libs/TinyArrayPaginator.d.mts +78 -0
- package/dist/v1/libs/TinyArrayPaginator.mjs +119 -0
- package/dist/v1/libs/TinyCookieConsent.cjs +278 -0
- package/dist/v1/libs/TinyCookieConsent.d.mts +142 -0
- package/dist/v1/libs/TinyCookieConsent.mjs +248 -0
- package/dist/v1/libs/TinyDayNightCycle.cjs +1389 -0
- package/dist/v1/libs/TinyDayNightCycle.d.mts +673 -0
- package/dist/v1/libs/TinyDayNightCycle.mjs +1232 -0
- package/dist/v1/libs/TinyGamepad.cjs +2690 -0
- package/dist/v1/libs/TinyGamepad.d.mts +1286 -0
- package/dist/v1/libs/TinyGamepad.mjs +2386 -0
- package/dist/v1/libs/TinyHtml.d.mts +2 -2
- package/dist/v1/libs/TinyI18.cjs +946 -0
- package/dist/v1/libs/TinyI18.d.mts +418 -0
- package/dist/v1/libs/TinyI18.mjs +873 -0
- package/dist/v1/libs/TinyInventory.cjs +1788 -0
- package/dist/v1/libs/TinyInventory.d.mts +871 -0
- package/dist/v1/libs/TinyInventory.mjs +1650 -0
- package/dist/v1/libs/TinyInventoryTrader.cjs +242 -0
- package/dist/v1/libs/TinyInventoryTrader.d.mts +95 -0
- package/dist/v1/libs/TinyInventoryTrader.mjs +212 -0
- package/dist/v1/libs/TinyLocalStorage.cjs +14 -1
- package/dist/v1/libs/TinyLocalStorage.mjs +8 -1
- package/dist/v1/libs/TinyRateLimiter.cjs +0 -13
- package/dist/v1/libs/TinyRateLimiter.d.mts +0 -8
- package/dist/v1/libs/TinyRateLimiter.mjs +0 -12
- package/dist/v1/libs/TinySmartScroller.cjs +51 -15
- package/dist/v1/libs/TinySmartScroller.d.mts +28 -12
- package/dist/v1/libs/TinySmartScroller.mjs +44 -14
- package/dist/v1/libs/TinyTextarea.cjs +230 -0
- package/dist/v1/libs/TinyTextarea.d.mts +128 -0
- package/dist/v1/libs/TinyTextarea.mjs +198 -0
- package/dist/v1/libs/TinyToastNotify.cjs +2 -2
- package/dist/v1/libs/TinyToastNotify.mjs +2 -2
- package/dist/v1/libs/TinyUploadClicker.cjs +1 -1
- package/docs/v1/Ai-Tips.md +51 -0
- package/docs/v1/Personal-Ai-Prompts(portuguese).md +134 -0
- package/docs/v1/Personal-Ai-Prompts.md +113 -0
- package/docs/v1/README.md +24 -0
- package/docs/v1/basics/array.md +17 -0
- package/docs/v1/basics/simpleMath.md +73 -0
- package/docs/v1/libs/TinyAdvancedRaffle.md +674 -0
- package/docs/v1/libs/TinyArrayPaginator.md +150 -0
- package/docs/v1/libs/TinyCookieConsent.md +152 -0
- package/docs/v1/libs/TinyDayNightCycle.md +711 -0
- package/docs/v1/libs/TinyGamepad.md +980 -0
- package/docs/v1/libs/TinyI18.md +515 -0
- package/docs/v1/libs/TinyInventory.md +777 -0
- package/docs/v1/libs/TinyInventoryTrader.md +114 -0
- package/docs/v1/libs/TinySmartScroller.md +4 -4
- package/docs/v1/libs/TinyTextarea.md +156 -0
- package/package.json +7 -5
- package/dist/v1/basics/html_deprecated.cjs +0 -124
- package/dist/v1/basics/html_deprecated.d.mts +0 -40
- package/dist/v1/basics/html_deprecated.mjs +0 -97
- package/dist/v1/css/TinyDraggerExample.css +0 -21
- package/dist/v1/css/TinyNotify.css +0 -350
- package/dist/v1/css/aiMarker.css +0 -4
- package/docs/v1/basics/html_deprecated.md +0 -127
|
@@ -275,6 +275,11 @@ class TinySmartScroller {
|
|
|
275
275
|
/** @type {null|EventListenerOrEventListenerObject} */
|
|
276
276
|
#handler = null;
|
|
277
277
|
|
|
278
|
+
#isPastAtBottom = false;
|
|
279
|
+
#isPastAtTop = false;
|
|
280
|
+
#isPastAtCustomTop = false;
|
|
281
|
+
#isPastAtCustomBottom = false;
|
|
282
|
+
|
|
278
283
|
#isAtBottom = false;
|
|
279
284
|
#isAtTop = false;
|
|
280
285
|
#isAtCustomTop = false;
|
|
@@ -596,17 +601,6 @@ class TinySmartScroller {
|
|
|
596
601
|
return results;
|
|
597
602
|
}
|
|
598
603
|
|
|
599
|
-
/**
|
|
600
|
-
* Emits a scroll-related event to all registered listeners.
|
|
601
|
-
*
|
|
602
|
-
* @param {string} event - Event name.
|
|
603
|
-
* @param {*} [payload] - Optional event data payload.
|
|
604
|
-
* @deprecated - Use emit() instead.
|
|
605
|
-
*/
|
|
606
|
-
_emit(event, payload) {
|
|
607
|
-
this.emit(event, payload);
|
|
608
|
-
}
|
|
609
|
-
|
|
610
604
|
/**
|
|
611
605
|
* Handles scroll events, calculates position-related statuses, and emits appropriate events.
|
|
612
606
|
*/
|
|
@@ -639,6 +633,12 @@ class TinySmartScroller {
|
|
|
639
633
|
else if (atCustomTop) atCustomResult = 'top';
|
|
640
634
|
else if (atCustomBottom) atCustomResult = 'bottom';
|
|
641
635
|
|
|
636
|
+
this.#isPastAtTop = this.#isAtTop ?? false;
|
|
637
|
+
this.#isPastAtBottom = this.#isAtBottom ?? false;
|
|
638
|
+
|
|
639
|
+
this.#isPastAtCustomTop = this.#isAtCustomTop ?? false;
|
|
640
|
+
this.#isPastAtCustomBottom = this.#isAtCustomBottom ?? false;
|
|
641
|
+
|
|
642
642
|
this.#isAtTop = atTop;
|
|
643
643
|
this.#isAtBottom = atBottom;
|
|
644
644
|
|
|
@@ -968,7 +968,7 @@ class TinySmartScroller {
|
|
|
968
968
|
*
|
|
969
969
|
* @returns {boolean}
|
|
970
970
|
*/
|
|
971
|
-
|
|
971
|
+
isAtCustomBottom() {
|
|
972
972
|
return this.#isAtCustomBottom;
|
|
973
973
|
}
|
|
974
974
|
|
|
@@ -977,7 +977,7 @@ class TinySmartScroller {
|
|
|
977
977
|
*
|
|
978
978
|
* @returns {boolean}
|
|
979
979
|
*/
|
|
980
|
-
|
|
980
|
+
isAtCustomTop() {
|
|
981
981
|
return this.#isAtCustomTop;
|
|
982
982
|
}
|
|
983
983
|
|
|
@@ -986,7 +986,7 @@ class TinySmartScroller {
|
|
|
986
986
|
*
|
|
987
987
|
* @returns {boolean}
|
|
988
988
|
*/
|
|
989
|
-
|
|
989
|
+
isAtBottom() {
|
|
990
990
|
return this.#isAtBottom;
|
|
991
991
|
}
|
|
992
992
|
|
|
@@ -995,10 +995,46 @@ class TinySmartScroller {
|
|
|
995
995
|
*
|
|
996
996
|
* @returns {boolean}
|
|
997
997
|
*/
|
|
998
|
-
|
|
998
|
+
isAtTop() {
|
|
999
999
|
return this.#isAtTop;
|
|
1000
1000
|
}
|
|
1001
1001
|
|
|
1002
|
+
/**
|
|
1003
|
+
* Returns true if the user has already passed beyond the bottom boundary at some point.
|
|
1004
|
+
*
|
|
1005
|
+
* @returns {boolean}
|
|
1006
|
+
*/
|
|
1007
|
+
isPastAtBottom() {
|
|
1008
|
+
return this.#isPastAtBottom;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Returns true if the user has already passed beyond the top boundary at some point.
|
|
1013
|
+
*
|
|
1014
|
+
* @returns {boolean}
|
|
1015
|
+
*/
|
|
1016
|
+
isPastAtTop() {
|
|
1017
|
+
return this.#isPastAtTop;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Returns true if the user has passed beyond the defined extra scroll boundary from the top at some point.
|
|
1022
|
+
*
|
|
1023
|
+
* @returns {boolean}
|
|
1024
|
+
*/
|
|
1025
|
+
isPastAtCustomTop() {
|
|
1026
|
+
return this.#isPastAtCustomTop;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Returns true if the user has passed beyond the defined extra scroll boundary from the bottom at some point.
|
|
1031
|
+
*
|
|
1032
|
+
* @returns {boolean}
|
|
1033
|
+
*/
|
|
1034
|
+
isPastAtCustomBottom() {
|
|
1035
|
+
return this.#isPastAtCustomBottom;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1002
1038
|
/**
|
|
1003
1039
|
* Returns true if automatic scrolling is currently paused.
|
|
1004
1040
|
*
|
|
@@ -402,14 +402,6 @@ declare class TinySmartScroller {
|
|
|
402
402
|
oldIsVisible: boolean;
|
|
403
403
|
isVisible: boolean;
|
|
404
404
|
}>;
|
|
405
|
-
/**
|
|
406
|
-
* Emits a scroll-related event to all registered listeners.
|
|
407
|
-
*
|
|
408
|
-
* @param {string} event - Event name.
|
|
409
|
-
* @param {*} [payload] - Optional event data payload.
|
|
410
|
-
* @deprecated - Use emit() instead.
|
|
411
|
-
*/
|
|
412
|
-
_emit(event: string, payload?: any): void;
|
|
413
405
|
/**
|
|
414
406
|
* Handles scroll events, calculates position-related statuses, and emits appropriate events.
|
|
415
407
|
*/
|
|
@@ -515,25 +507,49 @@ declare class TinySmartScroller {
|
|
|
515
507
|
*
|
|
516
508
|
* @returns {boolean}
|
|
517
509
|
*/
|
|
518
|
-
|
|
510
|
+
isAtCustomBottom(): boolean;
|
|
519
511
|
/**
|
|
520
512
|
* Checks if the user is within the defined extra scroll boundary from the top.
|
|
521
513
|
*
|
|
522
514
|
* @returns {boolean}
|
|
523
515
|
*/
|
|
524
|
-
|
|
516
|
+
isAtCustomTop(): boolean;
|
|
525
517
|
/**
|
|
526
518
|
* Returns true if the user is currently scrolled to the bottom of the element.
|
|
527
519
|
*
|
|
528
520
|
* @returns {boolean}
|
|
529
521
|
*/
|
|
530
|
-
|
|
522
|
+
isAtBottom(): boolean;
|
|
531
523
|
/**
|
|
532
524
|
* Returns true if the user is currently scrolled to the top of the element.
|
|
533
525
|
*
|
|
534
526
|
* @returns {boolean}
|
|
535
527
|
*/
|
|
536
|
-
|
|
528
|
+
isAtTop(): boolean;
|
|
529
|
+
/**
|
|
530
|
+
* Returns true if the user has already passed beyond the bottom boundary at some point.
|
|
531
|
+
*
|
|
532
|
+
* @returns {boolean}
|
|
533
|
+
*/
|
|
534
|
+
isPastAtBottom(): boolean;
|
|
535
|
+
/**
|
|
536
|
+
* Returns true if the user has already passed beyond the top boundary at some point.
|
|
537
|
+
*
|
|
538
|
+
* @returns {boolean}
|
|
539
|
+
*/
|
|
540
|
+
isPastAtTop(): boolean;
|
|
541
|
+
/**
|
|
542
|
+
* Returns true if the user has passed beyond the defined extra scroll boundary from the top at some point.
|
|
543
|
+
*
|
|
544
|
+
* @returns {boolean}
|
|
545
|
+
*/
|
|
546
|
+
isPastAtCustomTop(): boolean;
|
|
547
|
+
/**
|
|
548
|
+
* Returns true if the user has passed beyond the defined extra scroll boundary from the bottom at some point.
|
|
549
|
+
*
|
|
550
|
+
* @returns {boolean}
|
|
551
|
+
*/
|
|
552
|
+
isPastAtCustomBottom(): boolean;
|
|
537
553
|
/**
|
|
538
554
|
* Returns true if automatic scrolling is currently paused.
|
|
539
555
|
*
|
|
@@ -236,6 +236,10 @@ class TinySmartScroller {
|
|
|
236
236
|
#loadTags = new Set(['IMG', 'IFRAME', 'VIDEO']);
|
|
237
237
|
/** @type {null|EventListenerOrEventListenerObject} */
|
|
238
238
|
#handler = null;
|
|
239
|
+
#isPastAtBottom = false;
|
|
240
|
+
#isPastAtTop = false;
|
|
241
|
+
#isPastAtCustomTop = false;
|
|
242
|
+
#isPastAtCustomBottom = false;
|
|
239
243
|
#isAtBottom = false;
|
|
240
244
|
#isAtTop = false;
|
|
241
245
|
#isAtCustomTop = false;
|
|
@@ -507,16 +511,6 @@ class TinySmartScroller {
|
|
|
507
511
|
});
|
|
508
512
|
return results;
|
|
509
513
|
}
|
|
510
|
-
/**
|
|
511
|
-
* Emits a scroll-related event to all registered listeners.
|
|
512
|
-
*
|
|
513
|
-
* @param {string} event - Event name.
|
|
514
|
-
* @param {*} [payload] - Optional event data payload.
|
|
515
|
-
* @deprecated - Use emit() instead.
|
|
516
|
-
*/
|
|
517
|
-
_emit(event, payload) {
|
|
518
|
-
this.emit(event, payload);
|
|
519
|
-
}
|
|
520
514
|
/**
|
|
521
515
|
* Handles scroll events, calculates position-related statuses, and emits appropriate events.
|
|
522
516
|
*/
|
|
@@ -550,6 +544,10 @@ class TinySmartScroller {
|
|
|
550
544
|
atCustomResult = 'top';
|
|
551
545
|
else if (atCustomBottom)
|
|
552
546
|
atCustomResult = 'bottom';
|
|
547
|
+
this.#isPastAtTop = this.#isAtTop ?? false;
|
|
548
|
+
this.#isPastAtBottom = this.#isAtBottom ?? false;
|
|
549
|
+
this.#isPastAtCustomTop = this.#isAtCustomTop ?? false;
|
|
550
|
+
this.#isPastAtCustomBottom = this.#isAtCustomBottom ?? false;
|
|
553
551
|
this.#isAtTop = atTop;
|
|
554
552
|
this.#isAtBottom = atBottom;
|
|
555
553
|
this.#isAtCustomTop = atCustomTop;
|
|
@@ -840,7 +838,7 @@ class TinySmartScroller {
|
|
|
840
838
|
*
|
|
841
839
|
* @returns {boolean}
|
|
842
840
|
*/
|
|
843
|
-
|
|
841
|
+
isAtCustomBottom() {
|
|
844
842
|
return this.#isAtCustomBottom;
|
|
845
843
|
}
|
|
846
844
|
/**
|
|
@@ -848,7 +846,7 @@ class TinySmartScroller {
|
|
|
848
846
|
*
|
|
849
847
|
* @returns {boolean}
|
|
850
848
|
*/
|
|
851
|
-
|
|
849
|
+
isAtCustomTop() {
|
|
852
850
|
return this.#isAtCustomTop;
|
|
853
851
|
}
|
|
854
852
|
/**
|
|
@@ -856,7 +854,7 @@ class TinySmartScroller {
|
|
|
856
854
|
*
|
|
857
855
|
* @returns {boolean}
|
|
858
856
|
*/
|
|
859
|
-
|
|
857
|
+
isAtBottom() {
|
|
860
858
|
return this.#isAtBottom;
|
|
861
859
|
}
|
|
862
860
|
/**
|
|
@@ -864,9 +862,41 @@ class TinySmartScroller {
|
|
|
864
862
|
*
|
|
865
863
|
* @returns {boolean}
|
|
866
864
|
*/
|
|
867
|
-
|
|
865
|
+
isAtTop() {
|
|
868
866
|
return this.#isAtTop;
|
|
869
867
|
}
|
|
868
|
+
/**
|
|
869
|
+
* Returns true if the user has already passed beyond the bottom boundary at some point.
|
|
870
|
+
*
|
|
871
|
+
* @returns {boolean}
|
|
872
|
+
*/
|
|
873
|
+
isPastAtBottom() {
|
|
874
|
+
return this.#isPastAtBottom;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Returns true if the user has already passed beyond the top boundary at some point.
|
|
878
|
+
*
|
|
879
|
+
* @returns {boolean}
|
|
880
|
+
*/
|
|
881
|
+
isPastAtTop() {
|
|
882
|
+
return this.#isPastAtTop;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Returns true if the user has passed beyond the defined extra scroll boundary from the top at some point.
|
|
886
|
+
*
|
|
887
|
+
* @returns {boolean}
|
|
888
|
+
*/
|
|
889
|
+
isPastAtCustomTop() {
|
|
890
|
+
return this.#isPastAtCustomTop;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Returns true if the user has passed beyond the defined extra scroll boundary from the bottom at some point.
|
|
894
|
+
*
|
|
895
|
+
* @returns {boolean}
|
|
896
|
+
*/
|
|
897
|
+
isPastAtCustomBottom() {
|
|
898
|
+
return this.#isPastAtCustomBottom;
|
|
899
|
+
}
|
|
870
900
|
/**
|
|
871
901
|
* Returns true if automatic scrolling is currently paused.
|
|
872
902
|
*
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} OnInputInfo
|
|
5
|
+
* @property {number} breakLines - Total number of `\n` line breaks in the textarea value.
|
|
6
|
+
* @property {number} height - Final calculated height (in pixels) applied to the textarea.
|
|
7
|
+
* @property {number} scrollHeight - Internal scrollHeight before limiting.
|
|
8
|
+
* @property {number} maxHeight - Maximum allowed height before scrolling is forced.
|
|
9
|
+
* @property {number} lineHeight - Height of one line of text, computed from CSS.
|
|
10
|
+
* @property {number} maxRows - Maximum number of visible rows allowed.
|
|
11
|
+
* @property {number} rows - Effective number of visual rows being used.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A lightweight utility class that automatically adjusts the height of a `<textarea>`
|
|
16
|
+
* element based on its content. It prevents scrollbars by expanding vertically as needed,
|
|
17
|
+
* up to a configurable maximum number of visible rows.
|
|
18
|
+
*
|
|
19
|
+
* Features:
|
|
20
|
+
* - Automatically resizes the textarea as the user types
|
|
21
|
+
* - Prevents vertical scrollbars until a maximum row limit is reached
|
|
22
|
+
* - Supports additional height padding
|
|
23
|
+
* - Provides real-time callbacks for input and resize events
|
|
24
|
+
* - Allows manual refresh and cleanup of behavior
|
|
25
|
+
*
|
|
26
|
+
* Ideal for chat inputs, note editors, or any form where dynamic space usage
|
|
27
|
+
* is preferred without relying on scrollbars too early.
|
|
28
|
+
*
|
|
29
|
+
* @class
|
|
30
|
+
* @beta
|
|
31
|
+
*/
|
|
32
|
+
class TinyTextarea {
|
|
33
|
+
#lineHeight;
|
|
34
|
+
#maxRows;
|
|
35
|
+
#extraHeight;
|
|
36
|
+
|
|
37
|
+
#lastKnownHeight = 0;
|
|
38
|
+
#lastKnownRows = 0;
|
|
39
|
+
|
|
40
|
+
/** @type {HTMLTextAreaElement} */
|
|
41
|
+
#textarea;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @type {((info: OnInputInfo) => void) | null}
|
|
45
|
+
*/
|
|
46
|
+
#onResize = null;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @type {((info: OnInputInfo) => void) | null}
|
|
50
|
+
*/
|
|
51
|
+
#onInput = null;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Returns the computed line height in pixels.
|
|
55
|
+
* @returns {number}
|
|
56
|
+
*/
|
|
57
|
+
get lineHeight() {
|
|
58
|
+
return this.#lineHeight;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Returns the maximum number of rows allowed.
|
|
63
|
+
* @returns {number}
|
|
64
|
+
*/
|
|
65
|
+
get maxRows() {
|
|
66
|
+
return this.#maxRows - 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Returns the additional height added to the textarea.
|
|
71
|
+
* @returns {number}
|
|
72
|
+
*/
|
|
73
|
+
get extraHeight() {
|
|
74
|
+
return this.#extraHeight;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Returns the most recently applied height.
|
|
79
|
+
* @returns {number}
|
|
80
|
+
*/
|
|
81
|
+
get currentHeight() {
|
|
82
|
+
return this.#lastKnownHeight;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns the most recently calculated row count.
|
|
87
|
+
* @returns {number}
|
|
88
|
+
*/
|
|
89
|
+
get currentRows() {
|
|
90
|
+
return this.#lastKnownRows;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Returns the original textarea element managed by this instance.
|
|
95
|
+
* @returns {HTMLTextAreaElement}
|
|
96
|
+
*/
|
|
97
|
+
get textarea() {
|
|
98
|
+
return this.#textarea;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Creates a new TinyTextarea instance.
|
|
103
|
+
*
|
|
104
|
+
* @param {HTMLTextAreaElement} textarea - The `<textarea>` element to enhance.
|
|
105
|
+
* @param {Object} [options={}] - Optional configuration parameters.
|
|
106
|
+
* @param {number} [options.maxRows] - Maximum number of visible rows before scrolling.
|
|
107
|
+
* @param {number} [options.extraHeight] - Additional pixels to add to final height.
|
|
108
|
+
* @param {(info: OnInputInfo) => void} [options.onResize] - Callback when the number of rows changes.
|
|
109
|
+
* @param {(info: OnInputInfo) => void} [options.onInput] - Callback on every input event.
|
|
110
|
+
* @throws {Error} If `textarea` is not a valid `<textarea>` element.
|
|
111
|
+
* @throws {TypeError} If provided options are of invalid types.
|
|
112
|
+
*/
|
|
113
|
+
constructor(textarea, options = {}) {
|
|
114
|
+
if (!(textarea instanceof HTMLTextAreaElement))
|
|
115
|
+
throw new Error('TinyTextarea: Provided element is not a <textarea>.');
|
|
116
|
+
if (typeof options !== 'object' || options === null)
|
|
117
|
+
throw new TypeError('TinyTextarea: Options must be an object if provided.');
|
|
118
|
+
if ('maxRows' in options && typeof options.maxRows !== 'number')
|
|
119
|
+
throw new TypeError('TinyTextarea: `maxRows` must be a number.');
|
|
120
|
+
if ('extraHeight' in options && typeof options.extraHeight !== 'number')
|
|
121
|
+
throw new TypeError('TinyTextarea: `extraHeight` must be a number.');
|
|
122
|
+
if ('onResize' in options && typeof options.onResize !== 'function')
|
|
123
|
+
throw new TypeError('TinyTextarea: `onResize` must be a function.');
|
|
124
|
+
if ('onInput' in options && typeof options.onInput !== 'function')
|
|
125
|
+
throw new TypeError('TinyTextarea: `onInput` must be a function.');
|
|
126
|
+
|
|
127
|
+
this.#textarea = textarea;
|
|
128
|
+
this.#maxRows = (options.maxRows ?? 5) + 1;
|
|
129
|
+
this.#extraHeight = options.extraHeight ?? 0;
|
|
130
|
+
this.#onResize = options.onResize ?? null;
|
|
131
|
+
this.#onInput = options.onInput ?? null;
|
|
132
|
+
|
|
133
|
+
this.#lineHeight = this.#getLineHeight();
|
|
134
|
+
|
|
135
|
+
textarea.style.overflowY = 'hidden';
|
|
136
|
+
textarea.style.resize = 'none';
|
|
137
|
+
|
|
138
|
+
this._handleInput = () => this.#resize();
|
|
139
|
+
textarea.addEventListener('input', this._handleInput);
|
|
140
|
+
this.#resize();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Automatically resize the textarea based on its content and notify listeners.
|
|
145
|
+
* Triggers `onResize` if the number of rows has changed.
|
|
146
|
+
* Always triggers `onInput`.
|
|
147
|
+
*/
|
|
148
|
+
#resize() {
|
|
149
|
+
this.#textarea.style.height = 'auto';
|
|
150
|
+
|
|
151
|
+
const style = window.getComputedStyle(this.#textarea);
|
|
152
|
+
const paddingTop = parseFloat(style.paddingTop) || 0;
|
|
153
|
+
const paddingBottom = parseFloat(style.paddingBottom) || 0;
|
|
154
|
+
|
|
155
|
+
const breakLines = (this.#textarea.value.match(/\n/g) || []).length;
|
|
156
|
+
const scrollHeight = this.#textarea.scrollHeight;
|
|
157
|
+
const maxHeight = this.#lineHeight * this.#maxRows;
|
|
158
|
+
const newHeight = Math.ceil(
|
|
159
|
+
Math.min(scrollHeight, maxHeight) - paddingTop - paddingBottom + this.#extraHeight,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// const rows = Math.round(newHeight / this.#lineHeight);
|
|
163
|
+
const maxRows = this.#maxRows - 1;
|
|
164
|
+
const rows = breakLines < maxRows ? breakLines + 1 : maxRows;
|
|
165
|
+
|
|
166
|
+
this.#textarea.style.height = `${newHeight}px`;
|
|
167
|
+
this.#textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden';
|
|
168
|
+
this.#lastKnownHeight = newHeight;
|
|
169
|
+
|
|
170
|
+
const info = {
|
|
171
|
+
breakLines,
|
|
172
|
+
rows,
|
|
173
|
+
height: newHeight,
|
|
174
|
+
scrollHeight,
|
|
175
|
+
maxHeight,
|
|
176
|
+
lineHeight: this.#lineHeight,
|
|
177
|
+
maxRows,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
if (rows !== this.#lastKnownRows) {
|
|
181
|
+
this.#lastKnownRows = rows;
|
|
182
|
+
if (typeof this.#onResize === 'function') {
|
|
183
|
+
this.#onResize({ ...info });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (typeof this.#onInput === 'function') {
|
|
188
|
+
this.#onInput(info);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Computes the current line height from the textarea's computed styles.
|
|
194
|
+
* Falls back to `fontSize * 1.2` if lineHeight is not a number.
|
|
195
|
+
* @returns {number} - The computed line height in pixels.
|
|
196
|
+
*/
|
|
197
|
+
#getLineHeight() {
|
|
198
|
+
const style = window.getComputedStyle(this.#textarea);
|
|
199
|
+
const line = parseFloat(style.lineHeight);
|
|
200
|
+
if (!Number.isNaN(line)) return line;
|
|
201
|
+
return parseFloat(style.fontSize) * 1.2;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Returns the latest height and row count of the textarea.
|
|
206
|
+
* @returns {{ height: number, rows: number }} - Last known resize state.
|
|
207
|
+
*/
|
|
208
|
+
getData() {
|
|
209
|
+
return {
|
|
210
|
+
rows: this.#lastKnownRows,
|
|
211
|
+
height: this.#lastKnownHeight,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Manually trigger a resize check.
|
|
217
|
+
*/
|
|
218
|
+
refresh() {
|
|
219
|
+
this.#resize();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Cleans up internal listeners and disables dynamic behavior.
|
|
224
|
+
*/
|
|
225
|
+
destroy() {
|
|
226
|
+
this.#textarea.removeEventListener('input', this._handleInput);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
module.exports = TinyTextarea;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export default TinyTextarea;
|
|
2
|
+
export type OnInputInfo = {
|
|
3
|
+
/**
|
|
4
|
+
* - Total number of `\n` line breaks in the textarea value.
|
|
5
|
+
*/
|
|
6
|
+
breakLines: number;
|
|
7
|
+
/**
|
|
8
|
+
* - Final calculated height (in pixels) applied to the textarea.
|
|
9
|
+
*/
|
|
10
|
+
height: number;
|
|
11
|
+
/**
|
|
12
|
+
* - Internal scrollHeight before limiting.
|
|
13
|
+
*/
|
|
14
|
+
scrollHeight: number;
|
|
15
|
+
/**
|
|
16
|
+
* - Maximum allowed height before scrolling is forced.
|
|
17
|
+
*/
|
|
18
|
+
maxHeight: number;
|
|
19
|
+
/**
|
|
20
|
+
* - Height of one line of text, computed from CSS.
|
|
21
|
+
*/
|
|
22
|
+
lineHeight: number;
|
|
23
|
+
/**
|
|
24
|
+
* - Maximum number of visible rows allowed.
|
|
25
|
+
*/
|
|
26
|
+
maxRows: number;
|
|
27
|
+
/**
|
|
28
|
+
* - Effective number of visual rows being used.
|
|
29
|
+
*/
|
|
30
|
+
rows: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} OnInputInfo
|
|
34
|
+
* @property {number} breakLines - Total number of `\n` line breaks in the textarea value.
|
|
35
|
+
* @property {number} height - Final calculated height (in pixels) applied to the textarea.
|
|
36
|
+
* @property {number} scrollHeight - Internal scrollHeight before limiting.
|
|
37
|
+
* @property {number} maxHeight - Maximum allowed height before scrolling is forced.
|
|
38
|
+
* @property {number} lineHeight - Height of one line of text, computed from CSS.
|
|
39
|
+
* @property {number} maxRows - Maximum number of visible rows allowed.
|
|
40
|
+
* @property {number} rows - Effective number of visual rows being used.
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* A lightweight utility class that automatically adjusts the height of a `<textarea>`
|
|
44
|
+
* element based on its content. It prevents scrollbars by expanding vertically as needed,
|
|
45
|
+
* up to a configurable maximum number of visible rows.
|
|
46
|
+
*
|
|
47
|
+
* Features:
|
|
48
|
+
* - Automatically resizes the textarea as the user types
|
|
49
|
+
* - Prevents vertical scrollbars until a maximum row limit is reached
|
|
50
|
+
* - Supports additional height padding
|
|
51
|
+
* - Provides real-time callbacks for input and resize events
|
|
52
|
+
* - Allows manual refresh and cleanup of behavior
|
|
53
|
+
*
|
|
54
|
+
* Ideal for chat inputs, note editors, or any form where dynamic space usage
|
|
55
|
+
* is preferred without relying on scrollbars too early.
|
|
56
|
+
*
|
|
57
|
+
* @class
|
|
58
|
+
* @beta
|
|
59
|
+
*/
|
|
60
|
+
declare class TinyTextarea {
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new TinyTextarea instance.
|
|
63
|
+
*
|
|
64
|
+
* @param {HTMLTextAreaElement} textarea - The `<textarea>` element to enhance.
|
|
65
|
+
* @param {Object} [options={}] - Optional configuration parameters.
|
|
66
|
+
* @param {number} [options.maxRows] - Maximum number of visible rows before scrolling.
|
|
67
|
+
* @param {number} [options.extraHeight] - Additional pixels to add to final height.
|
|
68
|
+
* @param {(info: OnInputInfo) => void} [options.onResize] - Callback when the number of rows changes.
|
|
69
|
+
* @param {(info: OnInputInfo) => void} [options.onInput] - Callback on every input event.
|
|
70
|
+
* @throws {Error} If `textarea` is not a valid `<textarea>` element.
|
|
71
|
+
* @throws {TypeError} If provided options are of invalid types.
|
|
72
|
+
*/
|
|
73
|
+
constructor(textarea: HTMLTextAreaElement, options?: {
|
|
74
|
+
maxRows?: number | undefined;
|
|
75
|
+
extraHeight?: number | undefined;
|
|
76
|
+
onResize?: ((info: OnInputInfo) => void) | undefined;
|
|
77
|
+
onInput?: ((info: OnInputInfo) => void) | undefined;
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Returns the computed line height in pixels.
|
|
81
|
+
* @returns {number}
|
|
82
|
+
*/
|
|
83
|
+
get lineHeight(): number;
|
|
84
|
+
/**
|
|
85
|
+
* Returns the maximum number of rows allowed.
|
|
86
|
+
* @returns {number}
|
|
87
|
+
*/
|
|
88
|
+
get maxRows(): number;
|
|
89
|
+
/**
|
|
90
|
+
* Returns the additional height added to the textarea.
|
|
91
|
+
* @returns {number}
|
|
92
|
+
*/
|
|
93
|
+
get extraHeight(): number;
|
|
94
|
+
/**
|
|
95
|
+
* Returns the most recently applied height.
|
|
96
|
+
* @returns {number}
|
|
97
|
+
*/
|
|
98
|
+
get currentHeight(): number;
|
|
99
|
+
/**
|
|
100
|
+
* Returns the most recently calculated row count.
|
|
101
|
+
* @returns {number}
|
|
102
|
+
*/
|
|
103
|
+
get currentRows(): number;
|
|
104
|
+
/**
|
|
105
|
+
* Returns the original textarea element managed by this instance.
|
|
106
|
+
* @returns {HTMLTextAreaElement}
|
|
107
|
+
*/
|
|
108
|
+
get textarea(): HTMLTextAreaElement;
|
|
109
|
+
_handleInput: () => void;
|
|
110
|
+
/**
|
|
111
|
+
* Returns the latest height and row count of the textarea.
|
|
112
|
+
* @returns {{ height: number, rows: number }} - Last known resize state.
|
|
113
|
+
*/
|
|
114
|
+
getData(): {
|
|
115
|
+
height: number;
|
|
116
|
+
rows: number;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Manually trigger a resize check.
|
|
120
|
+
*/
|
|
121
|
+
refresh(): void;
|
|
122
|
+
/**
|
|
123
|
+
* Cleans up internal listeners and disables dynamic behavior.
|
|
124
|
+
*/
|
|
125
|
+
destroy(): void;
|
|
126
|
+
#private;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=TinyTextarea.d.mts.map
|