tiny-essentials 1.28.0 → 1.28.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 (168) hide show
  1. package/changelog/1/28/1.md +23 -0
  2. package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
  3. package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
  4. package/dist/v1/TinyAnalogClock.min.js +1 -1
  5. package/dist/v1/TinyBasicsEs.min.js +1 -1
  6. package/dist/v1/TinyDayNightCycle.min.js +1 -1
  7. package/dist/v1/TinyDragDropDetector.min.js +1 -1
  8. package/dist/v1/TinyDragger.min.js +1 -1
  9. package/dist/v1/TinyElementObserver.min.js +1 -1
  10. package/dist/v1/TinyEssentials.min.js +1 -1
  11. package/dist/v1/TinyGamepad.min.js +1 -1
  12. package/dist/v1/TinyHtml.min.js +1 -1
  13. package/dist/v1/TinyI18.min.js +1 -1
  14. package/dist/v1/TinyIframeEvents.min.js +1 -1
  15. package/dist/v1/TinyLocalStorage.min.js +1 -1
  16. package/dist/v1/TinyMediaPlayer.min.js +1 -1
  17. package/dist/v1/TinyNewWinEvents.min.js +1 -1
  18. package/dist/v1/TinyNotifyCenter.min.js +1 -1
  19. package/dist/v1/TinyRadioFm.min.js +1 -1
  20. package/dist/v1/TinyRateLimiter.min.js +1 -1
  21. package/dist/v1/TinySmartScroller.min.js +1 -1
  22. package/dist/v1/TinyTextDiffer.min.js +1 -1
  23. package/dist/v1/TinyTextarea.min.js +1 -1
  24. package/dist/v1/TinyTimeout.min.js +1 -1
  25. package/dist/v1/TinyToastNotify.min.js +1 -1
  26. package/dist/v1/TinyUploadClicker.min.js +1 -1
  27. package/dist/v1/UltraRandomMsgGen.min.js +1 -1
  28. package/dist/v1/basics/array.cjs +57 -9
  29. package/dist/v1/basics/array.d.mts +27 -11
  30. package/dist/v1/basics/array.mjs +51 -9
  31. package/dist/v1/basics/clock.cjs +94 -42
  32. package/dist/v1/basics/clock.d.mts +10 -10
  33. package/dist/v1/basics/clock.mjs +91 -54
  34. package/dist/v1/basics/deprecated/html.cjs +246 -0
  35. package/dist/v1/basics/deprecated/html.d.mts +63 -0
  36. package/dist/v1/basics/deprecated/html.mjs +190 -0
  37. package/dist/v1/basics/html.cjs +149 -130
  38. package/dist/v1/basics/html.d.mts +26 -61
  39. package/dist/v1/basics/html.mjs +113 -105
  40. package/dist/v1/basics/index.cjs +2 -0
  41. package/dist/v1/basics/index.d.mts +3 -1
  42. package/dist/v1/basics/index.mjs +3 -3
  43. package/dist/v1/basics/mediaContent.cjs +51 -9
  44. package/dist/v1/basics/mediaContent.d.mts +0 -87
  45. package/dist/v1/basics/mediaContent.mjs +40 -10
  46. package/dist/v1/basics/objChecker.cjs +7 -5
  47. package/dist/v1/basics/objChecker.d.mts +3 -2
  48. package/dist/v1/basics/objChecker.mjs +6 -6
  49. package/dist/v1/basics/objFilter.cjs +40 -7
  50. package/dist/v1/basics/objFilter.d.mts +6 -6
  51. package/dist/v1/basics/objFilter.mjs +32 -7
  52. package/dist/v1/basics/simpleMath.cjs +81 -25
  53. package/dist/v1/basics/simpleMath.d.mts +2 -2
  54. package/dist/v1/basics/simpleMath.mjs +70 -27
  55. package/dist/v1/basics/text.cjs +76 -31
  56. package/dist/v1/basics/text.d.mts +69 -7
  57. package/dist/v1/basics/text.mjs +62 -31
  58. package/dist/v1/index.cjs +4 -0
  59. package/dist/v1/index.d.mts +4 -1
  60. package/dist/v1/index.mjs +4 -3
  61. package/dist/v1/libs/TinyAdvancedRaffle.cjs +64 -50
  62. package/dist/v1/libs/TinyAdvancedRaffle.d.mts +4 -13
  63. package/dist/v1/libs/TinyAdvancedRaffle.mjs +62 -49
  64. package/dist/v1/libs/TinyAfterScrollWatcher.cjs +17 -1
  65. package/dist/v1/libs/TinyAfterScrollWatcher.d.mts +4 -1
  66. package/dist/v1/libs/TinyAfterScrollWatcher.mjs +15 -1
  67. package/dist/v1/libs/TinyAnalogClock.cjs +60 -0
  68. package/dist/v1/libs/TinyAnalogClock.d.mts +6 -0
  69. package/dist/v1/libs/TinyAnalogClock.mjs +57 -0
  70. package/dist/v1/libs/TinyClipboard.cjs +2 -0
  71. package/dist/v1/libs/TinyClipboard.d.mts +4 -2
  72. package/dist/v1/libs/TinyClipboard.mjs +2 -0
  73. package/dist/v1/libs/TinyColorConverter.cjs +1 -0
  74. package/dist/v1/libs/TinyColorConverter.d.mts +2 -1
  75. package/dist/v1/libs/TinyColorConverter.mjs +1 -0
  76. package/dist/v1/libs/TinyDayNightCycle.cjs +67 -42
  77. package/dist/v1/libs/TinyDayNightCycle.d.mts +2 -7
  78. package/dist/v1/libs/TinyDayNightCycle.mjs +65 -41
  79. package/dist/v1/libs/TinyDragDropDetector.cjs +25 -0
  80. package/dist/v1/libs/TinyDragDropDetector.d.mts +6 -0
  81. package/dist/v1/libs/TinyDragDropDetector.mjs +22 -0
  82. package/dist/v1/libs/TinyDragger.cjs +46 -19
  83. package/dist/v1/libs/TinyDragger.mjs +45 -18
  84. package/dist/v1/libs/TinyElementObserver.cjs +39 -0
  85. package/dist/v1/libs/TinyElementObserver.d.mts +6 -0
  86. package/dist/v1/libs/TinyElementObserver.mjs +36 -0
  87. package/dist/v1/libs/TinyGamepad.cjs +131 -1
  88. package/dist/v1/libs/TinyGamepad.mjs +129 -1
  89. package/dist/v1/libs/TinyHtml.cjs +1 -1
  90. package/dist/v1/libs/TinyHtml.mjs +2 -2
  91. package/dist/v1/libs/TinyI18.cjs +61 -0
  92. package/dist/v1/libs/TinyI18.d.mts +14 -0
  93. package/dist/v1/libs/TinyI18.mjs +55 -0
  94. package/dist/v1/libs/TinyIframeEvents.cjs +18 -1
  95. package/dist/v1/libs/TinyIframeEvents.mjs +18 -1
  96. package/dist/v1/libs/TinyLocalStorage.cjs +48 -0
  97. package/dist/v1/libs/TinyLocalStorage.d.mts +6 -0
  98. package/dist/v1/libs/TinyLocalStorage.mjs +45 -0
  99. package/dist/v1/libs/TinyMediaPlayer.cjs +72 -0
  100. package/dist/v1/libs/TinyMediaPlayer.d.mts +10 -0
  101. package/dist/v1/libs/TinyMediaPlayer.mjs +66 -0
  102. package/dist/v1/libs/TinyNewWinEvents.cjs +29 -0
  103. package/dist/v1/libs/TinyNewWinEvents.d.mts +6 -0
  104. package/dist/v1/libs/TinyNewWinEvents.mjs +26 -0
  105. package/dist/v1/libs/TinyNotifyCenter.cjs +36 -0
  106. package/dist/v1/libs/TinyNotifyCenter.d.mts +6 -0
  107. package/dist/v1/libs/TinyNotifyCenter.mjs +32 -0
  108. package/dist/v1/libs/TinyRadioFm.cjs +38 -0
  109. package/dist/v1/libs/TinyRadioFm.d.mts +1 -0
  110. package/dist/v1/libs/TinyRadioFm.mjs +35 -0
  111. package/dist/v1/libs/TinyRateLimiter.cjs +52 -0
  112. package/dist/v1/libs/TinyRateLimiter.d.mts +6 -0
  113. package/dist/v1/libs/TinyRateLimiter.mjs +48 -0
  114. package/dist/v1/libs/TinySmartScroller.cjs +52 -3
  115. package/dist/v1/libs/TinySmartScroller.d.mts +17 -15
  116. package/dist/v1/libs/TinySmartScroller.mjs +51 -5
  117. package/dist/v1/libs/TinyTextDiffer.cjs +19 -18
  118. package/dist/v1/libs/TinyTextDiffer.d.mts +1 -0
  119. package/dist/v1/libs/TinyTextDiffer.mjs +16 -17
  120. package/dist/v1/libs/TinyTextarea.cjs +19 -0
  121. package/dist/v1/libs/TinyTextarea.d.mts +6 -0
  122. package/dist/v1/libs/TinyTextarea.mjs +17 -0
  123. package/dist/v1/libs/TinyTimeout.cjs +11 -1
  124. package/dist/v1/libs/TinyTimeout.mjs +9 -1
  125. package/dist/v1/libs/TinyToastNotify.cjs +35 -0
  126. package/dist/v1/libs/TinyToastNotify.d.mts +6 -0
  127. package/dist/v1/libs/TinyToastNotify.mjs +31 -0
  128. package/dist/v1/libs/TinyUploadClicker.cjs +19 -0
  129. package/dist/v1/libs/TinyUploadClicker.d.mts +6 -0
  130. package/dist/v1/libs/TinyUploadClicker.mjs +17 -0
  131. package/dist/v1/libs/UltraRandomMsgGen.cjs +148 -35
  132. package/dist/v1/libs/UltraRandomMsgGen.d.mts +17 -3
  133. package/dist/v1/libs/UltraRandomMsgGen.mjs +133 -34
  134. package/dist/v1/libs/utils.cjs +21 -0
  135. package/dist/v1/libs/utils.d.mts +2 -0
  136. package/dist/v1/libs/utils.mjs +16 -0
  137. package/docs/v1/README.md +1 -0
  138. package/docs/v1/basics/array.md +2 -2
  139. package/docs/v1/basics/deprecated/html.md +17 -0
  140. package/docs/v1/basics/fullScreen.md +1 -1
  141. package/docs/v1/basics/html.md +12 -26
  142. package/docs/v1/basics/mediaContent.md +1 -1
  143. package/docs/v1/basics/objChecker.md +1 -1
  144. package/docs/v1/basics/text.md +2 -2
  145. package/docs/v1/fileManager/main.md +1 -1
  146. package/docs/v1/libs/ColorSafeStringify.md +1 -1
  147. package/docs/v1/libs/TinyAfterScrollWatcher.md +1 -1
  148. package/docs/v1/libs/TinyAnalogClock.md +1 -1
  149. package/docs/v1/libs/TinyArrayComparator.md +1 -1
  150. package/docs/v1/libs/TinyArrayPaginator.md +1 -1
  151. package/docs/v1/libs/TinyClassManager/TinyPluginInliner.md +2 -2
  152. package/docs/v1/libs/TinyClassManager.md +1 -1
  153. package/docs/v1/libs/TinyClipboard.md +1 -1
  154. package/docs/v1/libs/TinyCookieConsent.md +1 -1
  155. package/docs/v1/libs/TinyDomReadyManager.md +1 -1
  156. package/docs/v1/libs/TinyDragDropDetector.md +1 -1
  157. package/docs/v1/libs/TinyDragger.md +1 -1
  158. package/docs/v1/libs/TinyElementObserver.md +1 -1
  159. package/docs/v1/libs/TinyHtml.md +1 -1
  160. package/docs/v1/libs/TinyIframeEvents.md +2 -2
  161. package/docs/v1/libs/TinyLevelUp.md +1 -1
  162. package/docs/v1/libs/TinyLoadingScreen.md +1 -1
  163. package/docs/v1/libs/TinyNewWinEvents.md +2 -2
  164. package/docs/v1/libs/TinyNotifications.md +1 -1
  165. package/docs/v1/libs/TinyPromiseQueue.md +2 -2
  166. package/docs/v1/libs/TinyTextDiffer.md +1 -1
  167. package/docs/v1/libs/TinyTextarea.md +1 -1
  168. package/package.json +10 -1
