tiny-essentials 1.15.0 → 1.16.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 (47) hide show
  1. package/dist/v1/TinyAfterScrollWatcher.js +196 -0
  2. package/dist/v1/TinyAfterScrollWatcher.min.js +1 -0
  3. package/dist/v1/TinyBasicsEs.js +5058 -745
  4. package/dist/v1/TinyBasicsEs.min.js +1 -1
  5. package/dist/v1/TinyDragger.js +4874 -546
  6. package/dist/v1/TinyDragger.min.js +1 -1
  7. package/dist/v1/TinyEssentials.js +5299 -750
  8. package/dist/v1/TinyEssentials.min.js +1 -1
  9. package/dist/v1/TinyHtml.js +4815 -0
  10. package/dist/v1/TinyHtml.min.js +1 -0
  11. package/dist/v1/TinyUploadClicker.js +5093 -298
  12. package/dist/v1/TinyUploadClicker.min.js +1 -1
  13. package/dist/v1/basics/html.cjs +5 -187
  14. package/dist/v1/basics/html.d.mts +2 -53
  15. package/dist/v1/basics/html.mjs +5 -161
  16. package/dist/v1/basics/html_deprecated.cjs +124 -0
  17. package/dist/v1/basics/html_deprecated.d.mts +40 -0
  18. package/dist/v1/basics/html_deprecated.mjs +97 -0
  19. package/dist/v1/basics/index.cjs +8 -7
  20. package/dist/v1/basics/index.d.mts +7 -7
  21. package/dist/v1/basics/index.mjs +2 -1
  22. package/dist/v1/build/TinyAfterScrollWatcher.cjs +7 -0
  23. package/dist/v1/build/TinyAfterScrollWatcher.d.mts +3 -0
  24. package/dist/v1/build/TinyAfterScrollWatcher.mjs +2 -0
  25. package/dist/v1/build/TinyHtml.cjs +7 -0
  26. package/dist/v1/build/TinyHtml.d.mts +3 -0
  27. package/dist/v1/build/TinyHtml.mjs +2 -0
  28. package/dist/v1/index.cjs +12 -7
  29. package/dist/v1/index.d.mts +10 -8
  30. package/dist/v1/index.mjs +5 -2
  31. package/dist/v1/libs/TinyAfterScrollWatcher.cjs +157 -0
  32. package/dist/v1/libs/TinyAfterScrollWatcher.d.mts +86 -0
  33. package/dist/v1/libs/TinyAfterScrollWatcher.mjs +138 -0
  34. package/dist/v1/libs/TinyDragger.cjs +91 -16
  35. package/dist/v1/libs/TinyDragger.d.mts +78 -2
  36. package/dist/v1/libs/TinyDragger.mjs +93 -17
  37. package/dist/v1/libs/TinyHtml.cjs +4347 -0
  38. package/dist/v1/libs/TinyHtml.d.mts +2301 -0
  39. package/dist/v1/libs/TinyHtml.mjs +3926 -0
  40. package/dist/v1/libs/TinyUploadClicker.cjs +1 -0
  41. package/docs/v1/README.md +11 -10
  42. package/docs/v1/basics/html.md +0 -130
  43. package/docs/v1/basics/html_deprecated.md +127 -0
  44. package/docs/v1/libs/TinyAfterScrollWatcher.md +181 -0
  45. package/docs/v1/libs/TinyDragger.md +45 -15
  46. package/docs/v1/libs/TinyHtml.md +1658 -0
  47. package/package.json +4 -1
@@ -1,3 +1,5 @@
1
+ import TinyAfterScrollWatcher from './libs/TinyAfterScrollWatcher.mjs';
2
+ import TinyHtml from './libs/TinyHtml.mjs';
1
3
  import TinyNotifications from './libs/TinyNotifications.mjs';
2
4
  import TinyDomReadyManager from './libs/TinyDomReadyManager.mjs';
3
5
  import TinyDragger from './libs/TinyDragger.mjs';
@@ -26,8 +28,8 @@ import { getRectCenter } from './basics/collision.mjs';
26
28
  import { getElsRelativeCenterOffset } from './basics/collision.mjs';
27
29
  import { getElsCollDirDepth } from './basics/collision.mjs';
