@sohanemon/utils 5.2.0 → 5.2.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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ScrollableMarker(): any;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useScheduledEffect } from '../hooks/schedule';
|
|
3
|
+
export function ScrollableMarker() {
|
|
4
|
+
useScheduledEffect(() => {
|
|
5
|
+
const root = document.body;
|
|
6
|
+
if (!root)
|
|
7
|
+
return;
|
|
8
|
+
const isScrollable = (el) => {
|
|
9
|
+
const style = getComputedStyle(el);
|
|
10
|
+
if (style.overflow === 'hidden' &&
|
|
11
|
+
style.overflowY === 'hidden' &&
|
|
12
|
+
style.overflowX === 'hidden')
|
|
13
|
+
return false;
|
|
14
|
+
const canScrollY = (style.overflowY === 'auto' || style.overflowY === 'scroll') &&
|
|
15
|
+
el.scrollHeight > el.clientHeight;
|
|
16
|
+
const canScrollX = (style.overflowX === 'auto' || style.overflowX === 'scroll') &&
|
|
17
|
+
el.scrollWidth > el.clientWidth;
|
|
18
|
+
return canScrollY || canScrollX;
|
|
19
|
+
};
|
|
20
|
+
const markScrollable = (el) => {
|
|
21
|
+
if (isScrollable(el))
|
|
22
|
+
el.dataset.scrollable = 'true';
|
|
23
|
+
else
|
|
24
|
+
delete el.dataset.scrollable;
|
|
25
|
+
};
|
|
26
|
+
const scanTree = (node) => {
|
|
27
|
+
markScrollable(node);
|
|
28
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
29
|
+
const child = node.children[i];
|
|
30
|
+
scanTree(child);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
requestIdleCallback(() => scanTree(root));
|
|
34
|
+
const observer = new MutationObserver((mutations) => {
|
|
35
|
+
for (const m of mutations) {
|
|
36
|
+
if (m.type === 'childList') {
|
|
37
|
+
m.addedNodes.forEach((n) => {
|
|
38
|
+
if (n instanceof HTMLElement)
|
|
39
|
+
scanTree(n);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else if (m.type === 'attributes' && m.target instanceof HTMLElement) {
|
|
43
|
+
markScrollable(m.target);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
observer.observe(root, {
|
|
48
|
+
subtree: true,
|
|
49
|
+
childList: true,
|
|
50
|
+
attributes: true,
|
|
51
|
+
attributeFilter: ['style', 'class'],
|
|
52
|
+
});
|
|
53
|
+
return () => observer.disconnect();
|
|
54
|
+
}, []);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
package/dist/hooks/schedule.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare function useSchedule(options?: ScheduleOpts): (task: Task) => voi
|
|
|
13
13
|
* or a fallback scheduler. Useful for heavy computations, logging,
|
|
14
14
|
* analytics, or background work that doesn't need to block render.
|
|
15
15
|
*
|
|
16
|
-
* @param {
|
|
16
|
+
* @param {Function} effect - The function to run later. Can be synchronous or return a Promise.
|
|
17
17
|
* @param {React.DependencyList[]} deps - Dependency array; task will re-run whenever these change.
|
|
18
18
|
* @param {ScheduleOpts} [options] - Optional scheduling options.
|
|
19
19
|
* @param {number} [options.timeout] - Max time (ms) to wait before executing the task. Defaults to 10000.
|
|
@@ -33,4 +33,4 @@ export declare function useSchedule(options?: ScheduleOpts): (task: Task) => voi
|
|
|
33
33
|
* }
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export declare function useScheduledEffect(
|
|
36
|
+
export declare function useScheduledEffect(effect: () => void | (() => void), deps?: React.DependencyList, options?: ScheduleOpts): void;
|
package/dist/hooks/schedule.js
CHANGED
|
@@ -33,7 +33,7 @@ export function useSchedule(options = {}) {
|
|
|
33
33
|
* or a fallback scheduler. Useful for heavy computations, logging,
|
|
34
34
|
* analytics, or background work that doesn't need to block render.
|
|
35
35
|
*
|
|
36
|
-
* @param {
|
|
36
|
+
* @param {Function} effect - The function to run later. Can be synchronous or return a Promise.
|
|
37
37
|
* @param {React.DependencyList[]} deps - Dependency array; task will re-run whenever these change.
|
|
38
38
|
* @param {ScheduleOpts} [options] - Optional scheduling options.
|
|
39
39
|
* @param {number} [options.timeout] - Max time (ms) to wait before executing the task. Defaults to 10000.
|
|
@@ -53,9 +53,16 @@ export function useSchedule(options = {}) {
|
|
|
53
53
|
* }
|
|
54
54
|
* ```
|
|
55
55
|
*/
|
|
56
|
-
export function useScheduledEffect(
|
|
56
|
+
export function useScheduledEffect(effect, deps = [], options = {}) {
|
|
57
57
|
const schedule = useSchedule(options);
|
|
58
58
|
React.useEffect(() => {
|
|
59
|
-
|
|
59
|
+
let cleanup;
|
|
60
|
+
schedule(() => {
|
|
61
|
+
cleanup = effect();
|
|
62
|
+
});
|
|
63
|
+
return () => {
|
|
64
|
+
if (typeof cleanup === 'function')
|
|
65
|
+
cleanup?.();
|
|
66
|
+
};
|
|
60
67
|
}, [schedule, ...deps]);
|
|
61
68
|
}
|