@splendidlabz/utils 1.8.1 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/cjs/dom/index.cjs +90 -0
- package/dist/cjs/dom/observers/index.cjs +92 -2
- package/dist/cjs/dom/observers/scroll-observer.cjs +170 -0
- package/dist/cjs/lib/functions/functional.cjs +20 -0
- package/dist/cjs/lib/functions/index.cjs +20 -0
- package/dist/cjs/lib/index.cjs +20 -0
- package/dist/esm/dom/index.js +89 -0
- package/dist/esm/dom/observers/index.js +90 -1
- package/dist/esm/dom/observers/scroll-observer.js +144 -0
- package/dist/esm/lib/functions/functional.js +18 -0
- package/dist/esm/lib/functions/index.js +18 -0
- package/dist/esm/lib/index.js +18 -0
- package/dist/types/dom/index.d.cts +1 -0
- package/dist/types/dom/observers/index.d.cts +1 -0
- package/dist/types/dom/observers/scroll-observer.d.cts +27 -0
- package/dist/types/lib/functions/functional.d.cts +71 -5
- package/dist/types/lib/functions/index.d.cts +1 -1
- package/dist/types/lib/index.d.cts +1 -1
- package/package.json +1 -1
- package/src/dom/observers/index.js +1 -0
- package/src/dom/observers/resize-observer.js +5 -5
- package/src/dom/observers/scroll-observer.js +132 -0
- package/src/lib/functions/functional.js +82 -0
- package/src/lib/functions/functional.test.js +196 -0
package/CHANGELOG.md
CHANGED
package/dist/cjs/dom/index.cjs
CHANGED
|
@@ -79,6 +79,7 @@ __export(dom_exports, {
|
|
|
79
79
|
removeListeners: () => removeListeners,
|
|
80
80
|
resizeObserver: () => resizeObserver,
|
|
81
81
|
sanitize: () => sanitize2,
|
|
82
|
+
scrollObserver: () => scrollObserver,
|
|
82
83
|
scrollToElement: () => scrollToElement,
|
|
83
84
|
sessionStore: () => sessionStore,
|
|
84
85
|
setCSSValue: () => setCSSValue,
|
|
@@ -943,6 +944,94 @@ function mutationObserver(target, options) {
|
|
|
943
944
|
};
|
|
944
945
|
}
|
|
945
946
|
|
|
947
|
+
// src/dom/observers/scroll-observer.js
|
|
948
|
+
var defaultOptions2 = {
|
|
949
|
+
threshold: 0,
|
|
950
|
+
// Float between 0 to 1.
|
|
951
|
+
tolerance: 0.1,
|
|
952
|
+
// Float between 0 to 1. Tolerance for event firing
|
|
953
|
+
throttle: 16,
|
|
954
|
+
// Throttle interval in ms (default: ~60fps)
|
|
955
|
+
once: false
|
|
956
|
+
// Only fire threshold callback once
|
|
957
|
+
};
|
|
958
|
+
function scrollObserver(node, options = {}) {
|
|
959
|
+
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
960
|
+
const opts = { ...defaultOptions2, ...userOpts };
|
|
961
|
+
const { threshold, tolerance, throttle, once } = opts;
|
|
962
|
+
const prevScrollDirection = null;
|
|
963
|
+
let prevScrollTop = 0;
|
|
964
|
+
let prevScrollPercent = 0;
|
|
965
|
+
let lastThrottleTime = 0;
|
|
966
|
+
let thresholdFired = false;
|
|
967
|
+
let rafId = null;
|
|
968
|
+
const isDocumentScroll = node === document || node === window;
|
|
969
|
+
const scrollElement = isDocumentScroll ? document.documentElement : node;
|
|
970
|
+
let cachedScrollHeight = 0;
|
|
971
|
+
let cachedClientHeight = 0;
|
|
972
|
+
updateCache();
|
|
973
|
+
const cacheObserver = resizeObserver(scrollElement, {
|
|
974
|
+
callback: updateCache
|
|
975
|
+
});
|
|
976
|
+
node.addEventListener("scroll", throttledObserve, { passive: true });
|
|
977
|
+
function updateCache() {
|
|
978
|
+
cachedScrollHeight = scrollElement.scrollHeight;
|
|
979
|
+
cachedClientHeight = scrollElement.clientHeight;
|
|
980
|
+
}
|
|
981
|
+
function throttledObserve() {
|
|
982
|
+
const now = Date.now();
|
|
983
|
+
if (now - lastThrottleTime < throttle) return;
|
|
984
|
+
lastThrottleTime = now;
|
|
985
|
+
rafId = requestAnimationFrame(observe);
|
|
986
|
+
}
|
|
987
|
+
function observe() {
|
|
988
|
+
const scrollTop = scrollElement.scrollTop;
|
|
989
|
+
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
990
|
+
const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
|
|
991
|
+
const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
|
|
992
|
+
const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
|
|
993
|
+
const thresholdMin = threshold - tolerance / 2;
|
|
994
|
+
const thresholdMax = threshold + tolerance / 2;
|
|
995
|
+
const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
|
|
996
|
+
const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
|
|
997
|
+
const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
|
|
998
|
+
if (hasEnteredThreshold && once) {
|
|
999
|
+
thresholdFired = true;
|
|
1000
|
+
}
|
|
1001
|
+
const callbackData = {
|
|
1002
|
+
scrollTop,
|
|
1003
|
+
scrollDirection,
|
|
1004
|
+
scrollPercent,
|
|
1005
|
+
directionChanged: scrollDirection !== prevScrollDirection,
|
|
1006
|
+
hasEnteredThreshold,
|
|
1007
|
+
isInThreshold
|
|
1008
|
+
};
|
|
1009
|
+
if (typeof callback === "function") {
|
|
1010
|
+
callback(callbackData);
|
|
1011
|
+
}
|
|
1012
|
+
if (scrollDirection !== prevScrollDirection) {
|
|
1013
|
+
if (scrollDirection === "down" && typeof onScrollDown === "function") {
|
|
1014
|
+
onScrollDown(callbackData);
|
|
1015
|
+
}
|
|
1016
|
+
if (scrollDirection === "up" && typeof onScrollUp === "function") {
|
|
1017
|
+
onScrollUp(callbackData);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
|
|
1021
|
+
onEnterThreshold(callbackData);
|
|
1022
|
+
}
|
|
1023
|
+
prevScrollTop = scrollTop;
|
|
1024
|
+
prevScrollPercent = scrollPercent;
|
|
1025
|
+
}
|
|
1026
|
+
return {
|
|
1027
|
+
destroy() {
|
|
1028
|
+
node.removeEventListener("scroll", throttledObserve);
|
|
1029
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
1030
|
+
cacheObserver.destroy();
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
|
|
946
1035
|
// src/dom/random-string.js
|
|
947
1036
|
function randomString(length = 10) {
|
|
948
1037
|
const firstLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
|
@@ -1182,6 +1271,7 @@ function scrambleText(text) {
|
|
|
1182
1271
|
removeListeners,
|
|
1183
1272
|
resizeObserver,
|
|
1184
1273
|
sanitize,
|
|
1274
|
+
scrollObserver,
|
|
1185
1275
|
scrollToElement,
|
|
1186
1276
|
sessionStore,
|
|
1187
1277
|
setCSSValue,
|
|
@@ -21,7 +21,8 @@ var observers_exports = {};
|
|
|
21
21
|
__export(observers_exports, {
|
|
22
22
|
intersectionObserver: () => intersectionObserver,
|
|
23
23
|
mutationObserver: () => mutationObserver,
|
|
24
|
-
resizeObserver: () => resizeObserver
|
|
24
|
+
resizeObserver: () => resizeObserver,
|
|
25
|
+
scrollObserver: () => scrollObserver
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(observers_exports);
|
|
27
28
|
|
|
@@ -148,9 +149,98 @@ function resizeObserver(target, options) {
|
|
|
148
149
|
destroy: (_) => observer.disconnect()
|
|
149
150
|
};
|
|
150
151
|
}
|
|
152
|
+
|
|
153
|
+
// src/dom/observers/scroll-observer.js
|
|
154
|
+
var defaultOptions2 = {
|
|
155
|
+
threshold: 0,
|
|
156
|
+
// Float between 0 to 1.
|
|
157
|
+
tolerance: 0.1,
|
|
158
|
+
// Float between 0 to 1. Tolerance for event firing
|
|
159
|
+
throttle: 16,
|
|
160
|
+
// Throttle interval in ms (default: ~60fps)
|
|
161
|
+
once: false
|
|
162
|
+
// Only fire threshold callback once
|
|
163
|
+
};
|
|
164
|
+
function scrollObserver(node, options = {}) {
|
|
165
|
+
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
166
|
+
const opts = { ...defaultOptions2, ...userOpts };
|
|
167
|
+
const { threshold, tolerance, throttle, once } = opts;
|
|
168
|
+
const prevScrollDirection = null;
|
|
169
|
+
let prevScrollTop = 0;
|
|
170
|
+
let prevScrollPercent = 0;
|
|
171
|
+
let lastThrottleTime = 0;
|
|
172
|
+
let thresholdFired = false;
|
|
173
|
+
let rafId = null;
|
|
174
|
+
const isDocumentScroll = node === document || node === window;
|
|
175
|
+
const scrollElement = isDocumentScroll ? document.documentElement : node;
|
|
176
|
+
let cachedScrollHeight = 0;
|
|
177
|
+
let cachedClientHeight = 0;
|
|
178
|
+
updateCache();
|
|
179
|
+
const cacheObserver = resizeObserver(scrollElement, {
|
|
180
|
+
callback: updateCache
|
|
181
|
+
});
|
|
182
|
+
node.addEventListener("scroll", throttledObserve, { passive: true });
|
|
183
|
+
function updateCache() {
|
|
184
|
+
cachedScrollHeight = scrollElement.scrollHeight;
|
|
185
|
+
cachedClientHeight = scrollElement.clientHeight;
|
|
186
|
+
}
|
|
187
|
+
function throttledObserve() {
|
|
188
|
+
const now = Date.now();
|
|
189
|
+
if (now - lastThrottleTime < throttle) return;
|
|
190
|
+
lastThrottleTime = now;
|
|
191
|
+
rafId = requestAnimationFrame(observe);
|
|
192
|
+
}
|
|
193
|
+
function observe() {
|
|
194
|
+
const scrollTop = scrollElement.scrollTop;
|
|
195
|
+
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
196
|
+
const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
|
|
197
|
+
const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
|
|
198
|
+
const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
|
|
199
|
+
const thresholdMin = threshold - tolerance / 2;
|
|
200
|
+
const thresholdMax = threshold + tolerance / 2;
|
|
201
|
+
const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
|
|
202
|
+
const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
|
|
203
|
+
const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
|
|
204
|
+
if (hasEnteredThreshold && once) {
|
|
205
|
+
thresholdFired = true;
|
|
206
|
+
}
|
|
207
|
+
const callbackData = {
|
|
208
|
+
scrollTop,
|
|
209
|
+
scrollDirection,
|
|
210
|
+
scrollPercent,
|
|
211
|
+
directionChanged: scrollDirection !== prevScrollDirection,
|
|
212
|
+
hasEnteredThreshold,
|
|
213
|
+
isInThreshold
|
|
214
|
+
};
|
|
215
|
+
if (typeof callback === "function") {
|
|
216
|
+
callback(callbackData);
|
|
217
|
+
}
|
|
218
|
+
if (scrollDirection !== prevScrollDirection) {
|
|
219
|
+
if (scrollDirection === "down" && typeof onScrollDown === "function") {
|
|
220
|
+
onScrollDown(callbackData);
|
|
221
|
+
}
|
|
222
|
+
if (scrollDirection === "up" && typeof onScrollUp === "function") {
|
|
223
|
+
onScrollUp(callbackData);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
|
|
227
|
+
onEnterThreshold(callbackData);
|
|
228
|
+
}
|
|
229
|
+
prevScrollTop = scrollTop;
|
|
230
|
+
prevScrollPercent = scrollPercent;
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
destroy() {
|
|
234
|
+
node.removeEventListener("scroll", throttledObserve);
|
|
235
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
236
|
+
cacheObserver.destroy();
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
151
240
|
// Annotate the CommonJS export names for ESM import in node:
|
|
152
241
|
0 && (module.exports = {
|
|
153
242
|
intersectionObserver,
|
|
154
243
|
mutationObserver,
|
|
155
|
-
resizeObserver
|
|
244
|
+
resizeObserver,
|
|
245
|
+
scrollObserver
|
|
156
246
|
});
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/dom/observers/scroll-observer.js
|
|
20
|
+
var scroll_observer_exports = {};
|
|
21
|
+
__export(scroll_observer_exports, {
|
|
22
|
+
scrollObserver: () => scrollObserver
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(scroll_observer_exports);
|
|
25
|
+
|
|
26
|
+
// src/dom/events.js
|
|
27
|
+
function dispatchEvent(node, eventName, detail, options = {}) {
|
|
28
|
+
node.dispatchEvent(
|
|
29
|
+
new CustomEvent(eventName, {
|
|
30
|
+
...options,
|
|
31
|
+
detail
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/dom/get-element.js
|
|
37
|
+
function getNodeType(node) {
|
|
38
|
+
if (node instanceof Element) return "element";
|
|
39
|
+
if (node instanceof NodeList) return "nodelist";
|
|
40
|
+
if (Array.isArray(node)) return "array";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/dom/observers/observer.js
|
|
44
|
+
function useObserverMethodOnTarget(target, observer, method = "observe", options = void 0) {
|
|
45
|
+
const targetType = getNodeType(target);
|
|
46
|
+
if (targetType === "element") observer[method](target, options);
|
|
47
|
+
if (targetType === "nodelist") {
|
|
48
|
+
const elements = Array.from(target);
|
|
49
|
+
elements.forEach((element) => observer[method](element, options));
|
|
50
|
+
}
|
|
51
|
+
if (targetType === "array") {
|
|
52
|
+
target.forEach((element) => observer[method](element, options));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/dom/observers/resize-observer.js
|
|
57
|
+
function resizeObserver(target, options) {
|
|
58
|
+
const { callback, ...opts } = options;
|
|
59
|
+
const observer = new ResizeObserver(observerFn);
|
|
60
|
+
if (target === window) target = document.body;
|
|
61
|
+
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
62
|
+
function observerFn(entries) {
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
if (callback) callback({ entry, entries, observer });
|
|
65
|
+
else dispatchEvent(target, "resize-obs", { entry, entries, observer });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
observe(target2) {
|
|
70
|
+
useObserverMethodOnTarget(target2, observer, "observe", options);
|
|
71
|
+
},
|
|
72
|
+
unobserve(target2) {
|
|
73
|
+
useObserverMethodOnTarget(target2, observer, "unobserve");
|
|
74
|
+
},
|
|
75
|
+
disconnect: (_) => observer.disconnect(),
|
|
76
|
+
destroy: (_) => observer.disconnect()
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/dom/observers/scroll-observer.js
|
|
81
|
+
var defaultOptions = {
|
|
82
|
+
threshold: 0,
|
|
83
|
+
// Float between 0 to 1.
|
|
84
|
+
tolerance: 0.1,
|
|
85
|
+
// Float between 0 to 1. Tolerance for event firing
|
|
86
|
+
throttle: 16,
|
|
87
|
+
// Throttle interval in ms (default: ~60fps)
|
|
88
|
+
once: false
|
|
89
|
+
// Only fire threshold callback once
|
|
90
|
+
};
|
|
91
|
+
function scrollObserver(node, options = {}) {
|
|
92
|
+
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
93
|
+
const opts = { ...defaultOptions, ...userOpts };
|
|
94
|
+
const { threshold, tolerance, throttle, once } = opts;
|
|
95
|
+
const prevScrollDirection = null;
|
|
96
|
+
let prevScrollTop = 0;
|
|
97
|
+
let prevScrollPercent = 0;
|
|
98
|
+
let lastThrottleTime = 0;
|
|
99
|
+
let thresholdFired = false;
|
|
100
|
+
let rafId = null;
|
|
101
|
+
const isDocumentScroll = node === document || node === window;
|
|
102
|
+
const scrollElement = isDocumentScroll ? document.documentElement : node;
|
|
103
|
+
let cachedScrollHeight = 0;
|
|
104
|
+
let cachedClientHeight = 0;
|
|
105
|
+
updateCache();
|
|
106
|
+
const cacheObserver = resizeObserver(scrollElement, {
|
|
107
|
+
callback: updateCache
|
|
108
|
+
});
|
|
109
|
+
node.addEventListener("scroll", throttledObserve, { passive: true });
|
|
110
|
+
function updateCache() {
|
|
111
|
+
cachedScrollHeight = scrollElement.scrollHeight;
|
|
112
|
+
cachedClientHeight = scrollElement.clientHeight;
|
|
113
|
+
}
|
|
114
|
+
function throttledObserve() {
|
|
115
|
+
const now = Date.now();
|
|
116
|
+
if (now - lastThrottleTime < throttle) return;
|
|
117
|
+
lastThrottleTime = now;
|
|
118
|
+
rafId = requestAnimationFrame(observe);
|
|
119
|
+
}
|
|
120
|
+
function observe() {
|
|
121
|
+
const scrollTop = scrollElement.scrollTop;
|
|
122
|
+
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
123
|
+
const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
|
|
124
|
+
const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
|
|
125
|
+
const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
|
|
126
|
+
const thresholdMin = threshold - tolerance / 2;
|
|
127
|
+
const thresholdMax = threshold + tolerance / 2;
|
|
128
|
+
const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
|
|
129
|
+
const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
|
|
130
|
+
const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
|
|
131
|
+
if (hasEnteredThreshold && once) {
|
|
132
|
+
thresholdFired = true;
|
|
133
|
+
}
|
|
134
|
+
const callbackData = {
|
|
135
|
+
scrollTop,
|
|
136
|
+
scrollDirection,
|
|
137
|
+
scrollPercent,
|
|
138
|
+
directionChanged: scrollDirection !== prevScrollDirection,
|
|
139
|
+
hasEnteredThreshold,
|
|
140
|
+
isInThreshold
|
|
141
|
+
};
|
|
142
|
+
if (typeof callback === "function") {
|
|
143
|
+
callback(callbackData);
|
|
144
|
+
}
|
|
145
|
+
if (scrollDirection !== prevScrollDirection) {
|
|
146
|
+
if (scrollDirection === "down" && typeof onScrollDown === "function") {
|
|
147
|
+
onScrollDown(callbackData);
|
|
148
|
+
}
|
|
149
|
+
if (scrollDirection === "up" && typeof onScrollUp === "function") {
|
|
150
|
+
onScrollUp(callbackData);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
|
|
154
|
+
onEnterThreshold(callbackData);
|
|
155
|
+
}
|
|
156
|
+
prevScrollTop = scrollTop;
|
|
157
|
+
prevScrollPercent = scrollPercent;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
destroy() {
|
|
161
|
+
node.removeEventListener("scroll", throttledObserve);
|
|
162
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
163
|
+
cacheObserver.destroy();
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
168
|
+
0 && (module.exports = {
|
|
169
|
+
scrollObserver
|
|
170
|
+
});
|
|
@@ -20,8 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var functional_exports = {};
|
|
21
21
|
__export(functional_exports, {
|
|
22
22
|
compose: () => compose,
|
|
23
|
+
composeAsync: () => composeAsync,
|
|
23
24
|
curry: () => curry,
|
|
24
25
|
pipe: () => pipe,
|
|
26
|
+
pipeAsync: () => pipeAsync,
|
|
25
27
|
times: () => times
|
|
26
28
|
});
|
|
27
29
|
module.exports = __toCommonJS(functional_exports);
|
|
@@ -41,11 +43,27 @@ function compose(...fns) {
|
|
|
41
43
|
return fns.reduceRight((acc, fn) => fn(acc), value);
|
|
42
44
|
};
|
|
43
45
|
}
|
|
46
|
+
function composeAsync(...fns) {
|
|
47
|
+
return async function(value) {
|
|
48
|
+
return fns.reduceRight(async (acc, fn) => {
|
|
49
|
+
const result = await acc;
|
|
50
|
+
return await fn(result);
|
|
51
|
+
}, value);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
44
54
|
function pipe(...fns) {
|
|
45
55
|
return function(value) {
|
|
46
56
|
return fns.reduce((acc, fn) => fn(acc), value);
|
|
47
57
|
};
|
|
48
58
|
}
|
|
59
|
+
function pipeAsync(...fns) {
|
|
60
|
+
return async function(value) {
|
|
61
|
+
return fns.reduce(async (acc, fn) => {
|
|
62
|
+
const result = await acc;
|
|
63
|
+
return await fn(result);
|
|
64
|
+
}, value);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
49
67
|
function times(fn, n) {
|
|
50
68
|
const result = [];
|
|
51
69
|
for (let i = 0; i < n; i++) {
|
|
@@ -56,7 +74,9 @@ function times(fn, n) {
|
|
|
56
74
|
// Annotate the CommonJS export names for ESM import in node:
|
|
57
75
|
0 && (module.exports = {
|
|
58
76
|
compose,
|
|
77
|
+
composeAsync,
|
|
59
78
|
curry,
|
|
60
79
|
pipe,
|
|
80
|
+
pipeAsync,
|
|
61
81
|
times
|
|
62
82
|
});
|
|
@@ -20,11 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var functions_exports = {};
|
|
21
21
|
__export(functions_exports, {
|
|
22
22
|
compose: () => compose,
|
|
23
|
+
composeAsync: () => composeAsync,
|
|
23
24
|
curry: () => curry,
|
|
24
25
|
debounce: () => debounce,
|
|
25
26
|
delay: () => delay,
|
|
26
27
|
getEnv: () => getEnv,
|
|
27
28
|
pipe: () => pipe,
|
|
29
|
+
pipeAsync: () => pipeAsync,
|
|
28
30
|
throttle: () => throttle,
|
|
29
31
|
timeout: () => timeout,
|
|
30
32
|
times: () => times,
|
|
@@ -72,11 +74,27 @@ function compose(...fns) {
|
|
|
72
74
|
return fns.reduceRight((acc, fn) => fn(acc), value);
|
|
73
75
|
};
|
|
74
76
|
}
|
|
77
|
+
function composeAsync(...fns) {
|
|
78
|
+
return async function(value) {
|
|
79
|
+
return fns.reduceRight(async (acc, fn) => {
|
|
80
|
+
const result = await acc;
|
|
81
|
+
return await fn(result);
|
|
82
|
+
}, value);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
75
85
|
function pipe(...fns) {
|
|
76
86
|
return function(value) {
|
|
77
87
|
return fns.reduce((acc, fn) => fn(acc), value);
|
|
78
88
|
};
|
|
79
89
|
}
|
|
90
|
+
function pipeAsync(...fns) {
|
|
91
|
+
return async function(value) {
|
|
92
|
+
return fns.reduce(async (acc, fn) => {
|
|
93
|
+
const result = await acc;
|
|
94
|
+
return await fn(result);
|
|
95
|
+
}, value);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
80
98
|
function times(fn, n) {
|
|
81
99
|
const result = [];
|
|
82
100
|
for (let i = 0; i < n; i++) {
|
|
@@ -110,11 +128,13 @@ function wait(ms) {
|
|
|
110
128
|
// Annotate the CommonJS export names for ESM import in node:
|
|
111
129
|
0 && (module.exports = {
|
|
112
130
|
compose,
|
|
131
|
+
composeAsync,
|
|
113
132
|
curry,
|
|
114
133
|
debounce,
|
|
115
134
|
delay,
|
|
116
135
|
getEnv,
|
|
117
136
|
pipe,
|
|
137
|
+
pipeAsync,
|
|
118
138
|
throttle,
|
|
119
139
|
timeout,
|
|
120
140
|
times,
|
package/dist/cjs/lib/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(lib_exports, {
|
|
|
35
35
|
RouteManager: () => RouteManager,
|
|
36
36
|
camelCaseKeys: () => camelCaseKeys,
|
|
37
37
|
compose: () => compose,
|
|
38
|
+
composeAsync: () => composeAsync,
|
|
38
39
|
concatMix: () => concatMix,
|
|
39
40
|
createMix: () => createMix,
|
|
40
41
|
createSSE: () => createSSE,
|
|
@@ -76,6 +77,7 @@ __export(lib_exports, {
|
|
|
76
77
|
parseJSON: () => parseJSON,
|
|
77
78
|
parseSSE: () => parseSSE,
|
|
78
79
|
pipe: () => pipe,
|
|
80
|
+
pipeAsync: () => pipeAsync,
|
|
79
81
|
plural: () => plural,
|
|
80
82
|
pluralize: () => pluralize,
|
|
81
83
|
reject: () => reject,
|
|
@@ -568,11 +570,27 @@ function compose(...fns) {
|
|
|
568
570
|
return fns.reduceRight((acc, fn) => fn(acc), value);
|
|
569
571
|
};
|
|
570
572
|
}
|
|
573
|
+
function composeAsync(...fns) {
|
|
574
|
+
return async function(value) {
|
|
575
|
+
return fns.reduceRight(async (acc, fn) => {
|
|
576
|
+
const result = await acc;
|
|
577
|
+
return await fn(result);
|
|
578
|
+
}, value);
|
|
579
|
+
};
|
|
580
|
+
}
|
|
571
581
|
function pipe(...fns) {
|
|
572
582
|
return function(value) {
|
|
573
583
|
return fns.reduce((acc, fn) => fn(acc), value);
|
|
574
584
|
};
|
|
575
585
|
}
|
|
586
|
+
function pipeAsync(...fns) {
|
|
587
|
+
return async function(value) {
|
|
588
|
+
return fns.reduce(async (acc, fn) => {
|
|
589
|
+
const result = await acc;
|
|
590
|
+
return await fn(result);
|
|
591
|
+
}, value);
|
|
592
|
+
};
|
|
593
|
+
}
|
|
576
594
|
function times(fn, n) {
|
|
577
595
|
const result = [];
|
|
578
596
|
for (let i = 0; i < n; i++) {
|
|
@@ -1065,6 +1083,7 @@ function getSymbolValue(object, description) {
|
|
|
1065
1083
|
RouteManager,
|
|
1066
1084
|
camelCaseKeys,
|
|
1067
1085
|
compose,
|
|
1086
|
+
composeAsync,
|
|
1068
1087
|
concatMix,
|
|
1069
1088
|
createMix,
|
|
1070
1089
|
createSSE,
|
|
@@ -1106,6 +1125,7 @@ function getSymbolValue(object, description) {
|
|
|
1106
1125
|
parseJSON,
|
|
1107
1126
|
parseSSE,
|
|
1108
1127
|
pipe,
|
|
1128
|
+
pipeAsync,
|
|
1109
1129
|
plural,
|
|
1110
1130
|
pluralize,
|
|
1111
1131
|
reject,
|
package/dist/esm/dom/index.js
CHANGED
|
@@ -847,6 +847,94 @@ function mutationObserver(target, options) {
|
|
|
847
847
|
};
|
|
848
848
|
}
|
|
849
849
|
|
|
850
|
+
// src/dom/observers/scroll-observer.js
|
|
851
|
+
var defaultOptions2 = {
|
|
852
|
+
threshold: 0,
|
|
853
|
+
// Float between 0 to 1.
|
|
854
|
+
tolerance: 0.1,
|
|
855
|
+
// Float between 0 to 1. Tolerance for event firing
|
|
856
|
+
throttle: 16,
|
|
857
|
+
// Throttle interval in ms (default: ~60fps)
|
|
858
|
+
once: false
|
|
859
|
+
// Only fire threshold callback once
|
|
860
|
+
};
|
|
861
|
+
function scrollObserver(node, options = {}) {
|
|
862
|
+
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
863
|
+
const opts = { ...defaultOptions2, ...userOpts };
|
|
864
|
+
const { threshold, tolerance, throttle, once } = opts;
|
|
865
|
+
const prevScrollDirection = null;
|
|
866
|
+
let prevScrollTop = 0;
|
|
867
|
+
let prevScrollPercent = 0;
|
|
868
|
+
let lastThrottleTime = 0;
|
|
869
|
+
let thresholdFired = false;
|
|
870
|
+
let rafId = null;
|
|
871
|
+
const isDocumentScroll = node === document || node === window;
|
|
872
|
+
const scrollElement = isDocumentScroll ? document.documentElement : node;
|
|
873
|
+
let cachedScrollHeight = 0;
|
|
874
|
+
let cachedClientHeight = 0;
|
|
875
|
+
updateCache();
|
|
876
|
+
const cacheObserver = resizeObserver(scrollElement, {
|
|
877
|
+
callback: updateCache
|
|
878
|
+
});
|
|
879
|
+
node.addEventListener("scroll", throttledObserve, { passive: true });
|
|
880
|
+
function updateCache() {
|
|
881
|
+
cachedScrollHeight = scrollElement.scrollHeight;
|
|
882
|
+
cachedClientHeight = scrollElement.clientHeight;
|
|
883
|
+
}
|
|
884
|
+
function throttledObserve() {
|
|
885
|
+
const now = Date.now();
|
|
886
|
+
if (now - lastThrottleTime < throttle) return;
|
|
887
|
+
lastThrottleTime = now;
|
|
888
|
+
rafId = requestAnimationFrame(observe);
|
|
889
|
+
}
|
|
890
|
+
function observe() {
|
|
891
|
+
const scrollTop = scrollElement.scrollTop;
|
|
892
|
+
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
893
|
+
const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
|
|
894
|
+
const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
|
|
895
|
+
const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
|
|
896
|
+
const thresholdMin = threshold - tolerance / 2;
|
|
897
|
+
const thresholdMax = threshold + tolerance / 2;
|
|
898
|
+
const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
|
|
899
|
+
const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
|
|
900
|
+
const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
|
|
901
|
+
if (hasEnteredThreshold && once) {
|
|
902
|
+
thresholdFired = true;
|
|
903
|
+
}
|
|
904
|
+
const callbackData = {
|
|
905
|
+
scrollTop,
|
|
906
|
+
scrollDirection,
|
|
907
|
+
scrollPercent,
|
|
908
|
+
directionChanged: scrollDirection !== prevScrollDirection,
|
|
909
|
+
hasEnteredThreshold,
|
|
910
|
+
isInThreshold
|
|
911
|
+
};
|
|
912
|
+
if (typeof callback === "function") {
|
|
913
|
+
callback(callbackData);
|
|
914
|
+
}
|
|
915
|
+
if (scrollDirection !== prevScrollDirection) {
|
|
916
|
+
if (scrollDirection === "down" && typeof onScrollDown === "function") {
|
|
917
|
+
onScrollDown(callbackData);
|
|
918
|
+
}
|
|
919
|
+
if (scrollDirection === "up" && typeof onScrollUp === "function") {
|
|
920
|
+
onScrollUp(callbackData);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
|
|
924
|
+
onEnterThreshold(callbackData);
|
|
925
|
+
}
|
|
926
|
+
prevScrollTop = scrollTop;
|
|
927
|
+
prevScrollPercent = scrollPercent;
|
|
928
|
+
}
|
|
929
|
+
return {
|
|
930
|
+
destroy() {
|
|
931
|
+
node.removeEventListener("scroll", throttledObserve);
|
|
932
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
933
|
+
cacheObserver.destroy();
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
|
|
850
938
|
// src/dom/random-string.js
|
|
851
939
|
function randomString(length = 10) {
|
|
852
940
|
const firstLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
|
@@ -1085,6 +1173,7 @@ export {
|
|
|
1085
1173
|
removeListeners,
|
|
1086
1174
|
resizeObserver,
|
|
1087
1175
|
sanitize2 as sanitize,
|
|
1176
|
+
scrollObserver,
|
|
1088
1177
|
scrollToElement,
|
|
1089
1178
|
sessionStore,
|
|
1090
1179
|
setCSSValue,
|