bsky-app/src/view/com/util/pager/Pager.web.tsx
2023-03-19 18:11:33 -05:00

65 lines
1.6 KiB
TypeScript

import React from 'react'
import {Animated, View} from 'react-native'
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
import {s} from 'lib/styles'
export interface RenderTabBarFnProps {
selectedPage: number
position: Animated.Value
offset: Animated.Value
onSelect?: (index: number) => void
}
export type RenderTabBarFn = (props: RenderTabBarFnProps) => JSX.Element
interface Props {
tabBarPosition?: 'top' | 'bottom'
initialPage?: number
renderTabBar: RenderTabBarFn
onPageSelected?: (index: number) => void
}
export const Pager = ({
children,
tabBarPosition = 'top',
initialPage = 0,
renderTabBar,
onPageSelected,
}: React.PropsWithChildren<Props>) => {
const [selectedPage, setSelectedPage] = React.useState(initialPage)
const position = useAnimatedValue(0)
const offset = useAnimatedValue(0)
const onTabBarSelect = React.useCallback(
(index: number) => {
setSelectedPage(index)
onPageSelected?.(index)
Animated.timing(position, {
toValue: index,
duration: 200,
useNativeDriver: true,
}).start()
},
[setSelectedPage, onPageSelected, position],
)
return (
<View>
{tabBarPosition === 'top' &&
renderTabBar({
selectedPage,
position,
offset,
onSelect: onTabBarSelect,
})}
{children.map((child, i) => (
<View style={selectedPage === i ? undefined : s.hidden}>{child}</View>
))}
{tabBarPosition === 'bottom' &&
renderTabBar({
selectedPage,
position,
offset,
onSelect: onTabBarSelect,
})}
</View>
)
}