11import React , { forwardRef , useImperativeHandle , useMemo , useRef } from 'react'
22import clsx from 'clsx'
3- import { createNamespace , preventDefault } from '../utils'
3+ import {
4+ createNamespace ,
5+ getScrollTop ,
6+ getVisibleHeight ,
7+ preventDefault ,
8+ } from '../utils'
49import useEventListener from '../hooks/use-event-listener'
510import { useTouch } from '../hooks'
611import { FloatingPanelInstance , FloatingPanelProps } from './PropsType'
@@ -9,6 +14,12 @@ import { bound } from '../utils/bound'
914
1015const [ bem ] = createNamespace ( 'floating-panel' )
1116
17+ /** Check if EL is scrolling reach its bottom */
18+ function scrollReachBottom ( el : Element ) {
19+ const scrollTop = getScrollTop ( el )
20+ return scrollTop >= el . scrollHeight - getVisibleHeight ( el )
21+ }
22+
1223const FloatingPanel = forwardRef < FloatingPanelInstance , FloatingPanelProps > (
1324 ( props , ref ) => {
1425 const { className, style, onHeightChange, anchors = [ 100 ] } = props
@@ -44,24 +55,22 @@ const FloatingPanel = forwardRef<FloatingPanelInstance, FloatingPanelProps>(
4455 }
4556
4657 const onTouchMove : EventListener = event => {
47- if ( ! body . current || ! header . current ) return
58+ const [ headerEL , bodyEL ] = [ header . current , body . current ]
4859 touch . move ( event )
49- if ( touch . firstMove . current && touch . isVertical ( ) ) {
50- const bodyEL = body . current
60+ if ( visibleH . goal >= maxAnchor && bodyEL ) {
5161 if (
52- // attempt scroll at max anchor
53- ( touch . deltaY . current < 0 &&
54- visibleH . goal >= maxAnchor &&
55- bodyEL . offsetHeight < bodyEL . scrollHeight &&
56- ! ( bodyEL . scrollTop + bodyEL . offsetHeight >= bodyEL . scrollHeight ) ) ||
57- // attempt scroll back to top at max anchor
58- ( touch . deltaY . current > 0 && bodyEL . scrollTop > 0 )
62+ touch . firstMove . current &&
63+ // try going up to body top
64+ ( ( touch . deltaY . current > 0 && getScrollTop ( bodyEL ) > 0 ) ||
65+ // try going down to body bottom
66+ ( touch . deltaY . current < 0 && ! scrollReachBottom ( bodyEL ) ) )
5967 ) {
6068 dragging . current = false
61- return
6269 }
6370 }
64- if ( event . target === header . current ) dragging . current = true
71+ if ( headerEL && headerEL . contains ( event . target as Element ) ) {
72+ dragging . current = true
73+ }
6574 if ( ! dragging . current ) return
6675 preventDefault ( event , true )
6776 api . start ( {
@@ -87,9 +96,12 @@ const FloatingPanel = forwardRef<FloatingPanelInstance, FloatingPanelProps>(
8796 }
8897 }
8998
90- useEventListener ( 'touchstart' , onTouchStart , { target : root } )
91- useEventListener ( 'touchmove' , onTouchMove , { target : root } )
92- useEventListener ( 'touchend' , onTouchEnd , { target : root } )
99+ useEventListener ( 'touchstart' , onTouchStart , {
100+ target : root ,
101+ passive : false ,
102+ } )
103+ useEventListener ( 'touchmove' , onTouchMove , { target : root , passive : false } )
104+ useEventListener ( 'touchend' , onTouchEnd , { target : root , passive : false } )
93105
94106 return (
95107 < animated . div
0 commit comments