93 lines
2.1 KiB
TypeScript
93 lines
2.1 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import { Dimensions, Pressable, ScrollView, StyleSheet, View } from 'react-native';
|
|
import VideoPlayer from '../video-player/video-player';
|
|
|
|
export type ImageItem = {
|
|
id: string;
|
|
uri: string;
|
|
};
|
|
|
|
export type ImgTabProps = {
|
|
images: ImageItem[];
|
|
activeId: string | null;
|
|
onActiveChange: (id: string) => void;
|
|
imageSize?: number;
|
|
gap?: number;
|
|
};
|
|
|
|
const SCREEN_WIDTH = Dimensions.get('window').width;
|
|
|
|
export function ImgTab({
|
|
images,
|
|
activeId,
|
|
onActiveChange,
|
|
imageSize = 44,
|
|
gap = 12
|
|
}: ImgTabProps) {
|
|
const scrollRef = useRef<ScrollView>(null);
|
|
const activeIndex = images.findIndex(img => img.id === activeId);
|
|
|
|
useEffect(() => {
|
|
if (activeIndex === -1 || !scrollRef.current) return;
|
|
|
|
const offset = activeIndex * (imageSize + gap);
|
|
scrollRef.current.scrollTo({ x: offset, animated: true });
|
|
}, [activeIndex, imageSize, gap]);
|
|
|
|
const paddingHorizontal = (SCREEN_WIDTH - imageSize) / 2;
|
|
|
|
return (
|
|
<ScrollView
|
|
ref={scrollRef}
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={[
|
|
styles.container,
|
|
{ gap, paddingHorizontal }
|
|
]}
|
|
style={styles.scroll}
|
|
>
|
|
{images.map(image => {
|
|
const isActive = image.id === activeId;
|
|
return (
|
|
<Pressable
|
|
key={image.id}
|
|
onPress={() => onActiveChange(image.id)}
|
|
>
|
|
<View style={[
|
|
styles.imageWrapper,
|
|
{ width: imageSize, height: imageSize },
|
|
isActive && styles.activeWrapper
|
|
]}>
|
|
<VideoPlayer source={{ uri: image.uri }} />
|
|
</View>
|
|
</Pressable>
|
|
);
|
|
})}
|
|
</ScrollView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
scroll: {
|
|
flexGrow: 0,
|
|
paddingTop: 4,
|
|
paddingBottom: 4
|
|
},
|
|
container: {
|
|
alignItems: 'center',
|
|
},
|
|
imageWrapper: {
|
|
borderRadius: 6,
|
|
overflow: 'hidden',
|
|
opacity: 0.5,
|
|
transform: [{ scale: 0.7 }],
|
|
},
|
|
activeWrapper: {
|
|
opacity: 1,
|
|
transform: [{ scale: 1.15 }],
|
|
borderWidth: 2,
|
|
borderColor: '#FFFFFF',
|
|
}
|
|
});
|