@@ -36,6 +36,14 @@
36
36
  * ruleOfThree.execute(2, 6, 3, true); // → 4
37
37
  */
38
38
  function ruleOfThree(val1, val2, val3, inverse = false) {
39
+ if (typeof val1 !== 'number' || !Number.isFinite(val1))
40
+ throw new TypeError('val1 must be a finite number.');
41
+ if (typeof val2 !== 'number' || !Number.isFinite(val2))
42
+ throw new TypeError('val2 must be a finite number.');
43
+ if (typeof val3 !== 'number' || !Number.isFinite(val3))
44
+ throw new TypeError('val3 must be a finite number.');
45
+ if (typeof inverse !== 'boolean') throw new TypeError('inverse must be a boolean.');
46
+
39
47
  return inverse ? Number(val1 * val2) / val3 : Number(val3 * val2) / val1;
40
48
  }
41
49
 
@@ -52,6 +60,11 @@ function ruleOfThree(val1, val2, val3, inverse = false) {
52
60
  * getSimplePerc(200, 15); // 30
53
61
  */
54
62
  function getSimplePerc(price, percentage) {
63
+ if (typeof price !== 'number' || !Number.isFinite(price))
64
+ throw new TypeError('price must be a finite number.');
65
+ if (typeof percentage !== 'number' || !Number.isFinite(percentage))
66
+ throw new TypeError('percentage must be a finite number.');
67
+
55
68
  return price * (percentage / 100);
56
69
  }
57
70
 
@@ -66,6 +79,11 @@ function getSimplePerc(price, percentage) {
66
79
  * getPercentage(5, 100); // 5
67
80
  */
68
81
  function getPercentage(part, total) {
82
+ if (typeof part !== 'number' || !Number.isFinite(part))
83
+ throw new TypeError('part must be a finite number.');
84
+ if (typeof total !== 'number' || !Number.isFinite(total))
85
+ throw new TypeError('total must be a finite number.');
86
+
69
87
  if (total === 0) return 0;
70
88
  return (part / total) * 100;
71
89
  }
@@ -78,27 +96,31 @@ function getPercentage(part, total) {
78
96
  * @returns {number|null} The age in years, or null if `timeData` is not provided or invalid.
79
97
  */
80
98
  function getAge(timeData = 0, now = null) {
81
- if (typeof timeData !== 'undefined' && timeData !== null && timeData !== 0) {
82
- const birthDate = new Date(timeData);
83
- if (Number.isNaN(birthDate.getTime())) return null;
99
+ if (typeof timeData !== 'number' && typeof timeData !== 'string' && !(timeData instanceof Date)) {
100
+ throw new TypeError('timeData must be a number, string, or Date object.');
101
+ }
84
102
 
85
- const currentDate = now instanceof Date ? now : new Date();
103
+ if (now !== null && !(now instanceof Date)) {
104
+ throw new TypeError('now must be a Date object or null.');
105
+ }
86
106
 
87
- let age = currentDate.getFullYear() - birthDate.getFullYear();
107
+ const birthDate = new Date(timeData);
108
+ if (Number.isNaN(birthDate.getTime())) return null;
88
109
 
89
- const currentMonth = currentDate.getMonth();
90
- const birthMonth = birthDate.getMonth();
110
+ const currentDate = now instanceof Date ? now : new Date();
91
111
 
92
- const currentDay = currentDate.getDate();
93
- const birthDay = birthDate.getDate();
112
+ let age = currentDate.getFullYear() - birthDate.getFullYear();
94
113
 
95
- // Adjust if birthday hasn't occurred yet this year
96
- if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay)) age--;
114
+ const currentMonth = currentDate.getMonth();
115
+ const birthMonth = birthDate.getMonth();
97
116
 
98
- return Math.abs(age);
99
- }
117
+ const currentDay = currentDate.getDate();
118
+ const birthDay = birthDate.getDate();
119
+
120
+ // Adjust if birthday hasn't occurred yet this year
121
+ if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay)) age--;
100
122
 
