tiny-essentials 1.21.1 → 1.21.3

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.
@@ -0,0 +1,2 @@
1
+ import TinySimpleDice from '../libs/TinySimpleDice.mjs';
2
+ export { TinySimpleDice };
package/dist/v1/index.cjs CHANGED
@@ -45,6 +45,7 @@ var TinyInventoryTrader = require('./libs/TinyInventoryTrader.cjs');
45
45
  var TinyCookieConsent = require('./libs/TinyCookieConsent.cjs');
46
46
  var TinyI18 = require('./libs/TinyI18.cjs');
47
47
  var TinyNeedBar = require('./libs/TinyNeedBar.cjs');
48
+ var TinySimpleDice = require('./libs/TinySimpleDice.cjs');
48
49
 
49
50
 
50
51
 
@@ -52,6 +53,7 @@ exports.asyncReplace = replaceAsync;
52
53
  exports.TinyLevelUp = userLevel;
53
54
  exports.arraySortPositions = arraySortPositions;
54
55
  exports.shuffleArray = array.shuffleArray;
56
+ exports.breakdownDuration = clock.breakdownDuration;
55
57
  exports.formatCustomTimer = clock.formatCustomTimer;
56
58
  exports.formatDayTimer = clock.formatDayTimer;
57
59
  exports.formatTimer = clock.formatTimer;
@@ -166,3 +168,4 @@ exports.TinyInventoryTrader = TinyInventoryTrader;
166
168
  exports.TinyCookieConsent = TinyCookieConsent;
167
169
  exports.TinyI18 = TinyI18;
168
170
  exports.TinyNeedBar = TinyNeedBar;
171
+ exports.TinySimpleDice = TinySimpleDice;
@@ -1,3 +1,4 @@
1
+ import TinySimpleDice from './libs/TinySimpleDice.mjs';
1
2
  import TinyNeedBar from './libs/TinyNeedBar.mjs';
2
3
  import TinyI18 from './libs/TinyI18.mjs';
3
4
  import TinyCookieConsent from './libs/TinyCookieConsent.mjs';
@@ -30,6 +31,7 @@ import TinyRateLimiter from './libs/TinyRateLimiter.mjs';
30
31
  import ColorSafeStringify from './libs/ColorSafeStringify.mjs';
31
32
  import TinyPromiseQueue from './libs/TinyPromiseQueue.mjs';
32
33
  import TinyLevelUp from '../legacy/libs/userLevel.mjs';
34
+ import { breakdownDuration } from './basics/clock.mjs';
33
35
  import { calculateMarketcap } from './basics/simpleMath.mjs';
34
36
  import { compareMarketcap } from './basics/simpleMath.mjs';
35
37
  import { getPercentage } from './basics/simpleMath.mjs';
@@ -116,5 +118,5 @@ import { getTimeDuration } from './basics/clock.mjs';
116
118
  import { shuffleArray } from './basics/array.mjs';
117
119
  import { toTitleCase } from './basics/text.mjs';
118
120
  import { toTitleCaseLowerFirst } from './basics/text.mjs';
