mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-11 18:55:26 +00:00
Merge pull request #7831 from overleaf/ii-scroll-to-position
Add scroll to position custom hook GitOrigin-RevId: e2202e390ad674e31b61eb0f0ff6bda9346b34b8
This commit is contained in:
parent
c807bedb65
commit
f7977cdca5
2 changed files with 113 additions and 0 deletions
|
@ -14,10 +14,12 @@ import * as eventTracking from '../../../infrastructure/event-tracking'
|
|||
import { UserProvider } from '../../../shared/context/user-context'
|
||||
import { SSOProvider } from '../context/sso-context'
|
||||
import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
|
||||
import useScrollToIdOnLoad from '../../../shared/hooks/use-scroll-to-id-on-load'
|
||||
import { ExposedSettings } from '../../../../../types/exposed-settings'
|
||||
|
||||
function SettingsPageRoot() {
|
||||
const { isReady } = useWaitForI18n()
|
||||
useScrollToIdOnLoad()
|
||||
|
||||
useEffect(() => {
|
||||
eventTracking.sendMB('settings-view')
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
import { useEffect, useState, useRef } from 'react'
|
||||
|
||||
const DEFAULT_TIMEOUT = 3000
|
||||
const hash = window.location.hash.substring(1)
|
||||
const events = <const>['keydown', 'touchmove', 'wheel']
|
||||
|
||||
const isKeyboardEvent = (event: Event): event is KeyboardEvent => {
|
||||
return event.constructor.name === 'KeyboardEvent'
|
||||
}
|
||||
|
||||
type UseScrollToIdOnLoadProps = {
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
function UseScrollToIdOnLoad({
|
||||
timeout = DEFAULT_TIMEOUT,
|
||||
}: UseScrollToIdOnLoadProps = {}) {
|
||||
const [offsetTop, setOffsetTop] = useState<number | null>(null)
|
||||
const requestRef = useRef<number | null>(null)
|
||||
const targetRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
const cancelAnimationFrame = () => {
|
||||
if (requestRef.current) {
|
||||
window.cancelAnimationFrame(requestRef.current)
|
||||
}
|
||||
}
|
||||
|
||||
const cancelEventListeners = () => {
|
||||
events.forEach(eventType => {
|
||||
window.removeEventListener(eventType, eventListenersCallbackRef.current)
|
||||
})
|
||||
}
|
||||
|
||||
const eventListenersCallback = (
|
||||
event: KeyboardEvent | TouchEvent | WheelEvent
|
||||
) => {
|
||||
const keys = new Set(['ArrowUp', 'ArrowDown', 'PageUp', 'PageDown'])
|
||||
|
||||
if (!isKeyboardEvent(event) || keys.has(event.key)) {
|
||||
// Remove scroll checks
|
||||
cancelAnimationFrame()
|
||||
// Remove event listeners
|
||||
cancelEventListeners()
|
||||
}
|
||||
}
|
||||
|
||||
const eventListenersCallbackRef = useRef(eventListenersCallback)
|
||||
|
||||
// Scroll to the target
|
||||
useEffect(() => {
|
||||
if (!offsetTop) {
|
||||
return
|
||||
}
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetTop,
|
||||
})
|
||||
}, [offsetTop])
|
||||
|
||||
// Bail out from scrolling automatically in `${timeout}` milliseconds
|
||||
useEffect(() => {
|
||||
if (!hash) {
|
||||
return
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
cancelAnimationFrame()
|
||||
cancelEventListeners()
|
||||
}, timeout)
|
||||
}, [timeout])
|
||||
|
||||
// Scroll to target by recursively looking for the target element
|
||||
useEffect(() => {
|
||||
if (!hash) {
|
||||
return
|
||||
}
|
||||
|
||||
const offsetTop = () => {
|
||||
if (targetRef.current) {
|
||||
setOffsetTop(targetRef.current.offsetTop)
|
||||
} else {
|
||||
targetRef.current = document.getElementById(hash)
|
||||
}
|
||||
|
||||
requestRef.current = window.requestAnimationFrame(offsetTop)
|
||||
}
|
||||
|
||||
requestRef.current = window.requestAnimationFrame(offsetTop)
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame()
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Set up the event listeners that will cancel the target element lookup
|
||||
useEffect(() => {
|
||||
if (!hash) {
|
||||
return
|
||||
}
|
||||
|
||||
events.forEach(eventType => {
|
||||
window.addEventListener(eventType, eventListenersCallbackRef.current)
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelEventListeners()
|
||||
}
|
||||
}, [])
|
||||
}
|
||||
|
||||
export default UseScrollToIdOnLoad
|
Loading…
Add table
Reference in a new issue