Integrate dismissal with root lightbox view

This commit is contained in:
Dan Abramov
2024-10-31 00:05:57 +00:00
parent fe7d97b0bf
commit 0be8c55780
+54 -23
View File
@@ -40,6 +40,8 @@ import {ImageSource} from './@types'
import ImageDefaultHeader from './components/ImageDefaultHeader' import ImageDefaultHeader from './components/ImageDefaultHeader'
import ImageItem from './components/ImageItem/ImageItem' import ImageItem from './components/ImageItem/ImageItem'
const SCREEN = Dimensions.get('screen')
type Props = { type Props = {
images: ImageSource[] images: ImageSource[]
thumbDims: MeasuredDimensions | null thumbDims: MeasuredDimensions | null
@@ -52,7 +54,6 @@ type Props = {
} }
const SCREEN_HEIGHT = Dimensions.get('window').height const SCREEN_HEIGHT = Dimensions.get('window').height
const DEFAULT_BG_COLOR = '#000'
function ImageViewing({ function ImageViewing({
images, images,
@@ -60,7 +61,6 @@ function ImageViewing({
initialImageIndex, initialImageIndex,
visible, visible,
onRequestClose, onRequestClose,
backgroundColor = DEFAULT_BG_COLOR,
onPressSave, onPressSave,
onPressShare, onPressShare,
}: Props) { }: Props) {
@@ -70,24 +70,30 @@ function ImageViewing({
const [showControls, setShowControls] = useState(true) const [showControls, setShowControls] = useState(true)
const dismissSwipeTranslateY = useSharedValue(0) const dismissSwipeTranslateY = useSharedValue(0)
const animatedHeaderStyle = useAnimatedStyle(() => ({ const animatedHeaderStyle = useAnimatedStyle(() => {
pointerEvents: showControls ? 'auto' : 'none', const show = showControls && dismissSwipeTranslateY.value === 0
opacity: withClampedSpring(showControls ? 1 : 0), return {
transform: [ pointerEvents: show ? 'auto' : 'none',
{ opacity: withClampedSpring(show ? 1 : 0),
translateY: withClampedSpring(showControls ? 0 : -30), transform: [
}, {
], translateY: withClampedSpring(show ? 0 : -30),
})) },
const animatedFooterStyle = useAnimatedStyle(() => ({ ],
pointerEvents: showControls ? 'auto' : 'none', }
opacity: withClampedSpring(showControls ? 1 : 0), })
transform: [ const animatedFooterStyle = useAnimatedStyle(() => {
{ const show = showControls && dismissSwipeTranslateY.value === 0
translateY: withClampedSpring(showControls ? 0 : 30), return {
}, pointerEvents: show ? 'auto' : 'none',
], opacity: withClampedSpring(show ? 1 : 0),
})) transform: [
{
translateY: withClampedSpring(show ? 0 : 30),
},
],
}
})
const dismissSwipePan = Gesture.Pan() const dismissSwipePan = Gesture.Pan()
.enabled(!isScaled) .enabled(!isScaled)
@@ -130,6 +136,21 @@ function ImageViewing({
return ['left', 'right'] satisfies Edge[] // iOS, so no top/bottom safe area return ['left', 'right'] satisfies Edge[] // iOS, so no top/bottom safe area
}, []) }, [])
const backdropStyle = useAnimatedStyle(() => {
const dismissProgress = Math.min(
Math.abs(dismissSwipeTranslateY.value) / (SCREEN.height / 2),
1,
)
return {
opacity: 1 - dismissProgress,
}
})
const activeImageStyle = useAnimatedStyle(() => {
return {
transform: [{translateY: dismissSwipeTranslateY.value}],
}
})
if (!visible) { if (!visible) {
return null return null
} }
@@ -140,7 +161,8 @@ function ImageViewing({
edges={edges} edges={edges}
aria-modal aria-modal
accessibilityViewIsModal> accessibilityViewIsModal>
<View style={[styles.container, {backgroundColor}]}> <View style={[styles.container]}>
<Animated.View style={[styles.backdrop, backdropStyle]} />
<Animated.View style={[styles.header, animatedHeaderStyle]}> <Animated.View style={[styles.header, animatedHeaderStyle]}>
<ImageDefaultHeader onRequestClose={onRequestClose} /> <ImageDefaultHeader onRequestClose={onRequestClose} />
</Animated.View> </Animated.View>
@@ -157,7 +179,9 @@ function ImageViewing({
overdrag={true} overdrag={true}
style={styles.pager}> style={styles.pager}>
{images.map((imageSrc, i) => ( {images.map((imageSrc, i) => (
<View key={imageSrc.uri}> <Animated.View
key={imageSrc.uri}
style={imageIndex === i ? activeImageStyle : null}>
<ImageItem <ImageItem
onTap={onTap} onTap={onTap}
onZoom={onZoom} onZoom={onZoom}
@@ -169,7 +193,7 @@ function ImageViewing({
imageIndex === i && !isDragging ? dismissSwipePan : null imageIndex === i && !isDragging ? dismissSwipePan : null
} }
/> />
</View> </Animated.View>
))} ))}
</PagerView> </PagerView>
<Animated.View style={[styles.footer, animatedFooterStyle]}> <Animated.View style={[styles.footer, animatedFooterStyle]}>
@@ -276,7 +300,14 @@ const styles = StyleSheet.create({
}, },
container: { container: {
flex: 1, flex: 1,
},
backdrop: {
backgroundColor: '#000', backgroundColor: '#000',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
}, },
pager: { pager: {
flex: 1, flex: 1,