import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined'; import classNames from 'classnames'; import CSSMotion from 'rc-motion'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; import React, { memo, useContext, useEffect, useRef, useState } from 'react'; import FloatButton, { floatButtonPrefixCls } from './FloatButton'; import type { ConfigConsumerProps } from '../config-provider'; import { ConfigContext } from '../config-provider'; import getScroll from '../_util/getScroll'; import scrollTo from '../_util/scrollTo'; import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'; import FloatButtonGroupContext from './context'; import type { BackTopProps, FloatButtonProps, FloatButtonShape } from './interface'; import useStyle from './style'; const BackTop: React.FC = (props) => { const { prefixCls: customizePrefixCls, className = '', type = 'default', shape = 'circle', visibilityHeight = 400, icon = , target, onClick, duration = 450, ...restProps } = props; const [visible, setVisible] = useState(visibilityHeight === 0); const ref = useRef(null); const scrollEvent = useRef | null>(null); const getDefaultTarget = (): HTMLElement | Document | Window => ref.current && ref.current.ownerDocument ? ref.current.ownerDocument : window; const handleScroll = throttleByAnimationFrame( (e: React.UIEvent | { target: any }) => { const scrollTop = getScroll(e.target, true); setVisible(scrollTop >= visibilityHeight); }, ); const bindScrollEvent = () => { const getTarget = target || getDefaultTarget; const container = getTarget(); scrollEvent.current = addEventListener(container, 'scroll', handleScroll); handleScroll({ target: container }); }; useEffect(() => { bindScrollEvent(); return () => { handleScroll.cancel(); scrollEvent.current?.remove(); }; }, [target]); const scrollToTop: React.MouseEventHandler = (e) => { scrollTo(0, { getContainer: target || getDefaultTarget, duration }); onClick?.(e); }; const { getPrefixCls } = useContext(ConfigContext); const prefixCls = getPrefixCls(floatButtonPrefixCls, customizePrefixCls); const rootPrefixCls = getPrefixCls(); const [wrapSSR] = useStyle(prefixCls); const groupShape = useContext(FloatButtonGroupContext); const mergeShape = groupShape || shape; const contentProps: FloatButtonProps = { prefixCls, icon, type, shape: mergeShape, ...restProps }; return wrapSSR( {({ className: motionClassName }) => ( )} , ); }; export default memo(BackTop);