|
@@ -1,8 +1,9 @@
|
|
|
import {
|
|
import {
|
|
|
|
|
+ type ComponentRef,
|
|
|
|
|
+ useEffect,
|
|
|
useState,
|
|
useState,
|
|
|
type FC,
|
|
type FC,
|
|
|
- useRef,
|
|
|
|
|
- useEffect
|
|
|
|
|
|
|
+ useRef
|
|
|
} from "react";
|
|
} from "react";
|
|
|
import {
|
|
import {
|
|
|
type LayoutChangeEvent,
|
|
type LayoutChangeEvent,
|
|
@@ -57,18 +58,6 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
setIsMeasured
|
|
setIsMeasured
|
|
|
] = useState(false);
|
|
] = useState(false);
|
|
|
|
|
|
|
|
- const animatedHeight = useRef(new Animated.Value(
|
|
|
|
|
- (!isAutoHeight && typeof snapPoint === "number") ? snapPoint : 0
|
|
|
|
|
- )).current;
|
|
|
|
|
- const animatedTranslateY = useRef(new Animated.Value(0)).current;
|
|
|
|
|
-
|
|
|
|
|
- const lastTranslateY = useRef(0);
|
|
|
|
|
- const isAtBottom = useRef(false);
|
|
|
|
|
- const lastHeight = useRef(0);
|
|
|
|
|
- const startDy = useRef(0);
|
|
|
|
|
-
|
|
|
|
|
- const scrollOffset = useRef(0);
|
|
|
|
|
-
|
|
|
|
|
let bottomSafeArea = isWrapSafeareaContext ? bottom : 0;
|
|
let bottomSafeArea = isWrapSafeareaContext ? bottom : 0;
|
|
|
let topSafeArea = isWrapSafeareaContext ? top : 0;
|
|
let topSafeArea = isWrapSafeareaContext ? top : 0;
|
|
|
|
|
|
|
@@ -81,21 +70,57 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
topSafeArea = 0;
|
|
topSafeArea = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const maxHeight = windowHeight - topSafeArea;
|
|
|
|
|
|
|
+ const scrollViewRef = useRef<ComponentRef<ScrollView>>(null);
|
|
|
|
|
|
|
|
- let initialHeight: string | number = "auto";
|
|
|
|
|
|
|
+ const animatedTranslateY = useRef(new Animated.Value(0)).current;
|
|
|
|
|
+ const animatedHeight = useRef(new Animated.Value(
|
|
|
|
|
+ isAutoHeight ? 0 : snapPoint ?? 0
|
|
|
|
|
+ )).current;
|
|
|
|
|
+
|
|
|
|
|
+ const maxHeight = useRef(isWorkAsFullScreen ? windowHeight : windowHeight - (isForceFullScreenOnSwipe ? 0 : isWrapSafeareaContext ? topSafeArea : 0));
|
|
|
|
|
+ const heightValue = useRef(isWorkAsFullScreen ? windowHeight : snapPoint ?? 0);
|
|
|
|
|
+ const initialTranslateY = useRef(0);
|
|
|
|
|
+ const translateYValue = useRef(0);
|
|
|
|
|
+ const contentHeight = useRef(-1);
|
|
|
|
|
+ const initialHeight = useRef(0);
|
|
|
|
|
|
|
|
- if(!isAutoHeight && snapPoint) {
|
|
|
|
|
- initialHeight = snapPoint;
|
|
|
|
|
|
|
+ const scrollViewContentHeight = useRef(-1);
|
|
|
|
|
+ const scrollViewLayoutHeight = useRef(-1);
|
|
|
|
|
+ const initialScrollOffset = useRef(0);
|
|
|
|
|
+ const scrollOffset = useRef(0);
|
|
|
|
|
|
|
|
- if(initialHeight > maxHeight) initialHeight = maxHeight;
|
|
|
|
|
|
|
+ if(!isWorkAsFullScreen && !isCanFullScreenOnSwipe && snapPoint) {
|
|
|
|
|
+ maxHeight.current = snapPoint;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
- if (!isAutoHeight && typeof initialHeight === "number") {
|
|
|
|
|
- animatedHeight.setValue(initialHeight);
|
|
|
|
|
|
|
+ if(isMeasured && contentHeight.current !== -1) {
|
|
|
|
|
+ if(isCanFullScreenOnSwipe && !isWorkAsFullScreen) {
|
|
|
|
|
+ maxHeight.current = windowHeight - (isForceFullScreenOnSwipe ? 0 : topSafeArea);
|
|
|
|
|
+ } else if(isAutoHeight || !snapPoint) {
|
|
|
|
|
+ maxHeight.current = contentHeight.current;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }, [initialHeight]);
|
|
|
|
|
|
|
+ }, [isMeasured]);
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const listenerAHeightId = animatedHeight.addListener(({
|
|
|
|
|
+ value
|
|
|
|
|
+ }) => {
|
|
|
|
|
+ heightValue.current = value;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const listenerTYId = animatedTranslateY.addListener(({
|
|
|
|
|
+ value
|
|
|
|
|
+ }) => {
|
|
|
|
|
+ translateYValue.current = value;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ animatedHeight.removeListener(listenerAHeightId);
|
|
|
|
|
+ animatedTranslateY.removeListener(listenerTYId);
|
|
|
|
|
+ };
|
|
|
|
|
+ }, []);
|
|
|
|
|
|
|
|
const onLayout = (event: LayoutChangeEvent) => {
|
|
const onLayout = (event: LayoutChangeEvent) => {
|
|
|
if (isMeasured) return;
|
|
if (isMeasured) return;
|
|
@@ -104,177 +129,204 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
height
|
|
height
|
|
|
} = event.nativeEvent.layout;
|
|
} = event.nativeEvent.layout;
|
|
|
|
|
|
|
|
- let _height = height;
|
|
|
|
|
-
|
|
|
|
|
- if(height > maxHeight) _height = maxHeight;
|
|
|
|
|
-
|
|
|
|
|
- animatedHeight.setValue(_height);
|
|
|
|
|
|
|
+ animatedHeight.setValue(height);
|
|
|
|
|
+ contentHeight.current = height;
|
|
|
setIsMeasured(true);
|
|
setIsMeasured(true);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const snapTo = (targetHeight: number, targetTranslateY: number) => {
|
|
|
|
|
- Animated.parallel([
|
|
|
|
|
- Animated.spring(animatedHeight, {
|
|
|
|
|
- useNativeDriver: true,
|
|
|
|
|
- toValue: targetHeight,
|
|
|
|
|
- tension: 50,
|
|
|
|
|
- friction: 8
|
|
|
|
|
- }),
|
|
|
|
|
- Animated.spring(animatedTranslateY, {
|
|
|
|
|
- toValue: targetTranslateY,
|
|
|
|
|
- useNativeDriver: true,
|
|
|
|
|
- tension: 50,
|
|
|
|
|
- friction: 8
|
|
|
|
|
- })
|
|
|
|
|
- ]).start();
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
const panResponder = useRef(
|
|
const panResponder = useRef(
|
|
|
PanResponder.create({
|
|
PanResponder.create({
|
|
|
onStartShouldSetPanResponder: () => false,
|
|
onStartShouldSetPanResponder: () => false,
|
|
|
- onMoveShouldSetPanResponder: (evt, gestureState) => {
|
|
|
|
|
|
|
+ onMoveShouldSetPanResponderCapture: () => true,
|
|
|
|
|
+ onPanResponderGrant: () => {
|
|
|
|
|
+ initialTranslateY.current = translateYValue.current;
|
|
|
|
|
+ initialScrollOffset.current = scrollOffset.current;
|
|
|
|
|
+ initialHeight.current = heightValue.current;
|
|
|
|
|
+
|
|
|
|
|
+ animatedHeight.setOffset(heightValue.current);
|
|
|
|
|
+ animatedHeight.setValue(0);
|
|
|
|
|
+
|
|
|
|
|
+ animatedTranslateY.setOffset(translateYValue.current);
|
|
|
|
|
+ animatedTranslateY.setValue(0);
|
|
|
|
|
+ },
|
|
|
|
|
+ onPanResponderMove: (_, gestureState) => {
|
|
|
const {
|
|
const {
|
|
|
- dy,
|
|
|
|
|
- dx
|
|
|
|
|
|
|
+ dy
|
|
|
} = gestureState;
|
|
} = gestureState;
|
|
|
- // @ts-ignore
|
|
|
|
|
- const currentH = animatedHeight._value;
|
|
|
|
|
- const isAtMax = currentH >= maxHeight - 5;
|
|
|
|
|
|
|
|
|
|
- // Yatay kaydırmayı engelle (içeride slider varsa çakışmasın)
|
|
|
|
|
- if (Math.abs(dx) > Math.abs(dy)) return false;
|
|
|
|
|
|
|
+ const delta = -dy;
|
|
|
|
|
|
|
|
- // DURUM 1: Aşağı çekiyoruz (dy > 0)
|
|
|
|
|
- if (dy > 0) {
|
|
|
|
|
- // Scroll en tepedeyse kontrolü PanResponder alır
|
|
|
|
|
- if (scrollOffset.current <= 0) return true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const pivot = snapPoint ?? contentHeight.current;
|
|
|
|
|
+
|
|
|
|
|
+ const initialH = initialHeight.current;
|
|
|
|
|
+ const initialS = initialScrollOffset.current;
|
|
|
|
|
+ const initialT = initialTranslateY.current;
|
|
|
|
|
+
|
|
|
|
|
+ const maxS = Math.max(0, scrollViewContentHeight.current - scrollViewLayoutHeight.current);
|
|
|
|
|
|
|
|
- // DURUM 2: Yukarı çekiyoruz (dy < 0)
|
|
|
|
|
if (dy < 0) {
|
|
if (dy < 0) {
|
|
|
- // Sayfa tam açık değilse VEYA scroll en sona dayandıysa kontrolü al
|
|
|
|
|
- // (isCanFullScreenOnSwipe false olsa bile snapPoint'e kadar çekebilmeli)
|
|
|
|
|
- if (!isAtMax || isAtBottom.current) return true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ let currentDelta = delta;
|
|
|
|
|
|
|
|
- return false;
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ if (initialT > 0) {
|
|
|
|
|
+ const usedForT = Math.min(currentDelta, initialT);
|
|
|
|
|
|
|
|
- onPanResponderGrant: (evt, gestureState) => {
|
|
|
|
|
- startDy.current = gestureState.dy;
|
|
|
|
|
- // @ts-ignore
|
|
|
|
|
- lastHeight.current = animatedHeight._value;
|
|
|
|
|
- // @ts-ignore
|
|
|
|
|
- lastTranslateY.current = animatedTranslateY._value;
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ animatedTranslateY.setValue(-usedForT);
|
|
|
|
|
|
|
|
- onPanResponderMove: (evt, gestureState) => {
|
|
|
|
|
- const correctedDy = gestureState.dy - startDy.current;
|
|
|
|
|
- const currentSnap = typeof snapPoint === "number" ? snapPoint : lastHeight.current;
|
|
|
|
|
|
|
+ currentDelta -= usedForT;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (correctedDy < 0) { // YUKARI HAREKET
|
|
|
|
|
- if (lastTranslateY.current > 0) {
|
|
|
|
|
- // Sayfa aşağı kaymışsa önce translateY'i sıfırla
|
|
|
|
|
- const nextY = Math.max(0, lastTranslateY.current + correctedDy);
|
|
|
|
|
- animatedTranslateY.setValue(nextY);
|
|
|
|
|
- } else {
|
|
|
|
|
- // ÜST LİMİT KONTROLÜ: Tam ekran izni yoksa snapPoint/lastHeight'ta kilitle
|
|
|
|
|
- // Not: isCanFullScreenOnSwipe prop'unu buradan kontrol ediyoruz
|
|
|
|
|
- const upperLimit = isCanFullScreenOnSwipe ? maxHeight : currentSnap;
|
|
|
|
|
|
|
+ if (currentDelta > 0) {
|
|
|
|
|
+ if (initialH < pivot) {
|
|
|
|
|
+ const spaceToPivot = pivot - initialH;
|
|
|
|
|
+ const usedForH = Math.min(currentDelta, spaceToPivot);
|
|
|
|
|
+
|
|
|
|
|
+ animatedHeight.setValue(usedForH);
|
|
|
|
|
+
|
|
|
|
|
+ currentDelta -= usedForH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (currentDelta > 0) {
|
|
|
|
|
+ const remainingScroll = maxS - initialS;
|
|
|
|
|
+ if (remainingScroll > 0) {
|
|
|
|
|
+ const usedForS = Math.min(currentDelta, remainingScroll);
|
|
|
|
|
+ scrollOffset.current = initialS + usedForS;
|
|
|
|
|
+
|
|
|
|
|
+ scrollViewRef.current?.scrollTo({
|
|
|
|
|
+ y: scrollOffset.current,
|
|
|
|
|
+ animated: false
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- const nextH = Math.min(upperLimit, lastHeight.current - correctedDy);
|
|
|
|
|
- animatedHeight.setValue(nextH);
|
|
|
|
|
|
|
+ currentDelta -= usedForS;
|
|
|
|
|
+
|
|
|
|
|
+ animatedHeight.setValue(initialH < pivot ? (pivot - initialH) : 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (currentDelta > 0) {
|
|
|
|
|
+ if (isCanFullScreenOnSwipe) {
|
|
|
|
|
+ const totalUsedBefore = (initialH < pivot ? (pivot - initialH) : 0);
|
|
|
|
|
+
|
|
|
|
|
+ animatedHeight.setValue(totalUsedBefore + currentDelta);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ animatedHeight.setValue(initialH < pivot ? (pivot - initialH) : 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- else { // AŞAĞI HAREKET
|
|
|
|
|
- if (lastHeight.current > currentSnap) {
|
|
|
|
|
- // Boyu snapPoint'e kadar düşür
|
|
|
|
|
- const nextH = Math.max(currentSnap, lastHeight.current - correctedDy);
|
|
|
|
|
- animatedHeight.setValue(nextH);
|
|
|
|
|
- } else {
|
|
|
|
|
- // snapPoint'teyiz, artık komple aşağı kaydır
|
|
|
|
|
- const nextY = lastTranslateY.current + correctedDy;
|
|
|
|
|
- animatedTranslateY.setValue(nextY);
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let currentDelta = delta;
|
|
|
|
|
+
|
|
|
|
|
+ if (initialH > pivot || initialS > 0) {
|
|
|
|
|
+ if (initialS > 0) {
|
|
|
|
|
+ const usedForS = Math.max(currentDelta, -initialS);
|
|
|
|
|
+ scrollOffset.current = initialS + usedForS;
|
|
|
|
|
+
|
|
|
|
|
+ scrollViewRef.current?.scrollTo({
|
|
|
|
|
+ y: scrollOffset.current,
|
|
|
|
|
+ animated: false
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ currentDelta -= usedForS;
|
|
|
|
|
+
|
|
|
|
|
+ animatedHeight.setValue(initialH > pivot ? 0 : pivot - initialH);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (currentDelta < 0 && initialH > pivot) {
|
|
|
|
|
+ const distanceToPivot = pivot - initialH;
|
|
|
|
|
+ const usedForH = Math.max(currentDelta, distanceToPivot);
|
|
|
|
|
+
|
|
|
|
|
+ animatedHeight.setValue(usedForH);
|
|
|
|
|
+
|
|
|
|
|
+ currentDelta -= usedForH;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
|
|
|
|
|
- onPanResponderRelease: (evt, gestureState) => {
|
|
|
|
|
- const {
|
|
|
|
|
- dy,
|
|
|
|
|
- vy
|
|
|
|
|
- } = gestureState;
|
|
|
|
|
- // @ts-ignore
|
|
|
|
|
- const currentH = animatedHeight._value;
|
|
|
|
|
- const currentSnap = typeof snapPoint === "number" ? snapPoint : lastHeight.current;
|
|
|
|
|
-
|
|
|
|
|
- // 1. Karar: Aşağı fırlatma
|
|
|
|
|
- if (vy > 0.5 || dy > 150) {
|
|
|
|
|
- if (currentH > currentSnap + 50) {
|
|
|
|
|
- // Tam ekrandan snapPoint'e düş
|
|
|
|
|
- snapTo(currentSnap, 0);
|
|
|
|
|
- } else {
|
|
|
|
|
- // snapPoint'ten aşağı, yani kapat
|
|
|
|
|
- snapTo(currentSnap, windowHeight);
|
|
|
|
|
|
|
+ if (currentDelta < 0) {
|
|
|
|
|
+ animatedHeight.setValue(initialH > pivot ? (pivot - initialH) : 0);
|
|
|
|
|
+ animatedTranslateY.setValue(-currentDelta);
|
|
|
|
|
+
|
|
|
|
|
+ scrollOffset.current = 0;
|
|
|
|
|
+
|
|
|
|
|
+ scrollViewRef.current?.scrollTo({
|
|
|
|
|
+ y: 0,
|
|
|
|
|
+ animated: false
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- // 2. Karar: Yukarı fırlatma
|
|
|
|
|
- else if (vy < -0.5 || dy < -100) {
|
|
|
|
|
- if (isCanFullScreenOnSwipe) {
|
|
|
|
|
- snapTo(maxHeight, 0);
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ onPanResponderEnd: (_, gestureState) => {
|
|
|
|
|
+ animatedHeight.flattenOffset();
|
|
|
|
|
+ animatedTranslateY.flattenOffset();
|
|
|
|
|
+
|
|
|
|
|
+ const pivot = snapPoint ?? contentHeight.current;
|
|
|
|
|
+ const tavan = maxHeight.current;
|
|
|
|
|
+
|
|
|
|
|
+ const currentH = heightValue.current;
|
|
|
|
|
+ const currentT = translateYValue.current;
|
|
|
|
|
+
|
|
|
|
|
+ const isFastSwipeDown = gestureState.vy > 0.5;
|
|
|
|
|
+ const isFastSwipeUp = gestureState.vy < -0.5;
|
|
|
|
|
+
|
|
|
|
|
+ if (currentT <= 0.5) {
|
|
|
|
|
+ let toValue = pivot;
|
|
|
|
|
+
|
|
|
|
|
+ if (isFastSwipeUp && isCanFullScreenOnSwipe) {
|
|
|
|
|
+ toValue = tavan;
|
|
|
|
|
+ } else if (isFastSwipeDown) {
|
|
|
|
|
+ toValue = pivot;
|
|
|
} else {
|
|
} else {
|
|
|
- snapTo(currentSnap, 0);
|
|
|
|
|
|
|
+ const distToTavan = Math.max(0, tavan - currentH);
|
|
|
|
|
+ const distToPivot = Math.max(0, Math.abs(currentH - pivot));
|
|
|
|
|
+
|
|
|
|
|
+ toValue = (distToTavan < distToPivot && isCanFullScreenOnSwipe) ? tavan : pivot;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- // 3. Karar: Yavaş bırakma (En yakın noktaya mıknatısla)
|
|
|
|
|
- else {
|
|
|
|
|
- // @ts-ignore
|
|
|
|
|
- const currentY = animatedTranslateY._value;
|
|
|
|
|
-
|
|
|
|
|
- if (isCanFullScreenOnSwipe && currentH > (maxHeight + currentSnap) / 2) {
|
|
|
|
|
- snapTo(maxHeight, 0);
|
|
|
|
|
- } else if (currentY > 100) {
|
|
|
|
|
- snapTo(currentSnap, windowHeight); // Çok aşağıda kaldıysa kapat
|
|
|
|
|
|
|
+
|
|
|
|
|
+ Animated.spring(animatedHeight, {
|
|
|
|
|
+ useNativeDriver: false,
|
|
|
|
|
+ toValue: toValue,
|
|
|
|
|
+ friction: 10,
|
|
|
|
|
+ tension: 40
|
|
|
|
|
+ }).start();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let toValueT = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (isFastSwipeDown) {
|
|
|
|
|
+ toValueT = pivot + 100;
|
|
|
} else {
|
|
} else {
|
|
|
- snapTo(currentSnap, 0); // Diğer durumlarda snapPoint/Mevcut boyda kal
|
|
|
|
|
|
|
+ if (currentT > pivot * 0.4) {
|
|
|
|
|
+ toValueT = pivot + 100;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ toValueT = 0;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ Animated.spring(animatedTranslateY, {
|
|
|
|
|
+ useNativeDriver: false,
|
|
|
|
|
+ toValue: toValueT,
|
|
|
|
|
+ friction: 10,
|
|
|
|
|
+ tension: 40
|
|
|
|
|
+ }).start();
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
-
|
|
|
|
|
onPanResponderTerminationRequest: () => false,
|
|
onPanResponderTerminationRequest: () => false,
|
|
|
onShouldBlockNativeResponder: () => true
|
|
onShouldBlockNativeResponder: () => true
|
|
|
}),
|
|
}),
|
|
|
).current;
|
|
).current;
|
|
|
|
|
|
|
|
- const handleScroll = (event: any) => {
|
|
|
|
|
- const {
|
|
|
|
|
- layoutMeasurement,
|
|
|
|
|
- contentOffset,
|
|
|
|
|
- contentSize
|
|
|
|
|
- } = event.nativeEvent;
|
|
|
|
|
- scrollOffset.current = contentOffset.y;
|
|
|
|
|
-
|
|
|
|
|
- const isBottom = layoutMeasurement.height + contentOffset.y >= contentSize.height - 5;
|
|
|
|
|
- isAtBottom.current = isBottom;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
const renderView = () => {
|
|
const renderView = () => {
|
|
|
- const currentHeight = (isAutoHeight && !isMeasured) ? undefined : animatedHeight;
|
|
|
|
|
-
|
|
|
|
|
return <Animated.View
|
|
return <Animated.View
|
|
|
{...props}
|
|
{...props}
|
|
|
{...panResponder.panHandlers}
|
|
{...panResponder.panHandlers}
|
|
|
onLayout={onLayout}
|
|
onLayout={onLayout}
|
|
|
style={[
|
|
style={[
|
|
|
{
|
|
{
|
|
|
|
|
+ height: (isAutoHeight || !snapPoint) && !isMeasured ? "auto" : animatedHeight,
|
|
|
backgroundColor: colors.content.container[backgroundColor],
|
|
backgroundColor: colors.content.container[backgroundColor],
|
|
|
paddingBottom: bottomSafeArea + spaces.spacingMd,
|
|
paddingBottom: bottomSafeArea + spaces.spacingMd,
|
|
|
opacity: isMeasured || !isAutoHeight ? 1 : 0,
|
|
opacity: isMeasured || !isAutoHeight ? 1 : 0,
|
|
|
paddingRight: spaces.spacingMd,
|
|
paddingRight: spaces.spacingMd,
|
|
|
paddingLeft: spaces.spacingMd,
|
|
paddingLeft: spaces.spacingMd,
|
|
|
paddingTop: spaces.spacingMd,
|
|
paddingTop: spaces.spacingMd,
|
|
|
- height: currentHeight,
|
|
|
|
|
- maxHeight: maxHeight,
|
|
|
|
|
|
|
+ maxHeight: maxHeight.current,
|
|
|
transform: [{
|
|
transform: [{
|
|
|
translateY: animatedTranslateY
|
|
translateY: animatedTranslateY
|
|
|
}]
|
|
}]
|
|
@@ -284,13 +336,20 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
]}
|
|
]}
|
|
|
>
|
|
>
|
|
|
<ScrollView
|
|
<ScrollView
|
|
|
|
|
+ onContentSizeChange={(w, h) => {
|
|
|
|
|
+ scrollViewContentHeight.current = h;
|
|
|
|
|
+ }}
|
|
|
|
|
+ onLayout={(e) => {
|
|
|
|
|
+ scrollViewLayoutHeight.current = e.nativeEvent.layout.height;
|
|
|
|
|
+ }}
|
|
|
onStartShouldSetResponderCapture={() => false}
|
|
onStartShouldSetResponderCapture={() => false}
|
|
|
onMoveShouldSetResponderCapture={() => false}
|
|
onMoveShouldSetResponderCapture={() => false}
|
|
|
showsHorizontalScrollIndicator={false}
|
|
showsHorizontalScrollIndicator={false}
|
|
|
showsVerticalScrollIndicator={false}
|
|
showsVerticalScrollIndicator={false}
|
|
|
- scrollEventThrottle={16}
|
|
|
|
|
- onScroll={handleScroll}
|
|
|
|
|
|
|
+ scrollEventThrottle={1}
|
|
|
overScrollMode="never"
|
|
overScrollMode="never"
|
|
|
|
|
+ scrollEnabled={false}
|
|
|
|
|
+ ref={scrollViewRef}
|
|
|
bounces={false}
|
|
bounces={false}
|
|
|
>
|
|
>
|
|
|
{children}
|
|
{children}
|
|
@@ -324,7 +383,9 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
style={[
|
|
style={[
|
|
|
stylesheet.handleContainer,
|
|
stylesheet.handleContainer,
|
|
|
{
|
|
{
|
|
|
- backgroundColor: handleContainerBackgroundColor ? colors.content.container[handleContainerBackgroundColor] : "transparent",
|
|
|
|
|
|
|
+ backgroundColor: handleContainerBackgroundColor
|
|
|
|
|
+ ? colors.content.container[handleContainerBackgroundColor]
|
|
|
|
|
+ : "transparent",
|
|
|
height: handleContainerHeight,
|
|
height: handleContainerHeight,
|
|
|
transform: [{
|
|
transform: [{
|
|
|
translateY: -handleContainerHeight
|
|
translateY: -handleContainerHeight
|
|
@@ -336,7 +397,9 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
style={[
|
|
style={[
|
|
|
stylesheet.handle,
|
|
stylesheet.handle,
|
|
|
{
|
|
{
|
|
|
- backgroundColor: handleBackgroundColor ? colors.content.container[handleBackgroundColor] : colors.content.container.default,
|
|
|
|
|
|
|
+ backgroundColor: handleBackgroundColor
|
|
|
|
|
+ ? colors.content.container[handleBackgroundColor]
|
|
|
|
|
+ : colors.content.container.default,
|
|
|
borderRadius: handleBorderRadius,
|
|
borderRadius: handleBorderRadius,
|
|
|
height: handleHeight
|
|
height: handleHeight
|
|
|
}
|
|
}
|
|
@@ -349,7 +412,6 @@ const BottomSheet: FC<IBottomSheetProps> = ({
|
|
|
isContentRequired={false}
|
|
isContentRequired={false}
|
|
|
isAnimated={false}
|
|
isAnimated={false}
|
|
|
overlayProps={{
|
|
overlayProps={{
|
|
|
- ...panResponder.panHandlers,
|
|
|
|
|
onStartShouldSetResponderCapture: () => false,
|
|
onStartShouldSetResponderCapture: () => false,
|
|
|
onMoveShouldSetResponderCapture: () => false
|
|
onMoveShouldSetResponderCapture: () => false
|
|
|
}}
|
|
}}
|