/
ScrollManager.tsx
54 lines (49 loc) · 1.5 KB
/
ScrollManager.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/** @jsx jsx */
import { jsx } from '@emotion/react';
import { Fragment, ReactElement, RefCallback } from 'react';
import useScrollCapture from './useScrollCapture';
import useScrollLock from './useScrollLock';
interface Props {
readonly children: (ref: RefCallback<HTMLElement>) => ReactElement;
readonly lockEnabled: boolean;
readonly captureEnabled: boolean;
readonly onBottomArrive?: (event: WheelEvent | TouchEvent) => void;
readonly onBottomLeave?: (event: WheelEvent | TouchEvent) => void;
readonly onTopArrive?: (event: WheelEvent | TouchEvent) => void;
readonly onTopLeave?: (event: WheelEvent | TouchEvent) => void;
}
const blurSelectInput = () =>
document.activeElement && (document.activeElement as HTMLElement).blur();
export default function ScrollManager({
children,
lockEnabled,
captureEnabled = true,
onBottomArrive,
onBottomLeave,
onTopArrive,
onTopLeave,
}: Props) {
const setScrollCaptureTarget = useScrollCapture({
isEnabled: captureEnabled,
onBottomArrive,
onBottomLeave,
onTopArrive,
onTopLeave,
});
const setScrollLockTarget = useScrollLock({ isEnabled: lockEnabled });
const targetRef: RefCallback<HTMLElement> = (element) => {
setScrollCaptureTarget(element);
setScrollLockTarget(element);
};
return (
<Fragment>
{lockEnabled && (
<div
onClick={blurSelectInput}
css={{ position: 'fixed', left: 0, bottom: 0, right: 0, top: 0 }}
/>
)}
{children(targetRef)}
</Fragment>
);
}