119
- export { TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
121
+ export { TinySimpleDice, TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, breakdownDuration, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
120
122
  //# sourceMappingURL=index.d.mts.map
package/dist/v1/index.mjs CHANGED
@@ -2,7 +2,7 @@ import asyncReplace from '../legacy/libs/replaceAsync.mjs';
2
2
  import TinyLevelUp from '../legacy/libs/userLevel.mjs';
3
3
  import arraySortPositions from '../legacy/libs/arraySortPositions.mjs';
4
4
  import { shuffleArray } from './basics/array.mjs';
5
- import { formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, } from './basics/clock.mjs';
5
+ import { breakdownDuration, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, } from './basics/clock.mjs';
6
6
  import { extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, objType, checkObj, } from './basics/objFilter.mjs';
7
7
  import { countObj, isJsonObject } from './basics/objChecker.mjs';
8
8
  import { documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, } from './basics/fullScreen.mjs';
@@ -43,4 +43,5 @@ import TinyInventoryTrader from './libs/TinyInventoryTrader.mjs';
43
43
  import TinyCookieConsent from './libs/TinyCookieConsent.mjs';
44
44
  import TinyI18 from './libs/TinyI18.mjs';
45
45
  import TinyNeedBar from './libs/TinyNeedBar.mjs';
46
- export { TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
46
+ import TinySimpleDice from './libs/TinySimpleDice.mjs';
47
+ export { TinySimpleDice, TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, breakdownDuration, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
@@ -633,6 +633,17 @@ class TinyHtml {
633
633
 
634
634
  //////////////////////////////////////////////////////////////////
635
635
 
636
+ /**
637
+ * Iterates over all elements, executing the provided callback on each.
638
+ * @param {(element: TinyHtml, index: number, items: TinyHtml[]) => void} callback - Function invoked for each element.
639
+ * @returns {TinyHtml} The current instance for chaining.
640
+ */
641
+ forEach(callback) {
642
+ const elems = this.getAll().map((el, index) => this.extract(index));
643
+ for (const index in elems) callback(elems[index], Number(index), elems);
644
+ return this;
645
+ }
646
+
636
647
  /**
637
648
  * Returns the current target held by this instance.
638
649
  *
@@ -1331,8 +1342,30 @@ class TinyHtml {
1331
1342
 
1332
1343
  //////////////////////////////////////////////////////////////////
1333
1344
 
1334
- /** @type {ElementDataStore} */
1335
- _data = {};
1345
+ /**
1346
+ * Internal data storage for element information.
1347
+ * @type {ElementDataStore}
1348
+ */
1349
+ #data = {};
1350
+
1351
+ /**
1352
+ * Returns a shallow copy of the internal data.
1353
+ * @type {ElementDataStore}
1354
+ */
1355
+ get _data() {
1356
+ return { ...this.#data };
1357
+ }
1358
+
1359
+ /**
1360
+ * Replaces the internal data with a new object.
1361
+ * @param {ElementDataStore} value - Must be a non-null object.
1362
+ * @throws {Error} If the value is not a valid object.
1363
+ */
1364
+ set _data(value) {
1365
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
1366
+ throw new Error('value must be a non-null object.');
1367
+ this.#data = value;
1368
+ }
1336
1369
 
1337
1370
  /**
1338
1371
  * Internal data selectors for accessing public or private data stores.
@@ -1353,7 +1386,7 @@ class TinyHtml {
1353
1386
  private: (where, el) => {
1354
1387
  if (!(el instanceof TinyHtml))
1355
1388
  throw new Error(`Element must be a TinyHtml instance to execute ${where}().`);
1356
- return el._data;
1389
+ return el.#data;
1357
1390
  },
1358
1391
  };
1359
1392
 
@@ -2039,6 +2039,12 @@ declare class TinyHtml {
2039
2039
  * @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
2040
2040
  */
2041
2041
  getElementsByTagNameNS(localName: string, namespaceURI?: string | null): TinyHtml;
2042
+ /**
2043
+ * Iterates over all elements, executing the provided callback on each.
2044
+ * @param {(element: TinyHtml, index: number, items: TinyHtml[]) => void} callback - Function invoked for each element.
2045
+ * @returns {TinyHtml} The current instance for chaining.
2046
+ */
2047
+ forEach(callback: (element: TinyHtml, index: number, items: TinyHtml[]) => void): TinyHtml;
2042
2048
  /**
2043
2049
  * Returns the current target held by this instance.
2044
2050
  *
@@ -2127,8 +2133,17 @@ declare class TinyHtml {
2127
2133
  * @returns {boolean} `true` if both elements are the same DOM node; otherwise, `false`.
2128
2134
  */
2129
2135
  isSameDom(elem: TinyNode): boolean;
2130
- /** @type {ElementDataStore} */
2131
- _data: ElementDataStore;
2136
+ /**
2137
+ * Replaces the internal data with a new object.
2138
+ * @param {ElementDataStore} value - Must be a non-null object.
2139
+ * @throws {Error} If the value is not a valid object.
2140
+ */
2141
+ set _data(value: ElementDataStore);
2142
+ /**
2143
+ * Returns a shallow copy of the internal data.
2144
+ * @type {ElementDataStore}
2145
+ */
2146
+ get _data(): ElementDataStore;
2132
2147
  /**
2133
2148
  * Retrieves data associated with a DOM element.
2134
2149
  *
@@ -550,6 +550,17 @@ class TinyHtml {
550
550
  return TinyHtml.getByTagNameNS(localName, namespaceURI, TinyHtml._preElem(this, 'getByTagNameNS'));
551
551
  }
552
552
  //////////////////////////////////////////////////////////////////
553
+ /**
554
+ * Iterates over all elements, executing the provided callback on each.
555
+ * @param {(element: TinyHtml, index: number, items: TinyHtml[]) => void} callback - Function invoked for each element.
556
+ * @returns {TinyHtml} The current instance for chaining.
557
+ */
558
+ forEach(callback) {
559
+ const elems = this.getAll().map((el, index) => this.extract(index));
560
+ for (const index in elems)
561
+ callback(elems[index], Number(index), elems);
562
+ return this;
563
+ }
553
564
  /**
554
565
  * Returns the current target held by this instance.
555
566
  *
@@ -1153,8 +1164,28 @@ class TinyHtml {
1153
1164
  return TinyHtml.isSameDom(this, elem);
1154
1165
  }
1155
1166
  //////////////////////////////////////////////////////////////////
1156
- /** @type {ElementDataStore} */
1157
- _data = {};
1167
+ /**
1168
+ * Internal data storage for element information.
1169
+ * @type {ElementDataStore}
1170
+ */
1171
+ #data = {};
1172
+ /**
1173
+ * Returns a shallow copy of the internal data.
1174
+ * @type {ElementDataStore}
1175
+ */
1176
+ get _data() {
1177
+ return { ...this.#data };
1178
+ }
1179
+ /**
1180
+ * Replaces the internal data with a new object.
1181
+ * @param {ElementDataStore} value - Must be a non-null object.
1182
+ * @throws {Error} If the value is not a valid object.
1183
+ */
1184
+ set _data(value) {
1185
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
1186
+ throw new Error('value must be a non-null object.');
1187
+ this.#data = value;
1188
+ }
1158
1189
  /**
1159
1190
  * Internal data selectors for accessing public or private data stores.
1160
1191
  *
@@ -1174,7 +1205,7 @@ class TinyHtml {
1174
1205
  private: (where, el) => {
1175
1206
  if (!(el instanceof TinyHtml))
1176
1207
  throw new Error(`Element must be a TinyHtml instance to execute ${where}().`);
1177
- return el._data;
1208
+ return el.#data;
1178
1209
  },
1179
1210
  };
1180
1211
  /**
@@ -93,6 +93,8 @@ class TinyNeedBar {
93
93
  * @param {number} value - New maximum value.
94
94
  */
95
95
  set maxValue(value) {
96
+ if (typeof value !== 'number' || Number.isNaN(value) || value <= 0)
97
+ throw new TypeError('maxValue must be a positive number.');
96
98
  this.#maxValue = value;
97
99
  this.#currentValue = Math.min(this.#currentValue, value);
98
100
  }
@@ -123,6 +125,8 @@ class TinyNeedBar {
123
125
  * @param {number} value - New infinite value.
124
126
  */
125
127
  set infiniteValue(value) {
128
+ if (typeof value !== 'number' || Number.isNaN(value))
129
+ throw new TypeError('infiniteValue must be a number.');
126
130
  this.#infiniteValue = value;
127
131
  this.#currentValue = Math.max(0, value);
128
132
  this.#currentValue = Math.min(this.#currentValue, this.#maxValue);
@@ -146,6 +150,9 @@ class TinyNeedBar {
146
150
  * @param {number} [baseDecayMulti=1] - Multiplier applied to the base decay.
147
151
  */
148
152
  constructor(maxValue = 100, baseDecay = 1, baseDecayMulti = 1) {
153
+ if (typeof maxValue !== 'number' || Number.isNaN(maxValue) || maxValue <= 0)
154
+ throw new TypeError('maxValue must be a positive number.');
155
+
149
156
  this.#maxValue = maxValue;
150
157
  this.setFactor('main', baseDecay, baseDecayMulti);
151
158
 
@@ -161,6 +168,7 @@ class TinyNeedBar {
161
168
  * @throws {Error} If the factor does not exist.
162
169
  */
163
170
  getFactor(key) {
171
+ if (typeof key !== 'string' || !key) throw new TypeError('Key must be a non-empty string.');
164
172
  const result = this.#factors.get(key);
165
173
  if (!result) throw new Error(`Factor with key "${key}" not found.`);
166
174
  return { ...result };
@@ -173,6 +181,7 @@ class TinyNeedBar {
173
181
  * @returns {boolean} `true` if the factor exists, otherwise `false`.
174
182
  */
175
183
  hasFactor(key) {
184
+ if (typeof key !== 'string' || !key) throw new TypeError('Key must be a non-empty string.');
176
185
  return this.#factors.has(key);
177
186
  }
178
187
 
@@ -184,6 +193,11 @@ class TinyNeedBar {
184
193
  * @param {number} [multiplier=1] - Multiplier applied to the amount.
185
194
  */
186
195
  setFactor(key, amount, multiplier = 1) {
196
+ if (typeof key !== 'string' || !key) throw new TypeError('Key must be a non-empty string.');
197
+ if (typeof amount !== 'number' || Number.isNaN(amount))
198
+ throw new TypeError('Amount must be a valid number.');
199
+ if (typeof multiplier !== 'number' || Number.isNaN(multiplier))
200
+ throw new TypeError('Multiplier must be a valid number.');
187
201
  this.#factors.set(key, { amount, multiplier });
188
202
  }
189
203
 
@@ -191,23 +205,22 @@ class TinyNeedBar {
191
205
  * Removes a decay factor by its key.
192
206
  *
193
207
  * @param {string} key - The factor key to remove.
208
+ * @returns {boolean} Returns `true` if the factor existed and was successfully removed,
209
+ * or `false` if the factor did not exist.
194
210
  */
195
211
  removeFactor(key) {
196
- this.#factors.delete(key);
212
+ if (typeof key !== 'string' || !key) throw new TypeError('Key must be a non-empty string.');
213
+ return this.#factors.delete(key);
197
214
  }
198
215
 
199
216
  /**
200
- * Executes one tick of decay, applying all active factors.
217
+ * Applies a total decay value to the bar and updates both current and infinite values.
218
+ * This is a private helper used by the public tick methods.
201
219
  *
202
- * @returns {TickResult}
220
+ * @param {number} removedTotal - The total amount to remove from the bar during this tick.
221
+ * @returns {TickResult} An object containing detailed information about the tick.
203
222
  */
204
- tick() {
205
- let removedTotal = 0;
206
-
207
- for (let [_, factor] of this.#factors.entries()) {
208
- removedTotal += factor.amount * factor.multiplier;
209
- }
210
-
223
+ #tick(removedTotal) {
211
224
  const prevValue = this.#infiniteValue;
212
225
  this.#infiniteValue -= removedTotal;
213
226
  this.#currentValue = Math.max(0, this.#currentValue - removedTotal);
@@ -224,6 +237,66 @@ class TinyNeedBar {
224
237
  };
225
238
  }
226
239
 
240
+ /**
241
+ * Executes one tick of decay, applying all active factors.
242
+ *
243
+ * @returns {TickResult}
244
+ */
245
+ tick() {
246
+ let removedTotal = 0;
247
+ for (let [_, factor] of this.#factors.entries()) {
248
+ removedTotal += factor.amount * factor.multiplier;
249
+ }
250
+ return this.#tick(removedTotal);
251
+ }
252
+
253
+ /**
254
+ * Executes one tick of decay using a temporary factor.
255
+ *
256
+ * @param {BarFactor} tempFactor - Temporary factor to apply only in this tick.
257
+ * @returns {TickResult}
258
+ */
259
+ tickWithTempFactor(tempFactor) {
260
+ if (typeof tempFactor !== 'object' || tempFactor === null)
261
+ throw new TypeError('You must provide a valid factor object.');
262
+ if (typeof tempFactor.amount !== 'number' || Number.isNaN(tempFactor.amount))
263
+ throw new TypeError('Temp factor "amount" must be a valid number.');
264
+ if (
265
+ 'multiplier' in tempFactor &&
266
+ (typeof tempFactor.multiplier !== 'number' || Number.isNaN(tempFactor.multiplier))
267
+ )
268
+ throw new TypeError('Temp factor "multiplier" must be a valid number if provided.');
269
+
270
+ let removedTotal = 0;
271
+ for (let [_, factor] of this.#factors.entries()) {
272
+ removedTotal += factor.amount * factor.multiplier;
273
+ }
274
+ if (tempFactor) removedTotal += tempFactor.amount * (tempFactor.multiplier ?? 1);
275
+ return this.#tick(removedTotal);
276
+ }
277
+
278
+ /**
279
+ * Executes one tick using only the specified factor.
280
+ *
281
+ * @param {BarFactor} factor - The single factor to apply.
282
+ * @returns {TickResult}
283
+ */
284
+ tickSingleFactor(factor) {
285
+ if (typeof factor !== 'object' || factor === null)
286
+ throw new TypeError('You must provide a valid factor object.');
287
+ if (typeof factor.amount !== 'number' || Number.isNaN(factor.amount))
288
+ throw new TypeError('Temp factor "amount" must be a valid number.');
289
+ if (
290
+ 'multiplier' in factor &&
291
+ (typeof factor.multiplier !== 'number' || Number.isNaN(factor.multiplier))
292
+ )
293
+ throw new TypeError('Temp factor "multiplier" must be a valid number if provided.');
294
+
295
+ if (!factor) throw new Error('You must provide a factor to apply.');
296
+ const removedTotal = factor.amount * (factor.multiplier ?? 1);
297
+ return this.#tick(removedTotal);
298
+ }
299
+
227
300
  /**
228
301
  * Serializes the current state of the need bar.
229
302
  * @returns {SerializedData}
@@ -196,14 +196,30 @@ declare class TinyNeedBar {
196
196
  * Removes a decay factor by its key.
197
197
  *
198
198
  * @param {string} key - The factor key to remove.
199
+ * @returns {boolean} Returns `true` if the factor existed and was successfully removed,
200
+ * or `false` if the factor did not exist.
199
201
  */
200
- removeFactor(key: string): void;
202
+ removeFactor(key: string): boolean;
201
203
  /**
202
204
  * Executes one tick of decay, applying all active factors.
203
205
  *
204
206
  * @returns {TickResult}
205
207
  */
206
208
  tick(): TickResult;
209
+ /**
210
+ * Executes one tick of decay using a temporary factor.
211
+ *
212
+ * @param {BarFactor} tempFactor - Temporary factor to apply only in this tick.
213
+ * @returns {TickResult}
214
+ */
215
+ tickWithTempFactor(tempFactor: BarFactor): TickResult;
216
+ /**
217
+ * Executes one tick using only the specified factor.
218
+ *
219
+ * @param {BarFactor} factor - The single factor to apply.
220
+ * @returns {TickResult}
221
+ */
222
+ tickSingleFactor(factor: BarFactor): TickResult;
207
223
  /**
208
224
  * Serializes the current state of the need bar.
209
225
  * @returns {SerializedData}
@@ -82,6 +82,8 @@ class TinyNeedBar {
82
82
  * @param {number} value - New maximum value.
83
83
  */
84
84
  set maxValue(value) {
85
+ if (typeof value !== 'number' || Number.isNaN(value) || value <= 0)
86
+ throw new TypeError('maxValue must be a positive number.');
85
87
  this.#maxValue = value;
86
88
  this.#currentValue = Math.min(this.#currentValue, value);
87
89
  }
@@ -109,6 +111,8 @@ class TinyNeedBar {
109
111
  * @param {number} value - New infinite value.
110
112
  */
111
113
  set infiniteValue(value) {
114
+ if (typeof value !== 'number' || Number.isNaN(value))
115
+ throw new TypeError('infiniteValue must be a number.');
112
116
  this.#infiniteValue = value;
113
117
  this.#currentValue = Math.max(0, value);
114
118
  this.#currentValue = Math.min(this.#currentValue, this.#maxValue);
@@ -130,6 +134,8 @@ class TinyNeedBar {
130
134
  * @param {number} [baseDecayMulti=1] - Multiplier applied to the base decay.
131
135
  */
132
136
  constructor(maxValue = 100, baseDecay = 1, baseDecayMulti = 1) {
137
+ if (typeof maxValue !== 'number' || Number.isNaN(maxValue) || maxValue <= 0)
138
+ throw new TypeError('maxValue must be a positive number.');
133
139
  this.#maxValue = maxValue;
134
140
  this.setFactor('main', baseDecay, baseDecayMulti);
135
141
  this.#currentValue = maxValue;
@@ -143,6 +149,8 @@ class TinyNeedBar {
143
149
  * @throws {Error} If the factor does not exist.
144
150
  */
145
151
  getFactor(key) {
152
+ if (typeof key !== 'string' || !key)
153
+ throw new TypeError('Key must be a non-empty string.');
146
154
  const result = this.#factors.get(key);
147
155
  if (!result)
148
156
  throw new Error(`Factor with key "${key}" not found.`);
@@ -155,6 +163,8 @@ class TinyNeedBar {
155
163
  * @returns {boolean} `true` if the factor exists, otherwise `false`.
156
164
  */
157
165
  hasFactor(key) {
166
+ if (typeof key !== 'string' || !key)
167
+ throw new TypeError('Key must be a non-empty string.');
158
168
  return this.#factors.has(key);
159
169
  }
160
170
  /**
@@ -165,26 +175,34 @@ class TinyNeedBar {
165
175
  * @param {number} [multiplier=1] - Multiplier applied to the amount.
166
176
  */
167
177
  setFactor(key, amount, multiplier = 1) {
178
+ if (typeof key !== 'string' || !key)
179
+ throw new TypeError('Key must be a non-empty string.');
180
+ if (typeof amount !== 'number' || Number.isNaN(amount))
181
+ throw new TypeError('Amount must be a valid number.');
182
+ if (typeof multiplier !== 'number' || Number.isNaN(multiplier))
183
+ throw new TypeError('Multiplier must be a valid number.');
168
184
  this.#factors.set(key, { amount, multiplier });
169
185
  }
170
186
  /**
171
187
  * Removes a decay factor by its key.
172
188
  *
173
189
  * @param {string} key - The factor key to remove.
190
+ * @returns {boolean} Returns `true` if the factor existed and was successfully removed,
191
+ * or `false` if the factor did not exist.
174
192
  */
175
193
  removeFactor(key) {
176
- this.#factors.delete(key);
194
+ if (typeof key !== 'string' || !key)
195
+ throw new TypeError('Key must be a non-empty string.');
196
+ return this.#factors.delete(key);
177
197
  }
178
198
  /**
179
- * Executes one tick of decay, applying all active factors.
199
+ * Applies a total decay value to the bar and updates both current and infinite values.
200
+ * This is a private helper used by the public tick methods.
180
201
  *
181
- * @returns {TickResult}
202
+ * @param {number} removedTotal - The total amount to remove from the bar during this tick.
203
+ * @returns {TickResult} An object containing detailed information about the tick.
182
204
  */
183
- tick() {
184
- let removedTotal = 0;
185
- for (let [_, factor] of this.#factors.entries()) {
186
- removedTotal += factor.amount * factor.multiplier;
187
- }
205
+ #tick(removedTotal) {
188
206
  const prevValue = this.#infiniteValue;
189
207
  this.#infiniteValue -= removedTotal;
190
208
  this.#currentValue = Math.max(0, this.#currentValue - removedTotal);
@@ -198,6 +216,59 @@ class TinyNeedBar {
198
216
  infiniteRemaining: this.#infiniteValue,
199
217
  };
200
218
  }
219
+ /**
220
+ * Executes one tick of decay, applying all active factors.
221
+ *
222
+ * @returns {TickResult}
223
+ */
224
+ tick() {
225
+ let removedTotal = 0;
226
+ for (let [_, factor] of this.#factors.entries()) {
227
+ removedTotal += factor.amount * factor.multiplier;
228
+ }
229
+ return this.#tick(removedTotal);
230
+ }
231
+ /**
232
+ * Executes one tick of decay using a temporary factor.
233
+ *
234
+ * @param {BarFactor} tempFactor - Temporary factor to apply only in this tick.
235
+ * @returns {TickResult}
236
+ */
237
+ tickWithTempFactor(tempFactor) {
238
+ if (typeof tempFactor !== 'object' || tempFactor === null)
239
+ throw new TypeError('You must provide a valid factor object.');
240
+ if (typeof tempFactor.amount !== 'number' || Number.isNaN(tempFactor.amount))
241
+ throw new TypeError('Temp factor "amount" must be a valid number.');
242
+ if ('multiplier' in tempFactor &&
243
+ (typeof tempFactor.multiplier !== 'number' || Number.isNaN(tempFactor.multiplier)))
244
+ throw new TypeError('Temp factor "multiplier" must be a valid number if provided.');
245
+ let removedTotal = 0;
246
+ for (let [_, factor] of this.#factors.entries()) {
247
+ removedTotal += factor.amount * factor.multiplier;
248
+ }
249
+ if (tempFactor)
250
+ removedTotal += tempFactor.amount * (tempFactor.multiplier ?? 1);
251
+ return this.#tick(removedTotal);
252
+ }
253
+ /**
254
+ * Executes one tick using only the specified factor.
255
+ *
256
+ * @param {BarFactor} factor - The single factor to apply.
257
+ * @returns {TickResult}
258
+ */
259
+ tickSingleFactor(factor) {
260
+ if (typeof factor !== 'object' || factor === null)
261
+ throw new TypeError('You must provide a valid factor object.');
262
+ if (typeof factor.amount !== 'number' || Number.isNaN(factor.amount))
263
+ throw new TypeError('Temp factor "amount" must be a valid number.');
264
+ if ('multiplier' in factor &&
265
+ (typeof factor.multiplier !== 'number' || Number.isNaN(factor.multiplier)))
266
+ throw new TypeError('Temp factor "multiplier" must be a valid number if provided.');
267
+ if (!factor)
268
+ throw new Error('You must provide a factor to apply.');
269
+ const removedTotal = factor.amount * (factor.multiplier ?? 1);
270
+ return this.#tick(removedTotal);
271
+ }
201
272
  /**
202
273
  * Serializes the current state of the need bar.
203
274
  * @returns {SerializedData}
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * TinySimpleDice
5
+ *
6
+ * A lightweight, flexible dice rolling utility for generating random numbers.
7
+ * You can configure the dice to allow zero, set a maximum value, and even roll
8
+ * values suitable for indexing arrays or Sets.
9
+ */
10
+ class TinySimpleDice {
11
+ /**
12
+ * Rolls a dice specifically for choosing an array or Set index.
13
+ * @param {any[]|Set<any>} arr - The array or Set to get a random index from.
14
+ * @returns {number} - Valid index for the array or Set.
15
+ * @throws {TypeError} If the input is not an array or Set.
16
+ */
17
+ static rollArrayIndex(arr) {
18
+ const isArray = Array.isArray(arr);
19
+ const isSet = arr instanceof Set;
20
+ if (!isArray && !isSet) throw new TypeError('rollArrayIndex expects an array or Set.');
21
+ return Math.floor(Math.random() * (isArray ? arr.length : arr.size));
22
+ }
23
+
24
+ /** @type {number} */
25
+ #maxValue;
26
+ /** @type {boolean} */
27
+ #allowZero;
28
+
29
+ /**
30
+ * Maximum value the dice can roll.
31
+ * @type {number}
32
+ */
33
+ get maxValue() {
34
+ return this.#maxValue;
35
+ }
36
+
37
+ /**
38
+ * Set the maximum value the dice can roll.
39
+ * @param {number} value - New maximum value (must be a non-negative integer)
40
+ * @throws {TypeError} If value is not a non-negative integer
41
+ */
42
+ set maxValue(value) {
43
+ if (!Number.isInteger(value) || value < 0)
44
+ throw new TypeError('maxValue must be an integer greater than -1.');
45
+ this.#maxValue = value;
46
+ }
47
+
48
+ /**
49
+ * Whether 0 is allowed as a result.
50
+ * @type {boolean}
51
+ */
52
+ get allowZero() {
53
+ return this.#allowZero;
54
+ }
55
+
56
+ /**
57
+ * Set whether 0 is allowed as a result.
58
+ * @param {boolean} value - true to allow 0, false to disallow
59
+ * @throws {TypeError} If value is not a boolean
60
+ */
61
+ set allowZero(value) {
62
+ if (typeof value !== 'boolean') throw new TypeError('allowZero must be a boolean.');
63
+ this.#allowZero = value;
64
+ }
65
+
66
+ /**
67
+ * Creates a new TinySimpleDice instance.
68
+ * @param {Object} options - Configuration options for the dice.
69
+ * @param {number} options.maxValue - Maximum value the dice can roll.
70
+ * @param {boolean} [options.allowZero=true] - Whether 0 is allowed as a result.
71
+ * @throws {TypeError} If maxValue is not a non-negative integer or allowZero is not boolean.
72
+ */
73
+ constructor({ maxValue, allowZero = true }) {
74
+ if (typeof allowZero !== 'boolean') throw new TypeError('allowZero must be an boolean.');
75
+ if (!Number.isInteger(maxValue) || maxValue < 0)
76
+ throw new TypeError('maxValue must be an integer greater than -1.');
77
+ this.#maxValue = maxValue;
78
+ this.#allowZero = allowZero;
79
+ }
80
+
81
+ /**
82
+ * Rolls the dice according to the configuration.
83
+ * @returns {number} - Random number according to the dice configuration.
84
+ */
85
+ roll() {
86
+ const min = this.#allowZero ? 0 : 1;
87
+ return Math.floor(Math.random() * (this.#maxValue - min + 1)) + min;
88
+ }
89
+ }
90
+
91
+ module.exports = TinySimpleDice;