@splendidlabz/utils 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/cjs/dom/events.cjs +0 -36
- package/dist/cjs/dom/index.cjs +90 -36
- package/dist/cjs/dom/observers/index.cjs +92 -2
- package/dist/cjs/dom/observers/scroll-observer.cjs +170 -0
- package/dist/cjs/lib/functions/callback.cjs +31 -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/events.js +0 -35
- package/dist/esm/dom/index.js +89 -35
- package/dist/esm/dom/observers/index.js +90 -1
- package/dist/esm/dom/observers/scroll-observer.js +144 -0
- package/dist/esm/lib/functions/callback.js +7 -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/events.d.cts +90 -18
- package/dist/types/dom/index.d.cts +2 -1
- 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/callback.d.cts +8 -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/events.js +44 -50
- 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/callback.js +8 -0
- package/src/lib/functions/functional.js +82 -0
- package/src/lib/functions/functional.test.js +196 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @splendidlabz/utils
|
|
2
2
|
|
|
3
|
+
## 1.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8f2cb34: - 48406c69 Add JSDocs for events
|
|
8
|
+
- 304b5310 Utils: Add runCallback
|
|
9
|
+
|
|
10
|
+
## 1.8.2
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- - abd0770c Add pipeAsync and composeAsync along with tests
|
|
15
|
+
|
|
3
16
|
## 1.8.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/cjs/dom/events.cjs
CHANGED
|
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var events_exports = {};
|
|
21
21
|
__export(events_exports, {
|
|
22
22
|
addListeners: () => addListeners,
|
|
23
|
-
createListeners: () => createListeners,
|
|
24
23
|
dispatchEvent: () => dispatchEvent,
|
|
25
24
|
removeListeners: () => removeListeners,
|
|
26
25
|
updateEvent: () => updateEvent
|
|
@@ -51,44 +50,9 @@ function updateEvent(event, updates) {
|
|
|
51
50
|
...updates
|
|
52
51
|
});
|
|
53
52
|
}
|
|
54
|
-
function createListeners(listeners) {
|
|
55
|
-
listeners = listeners || [];
|
|
56
|
-
listeners.forEach((listener) => {
|
|
57
|
-
const { node, event, handler } = listener;
|
|
58
|
-
node.addEventListener(event, handler);
|
|
59
|
-
});
|
|
60
|
-
return {
|
|
61
|
-
get list() {
|
|
62
|
-
return listeners;
|
|
63
|
-
},
|
|
64
|
-
add({ node, event, handler }) {
|
|
65
|
-
listeners.push({ node, event, handler });
|
|
66
|
-
node.addEventListener(event, handler);
|
|
67
|
-
},
|
|
68
|
-
remove({ node, event, handler }) {
|
|
69
|
-
const index = listeners.findIndex((listener) => {
|
|
70
|
-
if (listener.node === node && listener.event === event && listener.handler === handler) {
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
});
|
|
75
|
-
if (index !== -1) {
|
|
76
|
-
listeners.splice(index, 1);
|
|
77
|
-
node.removeEventListener(event, handler);
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
clear() {
|
|
81
|
-
listeners.forEach(({ node, event, handler }) => {
|
|
82
|
-
listeners = [];
|
|
83
|
-
node.removeEventListener(event, handler);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
53
|
// Annotate the CommonJS export names for ESM import in node:
|
|
89
54
|
0 && (module.exports = {
|
|
90
55
|
addListeners,
|
|
91
|
-
createListeners,
|
|
92
56
|
dispatchEvent,
|
|
93
57
|
removeListeners,
|
|
94
58
|
updateEvent
|
package/dist/cjs/dom/index.cjs
CHANGED
|
@@ -37,7 +37,6 @@ __export(dom_exports, {
|
|
|
37
37
|
checkForAccessibleName: () => checkForAccessibleName,
|
|
38
38
|
cookies: () => cookies,
|
|
39
39
|
copyRichText: () => copyRichText,
|
|
40
|
-
createListeners: () => createListeners,
|
|
41
40
|
dispatchEvent: () => dispatchEvent,
|
|
42
41
|
em: () => em,
|
|
43
42
|
findScrollContainer: () => findScrollContainer,
|
|
@@ -79,6 +78,7 @@ __export(dom_exports, {
|
|
|
79
78
|
removeListeners: () => removeListeners,
|
|
80
79
|
resizeObserver: () => resizeObserver,
|
|
81
80
|
sanitize: () => sanitize2,
|
|
81
|
+
scrollObserver: () => scrollObserver,
|
|
82
82
|
scrollToElement: () => scrollToElement,
|
|
83
83
|
sessionStore: () => sessionStore,
|
|
84
84
|
setCSSValue: () => setCSSValue,
|
|
@@ -230,40 +230,6 @@ function updateEvent(event, updates) {
|
|
|
230
230
|
...updates
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
function createListeners(listeners) {
|
|
234
|
-
listeners = listeners || [];
|
|
235
|
-
listeners.forEach((listener) => {
|
|
236
|
-
const { node, event, handler } = listener;
|
|
237
|
-
node.addEventListener(event, handler);
|
|
238
|
-
});
|
|
239
|
-
return {
|
|
240
|
-
get list() {
|
|
241
|
-
return listeners;
|
|
242
|
-
},
|
|
243
|
-
add({ node, event, handler }) {
|
|
244
|
-
listeners.push({ node, event, handler });
|
|
245
|
-
node.addEventListener(event, handler);
|
|
246
|
-
},
|
|
247
|
-
remove({ node, event, handler }) {
|
|
248
|
-
const index = listeners.findIndex((listener) => {
|
|
249
|
-
if (listener.node === node && listener.event === event && listener.handler === handler) {
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
|
-
return false;
|
|
253
|
-
});
|
|
254
|
-
if (index !== -1) {
|
|
255
|
-
listeners.splice(index, 1);
|
|
256
|
-
node.removeEventListener(event, handler);
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
clear() {
|
|
260
|
-
listeners.forEach(({ node, event, handler }) => {
|
|
261
|
-
listeners = [];
|
|
262
|
-
node.removeEventListener(event, handler);
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
233
|
|
|
268
234
|
// src/dom/observers/observer.js
|
|
269
235
|
function useObserverMethodOnTarget(target, observer, method = "observe", options = void 0) {
|
|
@@ -943,6 +909,94 @@ function mutationObserver(target, options) {
|
|
|
943
909
|
};
|
|
944
910
|
}
|
|
945
911
|
|
|
912
|
+
// src/dom/observers/scroll-observer.js
|
|
913
|
+
var defaultOptions2 = {
|
|
914
|
+
threshold: 0,
|
|
915
|
+
// Float between 0 to 1.
|
|
916
|
+
tolerance: 0.1,
|
|
917
|
+
// Float between 0 to 1. Tolerance for event firing
|
|
918
|
+
throttle: 16,
|
|
919
|
+
// Throttle interval in ms (default: ~60fps)
|
|
920
|
+
once: false
|
|
921
|
+
// Only fire threshold callback once
|
|
922
|
+
};
|
|
923
|
+
function scrollObserver(node, options = {}) {
|
|
924
|
+
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
925
|
+
const opts = { ...defaultOptions2, ...userOpts };
|
|
926
|
+
const { threshold, tolerance, throttle, once } = opts;
|
|
927
|
+
const prevScrollDirection = null;
|
|
928
|
+
let prevScrollTop = 0;
|
|
929
|
+
let prevScrollPercent = 0;
|
|
930
|
+
let lastThrottleTime = 0;
|
|
931
|
+
let thresholdFired = false;
|
|
932
|
+
let rafId = null;
|
|
933
|
+
const isDocumentScroll = node === document || node === window;
|
|
934
|
+
const scrollElement = isDocumentScroll ? document.documentElement : node;
|
|
935
|
+
let cachedScrollHeight = 0;
|
|
936
|
+
let cachedClientHeight = 0;
|
|
937
|
+
updateCache();
|
|
938
|
+
const cacheObserver = resizeObserver(scrollElement, {
|
|
939
|
+
callback: updateCache
|
|
940
|
+
});
|
|
941
|
+
node.addEventListener("scroll", throttledObserve, { passive: true });
|
|
942
|
+
function updateCache() {
|
|
943
|
+
cachedScrollHeight = scrollElement.scrollHeight;
|
|
944
|
+
cachedClientHeight = scrollElement.clientHeight;
|
|
945
|
+
}
|
|
946
|
+
function throttledObserve() {
|
|
947
|
+
const now = Date.now();
|
|
948
|
+
if (now - lastThrottleTime < throttle) return;
|
|
949
|
+
lastThrottleTime = now;
|
|
950
|
+
rafId = requestAnimationFrame(observe);
|
|
951
|
+
}
|
|
952
|
+
function observe() {
|
|
953
|
+
const scrollTop = scrollElement.scrollTop;
|
|
954
|
+
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
955
|
+
const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
|
|
956
|
+
const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
|
|
957
|
+
const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
|
|
958
|
+
const thresholdMin = threshold - tolerance / 2;
|
|
959
|
+
const thresholdMax = threshold + tolerance / 2;
|
|
960
|
+
const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
|
|
961
|
+
const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
|
|
962
|
+
const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
|
|
963
|
+
if (hasEnteredThreshold && once) {
|
|
964
|
+
thresholdFired = true;
|
|
965
|
+
}
|
|
966
|
+
const callbackData = {
|
|
967
|
+
scrollTop,
|
|
968
|
+
scrollDirection,
|
|
969
|
+
scrollPercent,
|
|
970
|
+
directionChanged: scrollDirection !== prevScrollDirection,
|
|
971
|
+
hasEnteredThreshold,
|
|
972
|
+
isInThreshold
|
|
973
|
+
};
|
|
974
|
+
if (typeof callback === "function") {
|
|
975
|
+
callback(callbackData);
|
|
976
|
+
}
|
|
977
|
+
if (scrollDirection !== prevScrollDirection) {
|
|
978
|
+
if (scrollDirection === "down" && typeof onScrollDown === "function") {
|
|
979
|
+
onScrollDown(callbackData);
|
|
980
|
+
}
|
|
981
|
+
if (scrollDirection === "up" && typeof onScrollUp === "function") {
|
|
982
|
+
onScrollUp(callbackData);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
|
|
986
|
+
onEnterThreshold(callbackData);
|
|
987
|
+
}
|
|
988
|
+
prevScrollTop = scrollTop;
|
|
989
|
+
prevScrollPercent = scrollPercent;
|
|
990
|
+
}
|
|
991
|
+
return {
|
|
992
|
+
destroy() {
|
|
993
|
+
node.removeEventListener("scroll", throttledObserve);
|
|
994
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
995
|
+
cacheObserver.destroy();
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
|
|
946
1000
|
// src/dom/random-string.js
|
|
947
1001
|
function randomString(length = 10) {
|
|
948
1002
|
const firstLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
|
@@ -1140,7 +1194,6 @@ function scrambleText(text) {
|
|
|
1140
1194
|
checkForAccessibleName,
|
|
1141
1195
|
cookies,
|
|
1142
1196
|
copyRichText,
|
|
1143
|
-
createListeners,
|
|
1144
1197
|
dispatchEvent,
|
|
1145
1198
|
em,
|
|
1146
1199
|
findScrollContainer,
|
|
@@ -1182,6 +1235,7 @@ function scrambleText(text) {
|
|
|
1182
1235
|
removeListeners,
|
|
1183
1236
|
resizeObserver,
|
|
1184
1237
|
sanitize,
|
|
1238
|
+
scrollObserver,
|
|
1185
1239
|
scrollToElement,
|
|
1186
1240
|
sessionStore,
|
|
1187
1241
|
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
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
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/lib/functions/callback.js
|
|
20
|
+
var callback_exports = {};
|
|
21
|
+
__export(callback_exports, {
|
|
22
|
+
runCallback: () => runCallback
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(callback_exports);
|
|
25
|
+
function runCallback(fn, ...data) {
|
|
26
|
+
if (typeof fn === "function") fn(data);
|
|
27
|
+
}
|
|
28
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
29
|
+
0 && (module.exports = {
|
|
30
|
+
runCallback
|
|
31
|
+
});
|
|
@@ -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,
|