UNPKG

react-native-tab-view

Version:
216 lines (215 loc) 6.35 kB
"use strict"; import * as React from 'react'; import { Animated, Platform, StyleSheet, View } from 'react-native'; import useLatestCallback from 'use-latest-callback'; import { PlatformPressable } from "./PlatformPressable.js"; import { TabBarItemLabel } from "./TabBarItemLabel.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const DEFAULT_ACTIVE_COLOR = 'rgba(255, 255, 255, 1)'; const DEFAULT_INACTIVE_COLOR = 'rgba(255, 255, 255, 0.7)'; const ICON_SIZE = 24; const getActiveOpacity = (position, routesLength, tabIndex) => { if (routesLength > 1) { const inputRange = Array.from({ length: routesLength }, (_, i) => i); return position.interpolate({ inputRange, outputRange: inputRange.map(i => i === tabIndex ? 1 : 0) }); } else { return 1; } }; const getInactiveOpacity = (position, routesLength, tabIndex) => { if (routesLength > 1) { const inputRange = Array.from({ length: routesLength }, (_, i) => i); return position.interpolate({ inputRange, outputRange: inputRange.map(i => i === tabIndex ? 0 : 1) }); } else { return 0; } }; const ANDROID_RIPPLE_DEFAULT = { borderless: true }; const TabBarItemInternal = ({ accessibilityLabel, accessible, label: customlabel, testID, onLongPress, onPress, isFocused, position, style, inactiveColor: inactiveColorCustom, activeColor: activeColorCustom, labelStyle, onLayout, index: tabIndex, pressColor, pressOpacity, defaultTabWidth, icon: customIcon, badge: customBadge, href, labelText, routesLength, android_ripple = ANDROID_RIPPLE_DEFAULT, labelAllowFontScaling, route }) => { const labelColorFromStyle = StyleSheet.flatten(labelStyle || {}).color; const activeColor = activeColorCustom !== undefined ? activeColorCustom : typeof labelColorFromStyle === 'string' ? labelColorFromStyle : DEFAULT_ACTIVE_COLOR; const inactiveColor = inactiveColorCustom !== undefined ? inactiveColorCustom : typeof labelColorFromStyle === 'string' ? labelColorFromStyle : DEFAULT_INACTIVE_COLOR; const activeOpacity = getActiveOpacity(position, routesLength, tabIndex); const inactiveOpacity = getInactiveOpacity(position, routesLength, tabIndex); const icon = React.useMemo(() => { if (!customIcon) { return null; } const inactiveIcon = customIcon({ focused: false, color: inactiveColor, size: ICON_SIZE, route }); const activeIcon = customIcon({ focused: true, color: activeColor, size: ICON_SIZE, route }); return /*#__PURE__*/_jsxs(View, { style: styles.icon, children: [/*#__PURE__*/_jsx(Animated.View, { style: { opacity: inactiveOpacity }, children: inactiveIcon }), /*#__PURE__*/_jsx(Animated.View, { style: [StyleSheet.absoluteFill, { opacity: activeOpacity }], children: activeIcon })] }); }, [activeColor, activeOpacity, customIcon, inactiveColor, inactiveOpacity, route]); const renderLabel = React.useCallback(focused => customlabel ? customlabel({ focused, color: focused ? activeColor : inactiveColor, style: labelStyle, labelText, allowFontScaling: labelAllowFontScaling, route }) : /*#__PURE__*/_jsx(TabBarItemLabel, { color: focused ? activeColor : inactiveColor, icon: icon, label: labelText, style: labelStyle }), [customlabel, activeColor, labelStyle, labelText, labelAllowFontScaling, route, inactiveColor, icon]); const tabStyle = StyleSheet.flatten(style); const isWidthSet = tabStyle?.width !== undefined; const tabContainerStyle = isWidthSet ? null : { width: defaultTabWidth }; const ariaLabel = typeof accessibilityLabel !== 'undefined' ? accessibilityLabel : labelText; return /*#__PURE__*/_jsx(PlatformPressable, { android_ripple: android_ripple, testID: testID, accessible: accessible, role: "tab", "aria-label": ariaLabel, "aria-selected": isFocused, pressColor: pressColor, pressOpacity: pressOpacity, unstable_pressDelay: 0, onLayout: onLayout, onPress: onPress, onLongPress: onLongPress, href: href, style: [styles.pressable, tabContainerStyle], children: /*#__PURE__*/_jsxs(View, { pointerEvents: "none", style: [styles.item, tabStyle], children: [icon, /*#__PURE__*/_jsxs(View, { children: [/*#__PURE__*/_jsx(Animated.View, { style: { opacity: inactiveOpacity }, children: renderLabel(false) }), /*#__PURE__*/_jsx(Animated.View, { style: [StyleSheet.absoluteFill, { opacity: activeOpacity }], children: renderLabel(true) })] }), customBadge != null ? /*#__PURE__*/_jsx(View, { style: styles.badge, children: customBadge({ route }) }) : null] }) }); }; const MemoizedTabBarItemInternal = /*#__PURE__*/React.memo(TabBarItemInternal); export function TabBarItem(props) { const { onPress, onLongPress, onLayout, navigationState, route, ...rest } = props; const onPressLatest = useLatestCallback(onPress); const onLongPressLatest = useLatestCallback(onLongPress); const onLayoutLatest = useLatestCallback(onLayout ? onLayout : () => {}); const tabIndex = navigationState.routes.indexOf(route); return /*#__PURE__*/_jsx(MemoizedTabBarItemInternal, { ...rest, onPress: onPressLatest, onLayout: onLayoutLatest, onLongPress: onLongPressLatest, isFocused: navigationState.index === tabIndex, route: route, index: tabIndex, routesLength: navigationState.routes.length }); } const styles = StyleSheet.create({ icon: { margin: 2 }, item: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 10, minHeight: 48 }, badge: { position: 'absolute', top: 0, end: 0 }, pressable: { // The label is not pressable on Windows // Adding backgroundColor: 'transparent' seems to fix it backgroundColor: 'transparent', ...Platform.select({ // Roundness for iPad hover effect ios: { borderRadius: 10 }, default: null }) } }); //# sourceMappingURL=TabBarItem.js.map