diff --git a/src/components/FitCenter.tsx b/src/components/FitCenter.tsx index ede8b2e..4db55b9 100644 --- a/src/components/FitCenter.tsx +++ b/src/components/FitCenter.tsx @@ -1,10 +1,13 @@ import React from 'react' import '@/assets/css/fit-center.scss' -const FitCenter: React.FC = (props: PropsWithChildren) => { +const FitCenter: React.FC< + React.DetailedHTMLProps, HTMLDivElement> +> = (props) => { + const { className, ..._props } = props return ( <> -
{props.children}
+
) } diff --git a/src/components/FitFullScreen.tsx b/src/components/FitFullScreen.tsx index e356c2c..3a05f1b 100644 --- a/src/components/FitFullScreen.tsx +++ b/src/components/FitFullScreen.tsx @@ -1,20 +1,25 @@ +import React from 'react' import '@/assets/css/fit-fullscreen.scss' -interface FitFullscreenProps extends PropsWithChildren { +interface FitFullscreenProps + extends React.DetailedHTMLProps, HTMLDivElement> { zIndex?: number backgroundColor?: string } const FitFullScreen = forwardRef((props, ref) => { + const { zIndex, backgroundColor, className, style, ..._props } = props return ( <>
{props.children}
diff --git a/src/components/HideScrollbar.tsx b/src/components/HideScrollbar.tsx index 52a4644..76a3714 100644 --- a/src/components/HideScrollbar.tsx +++ b/src/components/HideScrollbar.tsx @@ -1,5 +1,11 @@ +import React from 'react' import '@/assets/css/hide-scrollbar.scss' +interface HideScrollbarProps + extends React.DetailedHTMLProps, HTMLDivElement> { + isPreventScroll?: boolean +} + export interface HideScrollbarElement { scrollTo(x: number, y: number): void scrollX(x: number): void @@ -32,11 +38,45 @@ export interface HideScrollbarElement { ): void } -const HideScrollbar = forwardRef((props, ref) => { +const HideScrollbar = forwardRef((props, ref) => { const rootRef = useRef(null) const [verticalScrollbarWidth, setVerticalScrollbarWidth] = useState(0) const [horizontalScrollbarWidth, setHorizontalScrollbarWidth] = useState(0) + const { isPreventScroll, ..._props } = props + const handleDefaultWheel = useCallback((event: WheelEvent) => { + event.preventDefault() + }, []) + + const handleDefaultTouchmove = useCallback((event: TouchEvent) => { + event.preventDefault() + }, []) + + const handleDefaultClickMiddleMouseButton = useCallback((event: MouseEvent) => { + if (event.button === 1) { + event.preventDefault() + } + }, []) + + const handleDefaultKeyDown = (event: KeyboardEvent) => { + if ( + [ + 'ArrowUp', + 'ArrowDown', + 'ArrowLeft', + 'ArrowRight', + ' ', + '', + 'PageUp', + 'PageDown', + 'Home', + 'End' + ].find((value) => value === event.key) + ) { + event.preventDefault() + } + } + useImperativeHandle( ref, () => { @@ -143,11 +183,24 @@ const HideScrollbar = forwardRef((props }, 1000) window.addEventListener('resize', windowResizeListener()) + if (isPreventScroll) { + rootRef.current?.addEventListener('wheel', handleDefaultWheel, { passive: false }) + rootRef.current?.addEventListener('touchmove', handleDefaultTouchmove, { + passive: false + }) + rootRef.current?.addEventListener('mousedown', handleDefaultClickMiddleMouseButton) + rootRef.current?.addEventListener('keydown', handleDefaultKeyDown) + } else { + rootRef.current?.removeEventListener('wheel', handleDefaultWheel) + rootRef.current?.removeEventListener('touchmove', handleDefaultTouchmove) + rootRef.current?.removeEventListener('mousedown', handleDefaultClickMiddleMouseButton) + rootRef.current?.removeEventListener('keydown', handleDefaultKeyDown) + } return () => { window.removeEventListener('resize', windowResizeListener) } - }, []) + }, [isPreventScroll]) return ( <> @@ -155,10 +208,12 @@ const HideScrollbar = forwardRef((props
{props.children}
diff --git a/src/components/Home.tsx b/src/components/Home.tsx index 5d967de..afde976 100644 --- a/src/components/Home.tsx +++ b/src/components/Home.tsx @@ -8,10 +8,10 @@ import { MainFrameworkContext } from '@/pages/MainFramework.tsx' const Home: React.FC = () => { const { hideScrollbarRef, - navbarHiddenState: { navbarHidden, setNavbarHidden } + navbarHiddenState: { setNavbarHidden }, + preventScrollState: { setPreventScroll } } = useContext(MainFrameworkContext) const fitFullScreenRef = useRef(null) - const pathname = useLocation().pathname const [slogan, setSlogan] = useState('') const [sloganType, setSloganType] = useState(true) @@ -35,59 +35,55 @@ const Home: React.FC = () => { }, 50) } - const hideScrollbarDOM = hideScrollbarRef.current - const scrollListener = useCallback(() => { - if ( - hideScrollbarDOM && - fitFullScreenRef.current && - hideScrollbarDOM.getY() < fitFullScreenRef.current?.offsetHeight - ) { - if (!navbarHidden) { - setNavbarHidden(true) - } - } else { - if (navbarHidden) { - setNavbarHidden(false) - } - } - }, [hideScrollbarDOM, navbarHidden, setNavbarHidden]) - useEffect(() => { - hideScrollbarDOM?.removeEventListener('scroll', scrollListener) - hideScrollbarDOM?.addEventListener('scroll', scrollListener) - return () => { - hideScrollbarDOM?.removeEventListener('scroll', scrollListener) - } - }, [hideScrollbarDOM, scrollListener]) + setTimeout(() => { + setNavbarHidden(true) + setPreventScroll(true) + }) + }, [setNavbarHidden, setPreventScroll]) - useEffect(() => { - scrollListener() - }, [pathname, scrollListener]) - - const handleScrollDown = () => { + const handleScrollToDown = () => { hideScrollbarRef.current?.scrollY(fitFullScreenRef.current?.offsetHeight ?? 0) + setNavbarHidden(false) + } + + const handleScrollToTop = () => { + hideScrollbarRef.current?.scrollY(0) + setNavbarHidden(true) + } + + const handleWheel = (event: React.WheelEvent) => { + if (event.deltaY > 0) { + handleScrollToDown() + setNavbarHidden(false) + } else { + handleScrollToTop() + setNavbarHidden(true) + } } return ( <> - - -
-
FatWeb
- - {slogan || <> } - -
-
- -
-
-
- - +
+ + +
+
FatWeb
+ + {slogan || <> } + +
+
+ +
+
+
+ + +
) } diff --git a/src/pages/MainFramework.tsx b/src/pages/MainFramework.tsx index 23ff379..54e77b8 100644 --- a/src/pages/MainFramework.tsx +++ b/src/pages/MainFramework.tsx @@ -9,30 +9,41 @@ export const MainFrameworkContext = createContext<{ navbarHidden: boolean setNavbarHidden: (newValue: boolean) => void } - hideScrollbarRef: RefObject + preventScrollState: { + preventScroll: boolean + setPreventScroll: (newValue: boolean) => void + } + hideScrollbarRef: React.RefObject }>({ navbarHiddenState: { navbarHidden: false, setNavbarHidden: () => undefined }, - hideScrollbarRef: createRef() + hideScrollbarRef: createRef(), + preventScrollState: { + preventScroll: false, + setPreventScroll: () => undefined + } }) const MainFramework: React.FC = () => { - const [navbarHidden, setNavbarHidden] = useState(true) - - const hideScrollbarRef = useRef(null) const routeId = useMatches()[1].id const routeChildren = router.routes[0].children?.find((value) => value.id === routeId)?.children const pathname = useLocation().pathname + + const hideScrollbarRef = useRef(null) + + const [navbarHidden, setNavbarHidden] = useState(true) + const [preventScroll, setPreventScroll] = useState(false) + useEffect(() => { setNavbarHidden(false) }, [pathname]) return ( <> - +