28
30
  import { getElsCollDetails } from './basics/collision.mjs';
29
- import { isInViewport } from './basics/html.mjs';
30
- import { isScrolledIntoView } from './basics/html.mjs';
31
+ import { isInViewport } from './basics/html_deprecated.mjs';
32
+ import { isScrolledIntoView } from './basics/html_deprecated.mjs';
31
33
  import { safeTextTrim } from './basics/text.mjs';
32
34
  import { installWindowHiddenScript } from './basics/html.mjs';
33
35
  import { genFibonacciSeq } from './basics/simpleMath.mjs';
@@ -36,10 +38,10 @@ import { fileSizeAsync } from './fileManager/asyncFuncs.mjs';
36
38
  import { dirSizeAsync } from './fileManager/asyncFuncs.mjs';
37
39
  import { listFilesAsync } from './fileManager/asyncFuncs.mjs';
38
40
  import { listDirsAsync } from './fileManager/asyncFuncs.mjs';
39
- import { getHtmlElBorders } from './basics/html.mjs';
40
- import { getHtmlElBordersWidth } from './basics/html.mjs';
41
- import { getHtmlElMargin } from './basics/html.mjs';
42
- import { getHtmlElPadding } from './basics/html.mjs';
41
+ import { getHtmlElBorders } from './basics/html_deprecated.mjs';
42
+ import { getHtmlElBordersWidth } from './basics/html_deprecated.mjs';
43
+ import { getHtmlElMargin } from './basics/html_deprecated.mjs';
44
+ import { getHtmlElPadding } from './basics/html_deprecated.mjs';
43
45
  import { getLatestBackupPath } from './fileManager/normalFuncs.mjs';
44
46
  import { fetchJson } from './basics/html.mjs';
45
47
  import { readJsonBlob } from './basics/html.mjs';
@@ -75,7 +77,7 @@ import { exitFullScreen } from './basics/fullScreen.mjs';
75
77
  import { isFullScreenMode } from './basics/fullScreen.mjs';
76
78
  import { onFullScreenChange } from './basics/fullScreen.mjs';
77
79
  import { offFullScreenChange } from './basics/fullScreen.mjs';
78
- import { areHtmlElsColliding } from './basics/html.mjs';
80
+ import { areHtmlElsColliding } from './basics/html_deprecated.mjs';
79
81
  import { isJsonObject } from './basics/objFilter.mjs';
80
82
  import arraySortPositions from '../legacy/libs/arraySortPositions.mjs';
81
83
  import { formatBytes } from './basics/simpleMath.mjs';
@@ -97,5 +99,5 @@ import { getTimeDuration } from './basics/clock.mjs';
97
99
  import { shuffleArray } from './basics/array.mjs';
98
100
  import { toTitleCase } from './basics/text.mjs';
99
101
  import { toTitleCaseLowerFirst } from './basics/text.mjs';