101
- return null;
123
+ return Math.abs(age);
102
124
  }
103
125
 
104
126
  /**
@@ -112,7 +134,7 @@ function getAge(timeData = 0, now = null) {
112
134
  *
113
135
  * @param {number} bytes - The number of bytes to format. Must be a non-negative number.
114
136
  * @param {number|null} [decimals=null] - The number of decimal places to include in the result. Defaults to null. If negative, it will be treated as 0. If null, no rounding is applied.
115
- * @param {string|null} [maxUnit=null] - Optional unit limit. If provided, restricts conversion to this unit at most (e.g., 'MB' prevents conversion to 'GB' or higher). Must be one of: 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'.
137
+ * @param {'Bytes'|'KB'|'MB'|'GB'|'TB'|'PB'|'EB'|'ZB'|'YB'|null} [maxUnit=null] - Optional unit limit. If provided, restricts conversion to this unit at most (e.g., 'MB' prevents conversion to 'GB' or higher).
116
138
  * @returns {FormattedByteResult} An object with the converted value and its corresponding unit. Returns nulls if input is invalid.
117
139
  *
118
140
  * @example
@@ -124,12 +146,23 @@ function getAge(timeData = 0, now = null) {
124
146
  * // → { unit: 'MB', value: 1024 }
125
147
  */
