diff options
Diffstat (limited to 'src/view/com/util')
-rw-r--r-- | src/view/com/util/TabBar.tsx | 161 | ||||
-rw-r--r-- | src/view/com/util/pager/Pager.tsx | 87 | ||||
-rw-r--r-- | src/view/com/util/pager/Pager.web.tsx | 69 |
3 files changed, 0 insertions, 317 deletions
diff --git a/src/view/com/util/TabBar.tsx b/src/view/com/util/TabBar.tsx deleted file mode 100644 index 545a6b742..000000000 --- a/src/view/com/util/TabBar.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import React, {createRef, useState, useMemo} from 'react' -import { - Animated, - StyleSheet, - TouchableWithoutFeedback, - View, -} from 'react-native' -import {Text} from './text/Text' -import {usePalette} from 'lib/hooks/usePalette' -import {isDesktopWeb} from 'platform/detection' - -interface Layout { - x: number - width: number -} - -export interface TabBarProps { - selectedPage: number - items: string[] - position: Animated.Value - offset: Animated.Value - indicatorPosition?: 'top' | 'bottom' - indicatorColor?: string - onSelect?: (index: number) => void - onPressSelected?: () => void -} - -export function TabBar({ - selectedPage, - items, - position, - offset, - indicatorPosition = 'bottom', - indicatorColor, - onSelect, - onPressSelected, -}: TabBarProps) { - const pal = usePalette('default') - const [itemLayouts, setItemLayouts] = useState<Layout[]>( - items.map(() => ({x: 0, width: 0})), - ) - const itemRefs = useMemo( - () => Array.from({length: items.length}).map(() => createRef<View>()), - [items.length], - ) - const panX = Animated.add(position, offset) - - const indicatorStyle = { - backgroundColor: indicatorColor || pal.colors.link, - bottom: - indicatorPosition === 'bottom' ? (isDesktopWeb ? 0 : -1) : undefined, - top: indicatorPosition === 'top' ? (isDesktopWeb ? 0 : -1) : undefined, - transform: [ - { - translateX: panX.interpolate({ - inputRange: items.map((_item, i) => i), - outputRange: itemLayouts.map(l => l.x + l.width / 2), - }), - }, - { - scaleX: panX.interpolate({ - inputRange: items.map((_item, i) => i), - outputRange: itemLayouts.map(l => l.width), - }), - }, - ], - } - - const onLayout = () => { - const promises = [] - for (let i = 0; i < items.length; i++) { - promises.push( - new Promise<Layout>(resolve => { - itemRefs[i].current?.measure( - (x: number, _y: number, width: number) => { - resolve({x, width}) - }, - ) - }), - ) - } - Promise.all(promises).then((layouts: Layout[]) => { - setItemLayouts(layouts) - }) - } - - const onPressItem = (index: number) => { - onSelect?.(index) - if (index === selectedPage) { - onPressSelected?.() - } - } - - return ( - <View style={[pal.view, styles.outer]} onLayout={onLayout}> - <Animated.View style={[styles.indicator, indicatorStyle]} /> - {items.map((item, i) => { - const selected = i === selectedPage - return ( - <TouchableWithoutFeedback key={i} onPress={() => onPressItem(i)}> - <View - style={ - indicatorPosition === 'top' ? styles.itemTop : styles.itemBottom - } - ref={itemRefs[i]}> - <Text type="xl-bold" style={selected ? pal.text : pal.textLight}> - {item} - </Text> - </View> - </TouchableWithoutFeedback> - ) - })} - </View> - ) -} - -const styles = isDesktopWeb - ? StyleSheet.create({ - outer: { - flexDirection: 'row', - paddingHorizontal: 18, - }, - itemTop: { - paddingTop: 16, - paddingBottom: 14, - marginRight: 24, - }, - itemBottom: { - paddingTop: 14, - paddingBottom: 16, - marginRight: 24, - }, - indicator: { - position: 'absolute', - left: 0, - width: 1, - height: 3, - }, - }) - : StyleSheet.create({ - outer: { - flexDirection: 'row', - paddingHorizontal: 14, - }, - itemTop: { - paddingTop: 10, - paddingBottom: 10, - marginRight: 24, - }, - itemBottom: { - paddingTop: 8, - paddingBottom: 12, - marginRight: 24, - }, - indicator: { - position: 'absolute', - left: 0, - width: 1, - height: 3, - }, - }) diff --git a/src/view/com/util/pager/Pager.tsx b/src/view/com/util/pager/Pager.tsx deleted file mode 100644 index 416828a27..000000000 --- a/src/view/com/util/pager/Pager.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react' -import {Animated, View} from 'react-native' -import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' -import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' -import {s} from 'lib/styles' - -export type PageSelectedEvent = PagerViewOnPageSelectedEvent -const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) - -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(0) - const position = useAnimatedValue(0) - const offset = useAnimatedValue(0) - const pagerView = React.useRef<PagerView>() - - const onPageSelectedInner = React.useCallback( - (e: PageSelectedEvent) => { - setSelectedPage(e.nativeEvent.position) - onPageSelected?.(e.nativeEvent.position) - }, - [setSelectedPage, onPageSelected], - ) - - const onTabBarSelect = React.useCallback( - (index: number) => { - pagerView.current?.setPage(index) - }, - [pagerView], - ) - - return ( - <View> - {tabBarPosition === 'top' && - renderTabBar({ - selectedPage, - position, - offset, - onSelect: onTabBarSelect, - })} - <AnimatedPagerView - ref={pagerView} - style={s.h100pct} - initialPage={initialPage} - onPageSelected={onPageSelectedInner} - onPageScroll={Animated.event( - [ - { - nativeEvent: { - position: position, - offset: offset, - }, - }, - ], - {useNativeDriver: true}, - )}> - {children} - </AnimatedPagerView> - {tabBarPosition === 'bottom' && - renderTabBar({ - selectedPage, - position, - offset, - onSelect: onTabBarSelect, - })} - </View> - ) -} diff --git a/src/view/com/util/pager/Pager.web.tsx b/src/view/com/util/pager/Pager.web.tsx deleted file mode 100644 index 3c2805833..000000000 --- a/src/view/com/util/pager/Pager.web.tsx +++ /dev/null @@ -1,69 +0,0 @@ -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} - key={`page-${i}`}> - {child} - </View> - ))} - {tabBarPosition === 'bottom' && - renderTabBar({ - selectedPage, - position, - offset, - onSelect: onTabBarSelect, - })} - </View> - ) -} |