100
- export { TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, isInViewport, isScrolledIntoView, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getHtmlElBorders, getHtmlElBordersWidth, getHtmlElMargin, getHtmlElPadding, getLatestBackupPath, fetchJson, 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, areHtmlElsColliding, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
102
+ export { TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, isInViewport, isScrolledIntoView, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getHtmlElBorders, getHtmlElBordersWidth, getHtmlElMargin, getHtmlElPadding, getLatestBackupPath, fetchJson, 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, areHtmlElsColliding, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
101
103
  //# sourceMappingURL=index.d.mts.map
package/dist/v1/index.mjs CHANGED
@@ -12,7 +12,8 @@ import TinyPromiseQueue from './libs/TinyPromiseQueue.mjs';
12
12
  import TinyRateLimiter from './libs/TinyRateLimiter.mjs';
13
13
  import TinyNotifyCenter from './libs/TinyNotifyCenter.mjs';
14
14
  import TinyToastNotify from './libs/TinyToastNotify.mjs';
15
- import { areHtmlElsColliding, readJsonBlob, saveJsonFile, fetchJson, getHtmlElBorders, getHtmlElBordersWidth, getHtmlElMargin, getHtmlElPadding, installWindowHiddenScript, readFileBlob, readBase64Blob, isInViewport, isScrolledIntoView, } from './basics/html.mjs';
15
+ import { readJsonBlob, saveJsonFile, fetchJson, installWindowHiddenScript, readFileBlob, readBase64Blob, } from './basics/html.mjs';
16
+ import { getHtmlElBorders, getHtmlElBordersWidth, getHtmlElMargin, getHtmlElPadding, areHtmlElsColliding, isInViewport, isScrolledIntoView, } from './basics/html_deprecated.mjs';
16
17
  import TinyDragDropDetector from './libs/TinyDragDropDetector.mjs';
17
18
  import { readJsonFile, writeJsonFile, ensureDirectory, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, getLatestBackupPath, } from './fileManager/normalFuncs.mjs';
18
19
  import { listFilesAsync, listDirsAsync, clearDirectoryAsync, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, } from './fileManager/asyncFuncs.mjs';
@@ -20,4 +21,6 @@ import TinyDragger from './libs/TinyDragger.mjs';
20
21
  import TinyDomReadyManager from './libs/TinyDomReadyManager.mjs';
21
22
  import TinyNotifications from './libs/TinyNotifications.mjs';
22
23
  import { areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, } from './basics/collision.mjs';
23
- export { TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, isInViewport, isScrolledIntoView, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getHtmlElBorders, getHtmlElBordersWidth, getHtmlElMargin, getHtmlElPadding, getLatestBackupPath, fetchJson, 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, areHtmlElsColliding, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
24
+ import TinyHtml from './libs/TinyHtml.mjs';
25
+ import TinyAfterScrollWatcher from './libs/TinyAfterScrollWatcher.mjs';
26
+ export { TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, isInViewport, isScrolledIntoView, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getHtmlElBorders, getHtmlElBordersWidth, getHtmlElMargin, getHtmlElPadding, getLatestBackupPath, fetchJson, 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, areHtmlElsColliding, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
@@ -0,0 +1,157 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @typedef {(() => void)} FnData - Function with no arguments and no return value
5
+ */
6
+
7
+ /**
8
+ * A function that handles a scroll event.
9
+ * It receives a standard `Event` object when a scroll occurs.
10
+ *
11
+ * @typedef {(ev: Event) => void} OnScrollFunc
12
+ */
13
+
14
+ /**
15
+ * A scroll tracker that queues functions to be executed
16
+ * after the user stops scrolling a specific element or the window.
17
+ */
18
+ class TinyAfterScrollWatcher {
19
+ /** @type {Element|Window} */
20
+ #scrollTarget;
21
+
22
+ /** @type {number} */
23
+ lastScrollTime = 0;
24
+
25
+ /** @type {FnData[]} */
26
+ #afterScrollQueue = [];
27
+
28
+ /** @type {number} */
29
+ #inactivityTime = 100;
30
+
31
+ /** @type {Set<OnScrollFunc>} */
32
+ #externalScrollListeners = new Set();
33
+
34
+ /** @type {boolean} */
35
+ #destroyed = false;
36
+
37
+ /**
38
+ * @param {Element|Window} scrollTarget - The element or window to track scrolling on
39
+ * @param {number} [inactivityTime=100] - Time in milliseconds to wait after scroll ends before executing the queue
40
+ * @throws {TypeError} If scrollTarget is not a valid Element or Window
41
+ * @throws {TypeError} If inactivityTime is not a positive number
42
+ */
43
+ constructor(scrollTarget = window, inactivityTime = 100) {
44
+ if (!(scrollTarget instanceof Element) && !(scrollTarget instanceof Window))
45
+ throw new TypeError('scrollTarget must be an Element or the Window object.');
46
+ this.#scrollTarget = scrollTarget;
47
+
48
+ this._onScroll = this._onScroll.bind(this);
49
+ this._checkQueue = this._checkQueue.bind(this);
50
+
51
+ this.#scrollTarget.addEventListener('scroll', this._onScroll);
52
+ this.#inactivityTime = inactivityTime;
53
+
54
+ requestAnimationFrame(this._checkQueue);
55
+ }
56
+
57
+ /**
58
+ * Gets the current inactivity time in milliseconds.
59
+ * @returns {number}
60
+ */
61
+ get inactivityTime() {
62
+ return this.#inactivityTime;
63
+ }
64
+
65
+ /**
66
+ * Sets a new inactivity time.
67
+ * Must be a positive number (in milliseconds).
68
+ * @param {number} value
69
+ * @throws {Error} If value is not a positive number
70
+ */
71
+ set inactivityTime(value) {
72
+ if (typeof value !== 'number' || value <= 0 || !Number.isFinite(value))
73
+ throw new Error('inactivityTime must be a positive number in milliseconds.');
74
+ this.#inactivityTime = value;
75
+ }
76
+
77
+ /**
78
+ * Internal handler for scroll events.
79
+ * Updates the last scroll timestamp.
80
+ * @private
81
+ */
82
+ _onScroll() {
83
+ this.lastScrollTime = Date.now();
84
+ }
85
+
86
+ /**
87
+ * Continuously checks whether the user has stopped scrolling,
88
+ * and if so, runs all queued functions.
89
+ * @private
90
+ */
91
+ _checkQueue() {
92
+ if (this.#destroyed) return;
93
+ requestAnimationFrame(this._checkQueue);
94
+
95
+ if (Date.now() - this.lastScrollTime > this.#inactivityTime) {
96
+ while (this.#afterScrollQueue.length) {
97
+ const fn = this.#afterScrollQueue.pop();
98
+ if (typeof fn === 'function') fn();
99
+ }
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Adds a function to be executed after scroll has stopped.
105
+ * The scroll is considered "stopped" after the configured inactivity time.
106
+ *
107
+ * @param {() => void} fn - A function to execute once scrolling has stopped.
108
+ * @throws {TypeError} If the argument is not a function.
109
+ */
110
+ doAfterScroll(fn) {
111
+ if (typeof fn !== 'function') throw new TypeError('Argument must be a function.');
112
+ this.lastScrollTime = Date.now();
113
+ this.#afterScrollQueue.push(fn);
114
+ }
115
+
116
+ /**
117
+ * Registers an external scroll listener on the tracked element.
118
+ *
119
+ * @param {OnScrollFunc} fn - The scroll listener to add
120
+ * @throws {TypeError} If the argument is not a function.
121
+ */
122
+ onScroll(fn) {
123
+ if (typeof fn !== 'function') throw new TypeError('Argument must be a function.');
124
+ this.#scrollTarget.addEventListener('scroll', fn);
125
+ this.#externalScrollListeners.add(fn);
126
+ }
127
+
128
+ /**
129
+ * Removes a previously registered scroll listener from the tracked element.
130
+ *
131
+ * @param {OnScrollFunc} fn - The scroll listener to remove
132
+ * @throws {TypeError} If the argument is not a function.
133
+ */
134
+ offScroll(fn) {
135
+ if (typeof fn !== 'function') throw new TypeError('Argument must be a function.');
136
+ if (this.#externalScrollListeners.has(fn)) {
137
+ this.#scrollTarget.removeEventListener('scroll', fn);
138
+ this.#externalScrollListeners.delete(fn);
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Destroys the watcher by removing internal listeners and clearing data.
144
+ */
145
+ destroy() {
146
+ if (this.#destroyed) return;
147
+ this.#destroyed = true;
148
+
149
+ this.#scrollTarget.removeEventListener('scroll', this._onScroll);
150
+ for (const fn of this.#externalScrollListeners)
151
+ this.#scrollTarget.removeEventListener('scroll', fn);
152
+
153
+ this.#externalScrollListeners.clear();
154
+ }
155
+ }
156
+
157
+ module.exports = TinyAfterScrollWatcher;
@@ -0,0 +1,86 @@
1
+ export default TinyAfterScrollWatcher;
2
+ /**
3
+ * - Function with no arguments and no return value
4
+ */
5
+ export type FnData = (() => void);
6
+ /**
7
+ * A function that handles a scroll event.
8
+ * It receives a standard `Event` object when a scroll occurs.
9
+ */
10
+ export type OnScrollFunc = (ev: Event) => void;
11
+ /**
12
+ * @typedef {(() => void)} FnData - Function with no arguments and no return value
13
+ */
14
+ /**
15
+ * A function that handles a scroll event.
16
+ * It receives a standard `Event` object when a scroll occurs.
17
+ *
18
+ * @typedef {(ev: Event) => void} OnScrollFunc
19
+ */
20
+ /**
21
+ * A scroll tracker that queues functions to be executed
22
+ * after the user stops scrolling a specific element or the window.
23
+ */
24
+ declare class TinyAfterScrollWatcher {
25
+ /**
26
+ * @param {Element|Window} scrollTarget - The element or window to track scrolling on
27
+ * @param {number} [inactivityTime=100] - Time in milliseconds to wait after scroll ends before executing the queue
28
+ * @throws {TypeError} If scrollTarget is not a valid Element or Window
29
+ * @throws {TypeError} If inactivityTime is not a positive number
30
+ */
31
+ constructor(scrollTarget?: Element | Window, inactivityTime?: number);
32
+ /** @type {number} */
33
+ lastScrollTime: number;
34
+ /**
35
+ * Internal handler for scroll events.
36
+ * Updates the last scroll timestamp.
37
+ * @private
38
+ */
39
+ private _onScroll;
40
+ /**
41
+ * Continuously checks whether the user has stopped scrolling,
42
+ * and if so, runs all queued functions.
43
+ * @private
44
+ */
45
+ private _checkQueue;
46
+ /**
47
+ * Sets a new inactivity time.
48
+ * Must be a positive number (in milliseconds).
49
+ * @param {number} value
50
+ * @throws {Error} If value is not a positive number
51
+ */
52
+ set inactivityTime(value: number);
53
+ /**
54
+ * Gets the current inactivity time in milliseconds.
55
+ * @returns {number}
56
+ */
57
+ get inactivityTime(): number;
58
+ /**
59
+ * Adds a function to be executed after scroll has stopped.
60
+ * The scroll is considered "stopped" after the configured inactivity time.
61
+ *
62
+ * @param {() => void} fn - A function to execute once scrolling has stopped.
63
+ * @throws {TypeError} If the argument is not a function.
64
+ */
65
+ doAfterScroll(fn: () => void): void;
66
+ /**
67
+ * Registers an external scroll listener on the tracked element.
68
+ *
69
+ * @param {OnScrollFunc} fn - The scroll listener to add
70
+ * @throws {TypeError} If the argument is not a function.
71
+ */
72
+ onScroll(fn: OnScrollFunc): void;
73
+ /**
74
+ * Removes a previously registered scroll listener from the tracked element.
75
+ *
76
+ * @param {OnScrollFunc} fn - The scroll listener to remove
77
+ * @throws {TypeError} If the argument is not a function.
78
+ */
79
+ offScroll(fn: OnScrollFunc): void;
80
+ /**
81
+ * Destroys the watcher by removing internal listeners and clearing data.
82
+ */
83
+ destroy(): void;
84
+ #private;
85
+ }
86
+ //# sourceMappingURL=TinyAfterScrollWatcher.d.mts.map
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @typedef {(() => void)} FnData - Function with no arguments and no return value
3
+ */
4
+ /**
5
+ * A function that handles a scroll event.
6
+ * It receives a standard `Event` object when a scroll occurs.
7
+ *
8
+ * @typedef {(ev: Event) => void} OnScrollFunc
9
+ */
10
+ /**
11
+ * A scroll tracker that queues functions to be executed
12
+ * after the user stops scrolling a specific element or the window.
13
+ */
14
+ class TinyAfterScrollWatcher {
15
+ /** @type {Element|Window} */
16
+ #scrollTarget;
17
+ /** @type {number} */
18
+ lastScrollTime = 0;
19
+ /** @type {FnData[]} */
20
+ #afterScrollQueue = [];
21
+ /** @type {number} */
22
+ #inactivityTime = 100;
23
+ /** @type {Set<OnScrollFunc>} */
24
+ #externalScrollListeners = new Set();
25
+ /** @type {boolean} */
26
+ #destroyed = false;
27
+ /**
28
+ * @param {Element|Window} scrollTarget - The element or window to track scrolling on
29
+ * @param {number} [inactivityTime=100] - Time in milliseconds to wait after scroll ends before executing the queue
30
+ * @throws {TypeError} If scrollTarget is not a valid Element or Window
31
+ * @throws {TypeError} If inactivityTime is not a positive number
32
+ */
33
+ constructor(scrollTarget = window, inactivityTime = 100) {
34
+ if (!(scrollTarget instanceof Element) && !(scrollTarget instanceof Window))
35
+ throw new TypeError('scrollTarget must be an Element or the Window object.');
36
+ this.#scrollTarget = scrollTarget;
37
+ this._onScroll = this._onScroll.bind(this);
38
+ this._checkQueue = this._checkQueue.bind(this);
39
+ this.#scrollTarget.addEventListener('scroll', this._onScroll);
40
+ this.#inactivityTime = inactivityTime;
41
+ requestAnimationFrame(this._checkQueue);
42
+ }
43
+ /**
44
+ * Gets the current inactivity time in milliseconds.
45
+ * @returns {number}
46
+ */
47
+ get inactivityTime() {
48
+ return this.#inactivityTime;
49
+ }
50
+ /**
51
+ * Sets a new inactivity time.
52
+ * Must be a positive number (in milliseconds).
53
+ * @param {number} value
54
+ * @throws {Error} If value is not a positive number
55
+ */
56
+ set inactivityTime(value) {
57
+ if (typeof value !== 'number' || value <= 0 || !Number.isFinite(value))
58
+ throw new Error('inactivityTime must be a positive number in milliseconds.');
59
+ this.#inactivityTime = value;
60
+ }
61
+ /**
62
+ * Internal handler for scroll events.
63
+ * Updates the last scroll timestamp.
64
+ * @private
65
+ */
66
+ _onScroll() {
67
+ this.lastScrollTime = Date.now();
68
+ }
69
+ /**
70
+ * Continuously checks whether the user has stopped scrolling,
71
+ * and if so, runs all queued functions.
72
+ * @private
73
+ */
74
+ _checkQueue() {
75
+ if (this.#destroyed)
76
+ return;
77
+ requestAnimationFrame(this._checkQueue);
78
+ if (Date.now() - this.lastScrollTime > this.#inactivityTime) {
79
+ while (this.#afterScrollQueue.length) {
80
+ const fn = this.#afterScrollQueue.pop();
81
+ if (typeof fn === 'function')
82
+ fn();
83
+ }
84
+ }
85
+ }
86
+ /**
87
+ * Adds a function to be executed after scroll has stopped.
88
+ * The scroll is considered "stopped" after the configured inactivity time.
89
+ *
90
+ * @param {() => void} fn - A function to execute once scrolling has stopped.
91
+ * @throws {TypeError} If the argument is not a function.
92
+ */
93
+ doAfterScroll(fn) {
94
+ if (typeof fn !== 'function')
95
+ throw new TypeError('Argument must be a function.');
96
+ this.lastScrollTime = Date.now();
97
+ this.#afterScrollQueue.push(fn);
98
+ }
99
+ /**
100
+ * Registers an external scroll listener on the tracked element.
101
+ *
102
+ * @param {OnScrollFunc} fn - The scroll listener to add
103
+ * @throws {TypeError} If the argument is not a function.
104
+ */
105
+ onScroll(fn) {
106
+ if (typeof fn !== 'function')
107
+ throw new TypeError('Argument must be a function.');
108
+ this.#scrollTarget.addEventListener('scroll', fn);
109
+ this.#externalScrollListeners.add(fn);
110
+ }
111
+ /**
112
+ * Removes a previously registered scroll listener from the tracked element.
113
+ *
114
+ * @param {OnScrollFunc} fn - The scroll listener to remove
115
+ * @throws {TypeError} If the argument is not a function.
116
+ */
117
+ offScroll(fn) {
118
+ if (typeof fn !== 'function')
119
+ throw new TypeError('Argument must be a function.');
120
+ if (this.#externalScrollListeners.has(fn)) {
121
+ this.#scrollTarget.removeEventListener('scroll', fn);
122
+ this.#externalScrollListeners.delete(fn);
123
+ }
124
+ }
125
+ /**
126
+ * Destroys the watcher by removing internal listeners and clearing data.
127
+ */
128
+ destroy() {
129
+ if (this.#destroyed)
130
+ return;
131
+ this.#destroyed = true;
132
+ this.#scrollTarget.removeEventListener('scroll', this._onScroll);
133
+ for (const fn of this.#externalScrollListeners)
134
+ this.#scrollTarget.removeEventListener('scroll', fn);
135
+ this.#externalScrollListeners.clear();
136
+ }
137
+ }
138
+ export default TinyAfterScrollWatcher;