126
148
  function formatBytes(bytes, decimals = null, maxUnit = null) {
127
- if (typeof bytes !== 'number' || bytes < 0) return { unit: null, value: null };
149
+ if (typeof bytes !== 'number' || !Number.isFinite(bytes) || bytes < 0)
150
+ throw new TypeError('bytes must be a positive number.');
128
151
  if (bytes === 0) return { unit: 'Bytes', value: 0 };
129
152
 
153
+ if (decimals !== null && (typeof decimals !== 'number' || !Number.isFinite(decimals))) {
154
+ throw new TypeError('decimals must be a number or null.');
155
+ }
156
+
130
157
  const k = 1024;
131
158
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
132
159
 
160
+ if (maxUnit !== null) {
161
+ if (typeof maxUnit !== 'string') throw new TypeError('maxUnit must be a string or null.');
162
+ if (!sizes.includes(maxUnit))
163
+ throw new RangeError(`maxUnit must be one of: ${sizes.join(', ')}`);
164
+ }
165
+
133
166
  const maxIndex = maxUnit && sizes.includes(maxUnit) ? sizes.indexOf(maxUnit) : sizes.length - 1;
134
167
  const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), maxIndex);
135
168
 
@@ -168,8 +201,19 @@ function genFibonacciSeq({
168
201
  length = 10,
169
202
  combiner = (a, b) => a + b,
170
203
  } = {}) {
171
- if (!Array.isArray(baseValues) || baseValues.length !== 2)
172
- throw new Error('baseValues must be an array of exactly two numbers');
204
+ if (
205
+ !Array.isArray(baseValues) ||
206
+ baseValues.length !== 2 ||
207
+ !baseValues.every((value) => typeof value === 'number')
208
+ ) {
209
+ throw new Error('baseValues must be an array of exactly two numbers.');
210
+ }
211
+ if (typeof length !== 'number' || !Number.isInteger(length)) {
212
+ throw new RangeError('length must be an integer.');
213
+ }
214
+ if (typeof combiner !== 'function') {
215
+ throw new TypeError('combiner must be a function.');
216
+ }
173
217
 
174
218
  const sequence = [...baseValues.slice(0, 2)];
175
219
 
@@ -192,11 +236,19 @@ function genFibonacciSeq({
192
236
  * @returns {number} The calculated price per unit of the asset.
193
237
  */
194
238
  function calculateMarketcap(originalMarketCap, circulatingSupply) {
195
- if (Number.isNaN(originalMarketCap) || !Number.isFinite(originalMarketCap))
196
- throw new TypeError('Original market cap must be a number.');
197
- if (Number.isNaN(circulatingSupply) || !Number.isFinite(circulatingSupply))
198
- throw new TypeError('Circulating supply must be a number.');
199
- if (circulatingSupply <= 0) throw new Error('Circulating supply must be greater than zero.');
239
+ if (
240
+ typeof originalMarketCap !== 'number' ||
241
+ Number.isNaN(originalMarketCap) ||
242
+ !Number.isFinite(originalMarketCap)
243
+ )
244
+ throw new TypeError('Original market cap must be a finite number.');
245
+ if (
246
+ typeof circulatingSupply !== 'number' ||
247
+ Number.isNaN(circulatingSupply) ||
248
+ !Number.isFinite(circulatingSupply)
249
+ )
250
+ throw new TypeError('Circulating supply must be a finite number.');
251
+ if (circulatingSupply <= 0) throw new RangeError('Circulating supply must be greater than zero.');
200
252
  return originalMarketCap / circulatingSupply;
201
253
  }
202
254
 
@@ -212,8 +264,12 @@ function calculateMarketcap(originalMarketCap, circulatingSupply) {
212
264
  * }}
213
265
  */
214
266
  function compareMarketcap(originalMarketCap, circulatingSupply, newMarketCap) {
215
- if (Number.isNaN(newMarketCap) || !Number.isFinite(newMarketCap))
216
- throw new TypeError('New market cap must be a number.');
267
+ if (
268
+ typeof newMarketCap !== 'number' ||
269
+ Number.isNaN(newMarketCap) ||
270
+ !Number.isFinite(newMarketCap)
271
+ )
272
+ throw new TypeError('New market cap must be a finite number.');
217
273
  const originalPrice = calculateMarketcap(originalMarketCap, circulatingSupply);
218
274
  const newPrice = typeof newMarketCap === 'number' ? newMarketCap / circulatingSupply : NaN;
219
275
  const priceChangePercent =
@@ -76,7 +76,7 @@ export function getAge(timeData?: number | string | Date, now?: Date | null): nu
76
76
  *
77
77
  * @param {number} bytes - The number of bytes to format. Must be a non-negative number.
78
78
  * @param {number|null} [decimals=null] - The number of decimal places to include in the result. Defaults to null. If negative, it will be treated as 0. If null, no rounding is applied.
79
- * @param {string|null} [maxUnit=null] - Optional unit limit. If provided, restricts conversion to this unit at most (e.g., 'MB' prevents conversion to 'GB' or higher). Must be one of: 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'.
79
+ * @param {'Bytes'|'KB'|'MB'|'GB'|'TB'|'PB'|'EB'|'ZB'|'YB'|null} [maxUnit=null] - Optional unit limit. If provided, restricts conversion to this unit at most (e.g., 'MB' prevents conversion to 'GB' or higher).
80
80
  * @returns {FormattedByteResult} An object with the converted value and its corresponding unit. Returns nulls if input is invalid.
81
81
  *
82
82
  * @example
@@ -87,7 +87,7 @@ export function getAge(timeData?: number | string | Date, now?: Date | null): nu
87
87
  * formatBytes(1073741824, 2, 'MB');
88
88
  * // → { unit: 'MB', value: 1024 }
89
89
  */
90
- export function formatBytes(bytes: number, decimals?: number | null, maxUnit?: string | null): FormattedByteResult;
90
+ export function formatBytes(bytes: number, decimals?: number | null, maxUnit?: "Bytes" | "KB" | "MB" | "GB" | "TB" | "PB" | "EB" | "ZB" | "YB" | null): FormattedByteResult;
91
91
  /**
92
92
  * Generates a Fibonacci-like sequence as an array of vectors.
93
93
  *
@@ -34,6 +34,14 @@
34
34
  * ruleOfThree.execute(2, 6, 3, true); // → 4
35
35
  */
36
36
  export function ruleOfThree(val1, val2, val3, inverse = false) {
37
+ if (typeof val1 !== 'number' || !Number.isFinite(val1))
38
+ throw new TypeError('val1 must be a finite number.');
39
+ if (typeof val2 !== 'number' || !Number.isFinite(val2))
40
+ throw new TypeError('val2 must be a finite number.');
41
+ if (typeof val3 !== 'number' || !Number.isFinite(val3))
42
+ throw new TypeError('val3 must be a finite number.');
43
+ if (typeof inverse !== 'boolean')
44
+ throw new TypeError('inverse must be a boolean.');
37
45
  return inverse ? Number(val1 * val2) / val3 : Number(val3 * val2) / val1;
38
46
  }
39
47
  /**
@@ -49,6 +57,10 @@ export function ruleOfThree(val1, val2, val3, inverse = false) {
49
57
  * getSimplePerc(200, 15); // 30
50
58
  */
51
59
  export function getSimplePerc(price, percentage) {
60
+ if (typeof price !== 'number' || !Number.isFinite(price))
61
+ throw new TypeError('price must be a finite number.');
62
+ if (typeof percentage !== 'number' || !Number.isFinite(percentage))
63
+ throw new TypeError('percentage must be a finite number.');
52
64
  return price * (percentage / 100);
53
65
  }
54
66
  /**
@@ -62,6 +74,10 @@ export function getSimplePerc(price, percentage) {
62
74
  * getPercentage(5, 100); // 5
63
75
  */
64
76
  export function getPercentage(part, total) {
77
+ if (typeof part !== 'number' || !Number.isFinite(part))
78
+ throw new TypeError('part must be a finite number.');
79
+ if (typeof total !== 'number' || !Number.isFinite(total))
80
+ throw new TypeError('total must be a finite number.');
65
81
  if (total === 0)
66
82
  return 0;
67
83
  return (part / total) * 100;
@@ -74,22 +90,25 @@ export function getPercentage(part, total) {
74
90
  * @returns {number|null} The age in years, or null if `timeData` is not provided or invalid.
75
91
  */
76
92
  export function getAge(timeData = 0, now = null) {
77
- if (typeof timeData !== 'undefined' && timeData !== null && timeData !== 0) {
78
- const birthDate = new Date(timeData);
79
- if (Number.isNaN(birthDate.getTime()))
80
- return null;
81
- const currentDate = now instanceof Date ? now : new Date();
82
- let age = currentDate.getFullYear() - birthDate.getFullYear();
83
- const currentMonth = currentDate.getMonth();
84
- const birthMonth = birthDate.getMonth();
85
- const currentDay = currentDate.getDate();
86
- const birthDay = birthDate.getDate();
87
- // Adjust if birthday hasn't occurred yet this year
88
- if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay))
89
- age--;
90
- return Math.abs(age);
93
+ if (typeof timeData !== 'number' && typeof timeData !== 'string' && !(timeData instanceof Date)) {
94
+ throw new TypeError('timeData must be a number, string, or Date object.');
91
95
  }
92
- return null;
96
+ if (now !== null && !(now instanceof Date)) {
97
+ throw new TypeError('now must be a Date object or null.');
98
+ }
99
+ const birthDate = new Date(timeData);
100
+ if (Number.isNaN(birthDate.getTime()))
101
+ return null;
102
+ const currentDate = now instanceof Date ? now : new Date();
103
+ let age = currentDate.getFullYear() - birthDate.getFullYear();
104
+ const currentMonth = currentDate.getMonth();
105
+ const birthMonth = birthDate.getMonth();
106
+ const currentDay = currentDate.getDate();
107
+ const birthDay = birthDate.getDate();
108
+ // Adjust if birthday hasn't occurred yet this year
109
+ if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay))
110
+ age--;
111
+ return Math.abs(age);
93
112
  }
94
113
  /**
95
114
  * @typedef {Object} FormattedByteResult
@@ -101,7 +120,7 @@ export function getAge(timeData = 0, now = null) {
101
120
  *
102
121
  * @param {number} bytes - The number of bytes to format. Must be a non-negative number.
103
122
  * @param {number|null} [decimals=null] - The number of decimal places to include in the result. Defaults to null. If negative, it will be treated as 0. If null, no rounding is applied.
104
- * @param {string|null} [maxUnit=null] - Optional unit limit. If provided, restricts conversion to this unit at most (e.g., 'MB' prevents conversion to 'GB' or higher). Must be one of: 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'.
123
+ * @param {'Bytes'|'KB'|'MB'|'GB'|'TB'|'PB'|'EB'|'ZB'|'YB'|null} [maxUnit=null] - Optional unit limit. If provided, restricts conversion to this unit at most (e.g., 'MB' prevents conversion to 'GB' or higher).
105
124
  * @returns {FormattedByteResult} An object with the converted value and its corresponding unit. Returns nulls if input is invalid.
106
125
  *
107
126
  * @example
@@ -113,12 +132,21 @@ export function getAge(timeData = 0, now = null) {
113
132
  * // → { unit: 'MB', value: 1024 }
114
133
  */
115
134
  export function formatBytes(bytes, decimals = null, maxUnit = null) {
116
- if (typeof bytes !== 'number' || bytes < 0)
117
- return { unit: null, value: null };
135
+ if (typeof bytes !== 'number' || !Number.isFinite(bytes) || bytes < 0)
136
+ throw new TypeError('bytes must be a positive number.');
118
137
  if (bytes === 0)
119
138
  return { unit: 'Bytes', value: 0 };
139
+ if (decimals !== null && (typeof decimals !== 'number' || !Number.isFinite(decimals))) {
140
+ throw new TypeError('decimals must be a number or null.');
141
+ }
120
142
  const k = 1024;
121
143
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
144
+ if (maxUnit !== null) {
145
+ if (typeof maxUnit !== 'string')
146
+ throw new TypeError('maxUnit must be a string or null.');
147
+ if (!sizes.includes(maxUnit))
148
+ throw new RangeError(`maxUnit must be one of: ${sizes.join(', ')}`);
149
+ }
122
150
  const maxIndex = maxUnit && sizes.includes(maxUnit) ? sizes.indexOf(maxUnit) : sizes.length - 1;
123
151
  const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), maxIndex);
124
152
  let value = bytes / Math.pow(k, i);
@@ -149,8 +177,17 @@ export function formatBytes(bytes, decimals = null, maxUnit = null) {
149
177
  * @beta
150
178
  */
151
179
  export function genFibonacciSeq({ baseValues = [0, 1], length = 10, combiner = (a, b) => a + b, } = {}) {
152
- if (!Array.isArray(baseValues) || baseValues.length !== 2)
153
- throw new Error('baseValues must be an array of exactly two numbers');
180
+ if (!Array.isArray(baseValues) ||
181
+ baseValues.length !== 2 ||
182
+ !baseValues.every((value) => typeof value === 'number')) {
183
+ throw new Error('baseValues must be an array of exactly two numbers.');
184
+ }
185
+ if (typeof length !== 'number' || !Number.isInteger(length)) {
186
+ throw new RangeError('length must be an integer.');
187
+ }
188
+ if (typeof combiner !== 'function') {
189
+ throw new TypeError('combiner must be a function.');
190
+ }
154
191
  const sequence = [...baseValues.slice(0, 2)];
155
192
  for (let i = 2; i < length; i++) {
156
193
  const next = combiner(sequence[i - 2], sequence[i - 1], i);
@@ -169,12 +206,16 @@ export function genFibonacciSeq({ baseValues = [0, 1], length = 10, combiner = (
169
206
  * @returns {number} The calculated price per unit of the asset.
170
207
  */
171
208
  export function calculateMarketcap(originalMarketCap, circulatingSupply) {
172
- if (Number.isNaN(originalMarketCap) || !Number.isFinite(originalMarketCap))
173
- throw new TypeError('Original market cap must be a number.');
174
- if (Number.isNaN(circulatingSupply) || !Number.isFinite(circulatingSupply))
175
- throw new TypeError('Circulating supply must be a number.');
209
+ if (typeof originalMarketCap !== 'number' ||
210
+ Number.isNaN(originalMarketCap) ||
211
+ !Number.isFinite(originalMarketCap))
212
+ throw new TypeError('Original market cap must be a finite number.');
213
+ if (typeof circulatingSupply !== 'number' ||
214
+ Number.isNaN(circulatingSupply) ||
215
+ !Number.isFinite(circulatingSupply))
216
+ throw new TypeError('Circulating supply must be a finite number.');
176
217
  if (circulatingSupply <= 0)
177
- throw new Error('Circulating supply must be greater than zero.');
218
+ throw new RangeError('Circulating supply must be greater than zero.');
178
219
  return originalMarketCap / circulatingSupply;
179
220
  }
180
221
  /**
@@ -189,8 +230,10 @@ export function calculateMarketcap(originalMarketCap, circulatingSupply) {
189
230
  * }}
190
231
  */
191
232
  export function compareMarketcap(originalMarketCap, circulatingSupply, newMarketCap) {
192
- if (Number.isNaN(newMarketCap) || !Number.isFinite(newMarketCap))
193
- throw new TypeError('New market cap must be a number.');
233
+ if (typeof newMarketCap !== 'number' ||
234
+ Number.isNaN(newMarketCap) ||
235
+ !Number.isFinite(newMarketCap))
236
+ throw new TypeError('New market cap must be a finite number.');
194
237
  const originalPrice = calculateMarketcap(originalMarketCap, circulatingSupply);
195
238
  const newPrice = typeof newMarketCap === 'number' ? newMarketCap / circulatingSupply : NaN;
196
239
  const priceChangePercent = typeof newMarketCap === 'number' ? ((newPrice - originalPrice) / originalPrice) * 100 : NaN;
@@ -6,15 +6,25 @@
6
6
  * @param {string} str - The input string to perform replacements on.
7
7
  * @param {RegExp} regex - The regular expression to match substrings for replacement.
8
8
  * @param {Function} asyncFn - An asynchronous function that returns a replacement for each match.
9
- * It receives the same arguments as a standard `replace` callback.
9
+ * It receives the same arguments as a standard `replace` callback.
10
10
  * @returns {Promise<string>} The resulting string with all async replacements applied.
11
11
  *
12
12
  * @example
13
13
  * await asyncReplace("Hello @user1 and @user2!", /@\w+/g, async (mention) => {
14
- * return await getUserNameFromMention(mention);
14
+ * return await getUserNameFromMention(mention);
15
15
  * });
16
16
  */
17
17
  async function asyncReplace(str, regex, asyncFn) {
18
+ if (typeof str !== 'string') {
19
+ throw new TypeError(`Expected a string for 'str', but received ${typeof str}`);
20
+ }
21
+ if (!(regex instanceof RegExp)) {
22
+ throw new TypeError(`Expected a RegExp for 'regex', but received ${typeof regex}`);
23
+ }
24
+ if (typeof asyncFn !== 'function') {
25
+ throw new TypeError(`Expected a function for 'asyncFn', but received ${typeof asyncFn}`);
26
+ }
27
+
18
28
  /**
19
29
  * @type {any[]}
20
30
  */
@@ -42,6 +52,10 @@ async function asyncReplace(str, regex, asyncFn) {
42
52
  * @returns {string} The string converted to title case.
43
53
  */
44
54
  function toTitleCase(str) {
55
+ if (typeof str !== 'string') {
56
+ throw new TypeError(`Expected a string for 'str', but received ${typeof str}`);
57
+ }
58
+
45
59
  return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
46
60
  }
47
61
 
@@ -55,6 +69,10 @@ function toTitleCase(str) {
55
69
  * @returns {string} The string converted to title case with the first letter in lowercase.
56
70
  */
57
71
  function toTitleCaseLowerFirst(str) {
72
+ if (typeof str !== 'string') {
73
+ throw new TypeError(`Expected a string for 'str', but received ${typeof str}`);
74
+ }
75
+
58
76
  const titleCased = str.replace(
59
77
  /\w\S*/g,
60
78
  (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(),
@@ -101,6 +119,15 @@ function addAiMarkerShortcut({ key = 'a', className = 'detect-made-by-ai' } = {}
101
119
  '[AiMarkerShortcut] Environment does not support the DOM. This function must be run in a browser.',
102
120
  );
103
121
 
122
+ if (typeof key !== 'string') {
123
+ throw new TypeError(`Expected a string for 'config.key', but received ${typeof key}`);
124
+ }
125
+ if (typeof className !== 'string') {
126
+ throw new TypeError(
127
+ `Expected a string for 'config.className', but received ${typeof className}`,
128
+ );
129
+ }
130
+
104
131
  /** @type {(this: Document, ev: KeyboardEvent) => any} */
105
132
  const keydownEvent = function (event) {
106
133
  if (event.ctrlKey && event.altKey && event.key.toLowerCase() === key) {
@@ -128,7 +155,7 @@ function addAiMarkerShortcut({ key = 'a', className = 'detect-made-by-ai' } = {}
128
155
  * @param {string} text - The input text to be trimmed.
129
156
  * @param {number} limit - The maximum number of characters allowed.
130
157
  * @param {number} [safeCutZone=0.6] - A decimal between 0 and 1 representing the minimal acceptable position
131
- * (as a fraction of `limit`) to cut at a space. Defaults to 0.6.
158
+ * (as a fraction of `limit`) to cut at a space. Defaults to 0.6.
132
159
  * @returns {string} - The trimmed text, possibly ending with an ellipsis ("...").
133
160
  * @throws {TypeError} - Throws if `text` is not a string.
134
161
  * @throws {TypeError} - Throws if `limit` is not a positive integer.
@@ -162,18 +189,48 @@ function safeTextTrim(text, limit, safeCutZone = 0.6) {
162
189
  }
163
190
 
164
191
  /**
165
- * Diff two string objects.
166
- * @param {Record<string,string>} oldStrings
167
- * @param {Record<string,string>} newStrings
192
+ * @template {Record<string, any>} CompareValue
193
+ * @typedef {Object} DiffStringsModifiedValue
194
+ * @property {CompareValue[keyof CompareValue]} old - The value before the modification.
195
+ * @property {CompareValue[keyof CompareValue]} new - The new value after the modification.
196
+ */
197
+
198
+ /**
199
+ * @template {Record<string, any>} CompareValue
200
+ * @typedef {Object} DiffStringsData
201
+ * @property {Partial<CompareValue>} added - Properties that only exist in the new object.
202
+ * @property {Partial<CompareValue>} removed - Properties that only existed in the old object.
203
+ * @property {Partial<Record<keyof CompareValue, DiffStringsModifiedValue<CompareValue>>>} modified - Properties that changed, containing their old and new values.
204
+ */
205
+
206
+ /**
207
+ * Diff two objects.
208
+ * @template {Record<string, any>} CompareValue1
209
+ * @template {Record<string, any>} CompareValue2
210
+ * @param {CompareValue1} oldStrings - The original/old object for comparison.
211
+ * @param {CompareValue2} newStrings - The new object for comparison.
212
+ * @returns {DiffStringsData<CompareValue1 & CompareValue2>} An object containing what was added, removed, and modified.
168
213
  */
169
- function diffStrings(oldStrings, newStrings) {
170
- /** @type {Record<string,Record<string,string|Record<string,string>>>}} */
214
+ function diffObjList(oldStrings, newStrings) {
215
+ if (typeof oldStrings !== 'object' || oldStrings === null || Array.isArray(oldStrings)) {
216
+ throw new TypeError(
217
+ `Expected an object for 'oldStrings', but received ${oldStrings === null ? 'null' : typeof oldStrings}`,
218
+ );
219
+ }
220
+ if (typeof newStrings !== 'object' || newStrings === null || Array.isArray(newStrings)) {
221
+ throw new TypeError(
222
+ `Expected an object for 'newStrings', but received ${newStrings === null ? 'null' : typeof newStrings}`,
223
+ );
224
+ }
225
+
226
+ /** @type {DiffStringsData<CompareValue1 & CompareValue2>} */
171
227
  const changes = { added: {}, removed: {}, modified: {} };
172
228
 
173
229
  // detect removed and modified
174
230
  for (const prop in oldStrings) {
175
231
  if (!(prop in newStrings)) {
176
232
  changes.removed[prop] = oldStrings[prop];
233
+ // @ts-ignore
177
234
  } else if (oldStrings[prop] !== newStrings[prop]) {
178
235
  changes.modified[prop] = { old: oldStrings[prop], new: newStrings[prop] };
179
236
  }
@@ -189,32 +246,20 @@ function diffStrings(oldStrings, newStrings) {
189
246
  return changes;
190
247
  }
191
248
 
192
- /*
193
- import { useEffect } from "react";
194
-
195
- function KeyPressHandler() {
196
- useEffect(() => {
197
- const handleKeyDown = (event) => {
198
- if (event.ctrlKey && event.altKey && event.key.toLowerCase() === "a") {
199
- event.preventDefault();
200
- document.body.classList.toggle("detect-made-by-ai");
201
- }
202
- };
203
-
204
- document.addEventListener("keydown", handleKeyDown);
205
- return () => {
206
- document.removeEventListener("keydown", handleKeyDown);
207
- };
208
- }, []);
209
-
210
- return null;
211
- }
212
-
213
- export default KeyPressHandler;
214
- */
249
+ /**
250
+ * Diff two objects.
251
+ * @template {Record<string, any>} CompareValue1
252
+ * @template {Record<string, any>} CompareValue2
253
+ * @param {CompareValue1} oldStrings - The original/old object for comparison.
254
+ * @param {CompareValue2} newStrings - The new object for comparison.
255
+ * @returns {DiffStringsData<CompareValue1 & CompareValue2>} An object containing what was added, removed, and modified.
256
+ * @deprecated Function rename! Use {@link diffObjList} instead.
257
+ */
258
+ const diffStrings = diffObjList;
215
259
 
216
260
  exports.addAiMarkerShortcut = addAiMarkerShortcut;
217
261
  exports.asyncReplace = asyncReplace;
262
+ exports.diffObjList = diffObjList;
218
263
  exports.diffStrings = diffStrings;
219
264
  exports.safeTextTrim = safeTextTrim;
220
265
  exports.toTitleCase = toTitleCase;
@@ -4,12 +4,12 @@
4
4
  * @param {string} str - The input string to perform replacements on.
5
5
  * @param {RegExp} regex - The regular expression to match substrings for replacement.
6
6
  * @param {Function} asyncFn - An asynchronous function that returns a replacement for each match.
7
- * It receives the same arguments as a standard `replace` callback.
7
+ * It receives the same arguments as a standard `replace` callback.
8
8
  * @returns {Promise<string>} The resulting string with all async replacements applied.
9
9
  *
10
10
  * @example
11
11
  * await asyncReplace("Hello @user1 and @user2!", /@\w+/g, async (mention) => {
12
- * return await getUserNameFromMention(mention);
12
+ * return await getUserNameFromMention(mention);
13
13
  * });
14
14
  */
15
15
  export function asyncReplace(str: string, regex: RegExp, asyncFn: Function): Promise<string>;
@@ -79,7 +79,7 @@ export function addAiMarkerShortcut({ key, className }?: {
79
79
  * @param {string} text - The input text to be trimmed.
80
80
  * @param {number} limit - The maximum number of characters allowed.
81
81
  * @param {number} [safeCutZone=0.6] - A decimal between 0 and 1 representing the minimal acceptable position
82
- * (as a fraction of `limit`) to cut at a space. Defaults to 0.6.
82
+ * (as a fraction of `limit`) to cut at a space. Defaults to 0.6.
83
83
  * @returns {string} - The trimmed text, possibly ending with an ellipsis ("...").
84
84
  * @throws {TypeError} - Throws if `text` is not a string.
85
85
  * @throws {TypeError} - Throws if `limit` is not a positive integer.
@@ -87,9 +87,71 @@ export function addAiMarkerShortcut({ key, className }?: {
87
87
  */
88
88
  export function safeTextTrim(text: string, limit: number, safeCutZone?: number): string;
89
89
  /**
90
- * Diff two string objects.
91
- * @param {Record<string,string>} oldStrings
92
- * @param {Record<string,string>} newStrings
90
+ * @template {Record<string, any>} CompareValue
91
+ * @typedef {Object} DiffStringsModifiedValue
92
+ * @property {CompareValue[keyof CompareValue]} old - The value before the modification.
93
+ * @property {CompareValue[keyof CompareValue]} new - The new value after the modification.
93
94
  */
94
- export function diffStrings(oldStrings: Record<string, string>, newStrings: Record<string, string>): Record<string, Record<string, string | Record<string, string>>>;
95
+ /**
96
+ * @template {Record<string, any>} CompareValue
97
+ * @typedef {Object} DiffStringsData
98
+ * @property {Partial<CompareValue>} added - Properties that only exist in the new object.
99
+ * @property {Partial<CompareValue>} removed - Properties that only existed in the old object.
100
+ * @property {Partial<Record<keyof CompareValue, DiffStringsModifiedValue<CompareValue>>>} modified - Properties that changed, containing their old and new values.
101
+ */
102
+ /**
103
+ * Diff two objects.
104
+ * @template {Record<string, any>} CompareValue1
105
+ * @template {Record<string, any>} CompareValue2
106
+ * @param {CompareValue1} oldStrings - The original/old object for comparison.
107
+ * @param {CompareValue2} newStrings - The new object for comparison.
108
+ * @returns {DiffStringsData<CompareValue1 & CompareValue2>} An object containing what was added, removed, and modified.
109
+ */
110
+ export function diffObjList<CompareValue1_1 extends Record<string, any>, CompareValue2_1 extends Record<string, any>>(oldStrings: CompareValue1_1, newStrings: CompareValue2_1): DiffStringsData<CompareValue1_1 & CompareValue2_1>;
111
+ /**
112
+ * @template {Record<string, any>} CompareValue
113
+ * @typedef {Object} DiffStringsModifiedValue
114
+ * @property {CompareValue[keyof CompareValue]} old - The value before the modification.
115
+ * @property {CompareValue[keyof CompareValue]} new - The new value after the modification.
116
+ */
117
+ /**
118
+ * @template {Record<string, any>} CompareValue
119
+ * @typedef {Object} DiffStringsData
120
+ * @property {Partial<CompareValue>} added - Properties that only exist in the new object.
121
+ * @property {Partial<CompareValue>} removed - Properties that only existed in the old object.
122
+ * @property {Partial<Record<keyof CompareValue, DiffStringsModifiedValue<CompareValue>>>} modified - Properties that changed, containing their old and new values.
123
+ */
124
+ /**
125
+ * Diff two objects.
126
+ * @template {Record<string, any>} CompareValue1
127
+ * @template {Record<string, any>} CompareValue2
128
+ * @param {CompareValue1} oldStrings - The original/old object for comparison.
129
+ * @param {CompareValue2} newStrings - The new object for comparison.
130
+ * @returns {DiffStringsData<CompareValue1 & CompareValue2>} An object containing what was added, removed, and modified.
131
+ */
132
+ export function diffStrings<CompareValue1_1 extends Record<string, any>, CompareValue2_1 extends Record<string, any>>(oldStrings: CompareValue1_1, newStrings: CompareValue2_1): DiffStringsData<CompareValue1_1 & CompareValue2_1>;
133
+ export type DiffStringsModifiedValue<CompareValue extends Record<string, any>> = {
134
+ /**
135
+ * - The value before the modification.
136
+ */
137
+ old: CompareValue[keyof CompareValue];
138
+ /**
139
+ * - The new value after the modification.
140
+ */
141
+ new: CompareValue[keyof CompareValue];
142
+ };
143
+ export type DiffStringsData<CompareValue extends Record<string, any>> = {
144
+ /**
145
+ * - Properties that only exist in the new object.
146
+ */
147
+ added: Partial<CompareValue>;
148
+ /**
149
+ * - Properties that only existed in the old object.
150
+ */
151
+ removed: Partial<CompareValue>;
152
+ /**
153
+ * - Properties that changed, containing their old and new values.
154
+ */
155
+ modified: Partial<Record<keyof CompareValue, DiffStringsModifiedValue<CompareValue>>>;
156
+ };
95
157
  //# sourceMappingURL=text.d.mts.map