import { createNavigatorFactory, TabRouter, useNavigationBuilder, type DefaultNavigatorOptions, type NavigationProp, type ParamListBase, type TabActionHelpers, type TabNavigationState, type TabRouterOptions, } from '@react-navigation/native'; import { withLayoutContext } from 'expo-router'; import type { ImageSourcePropType } from 'react-native'; import TabView, { type AppleIcon } from 'react-native-bottom-tabs'; // Pro-Screen Optionen (kompatibel mit Expo Router's Tabs.Screen API) export type NativeTabsScreenOptions = { title?: string; tabBarIcon?: (props: { focused: boolean }) => AppleIcon | ImageSourcePropType; tabBarBadge?: string; // Expo-Router-Konvention: href === null → Screen NICHT in TabBar zeigen href?: string | null; }; type NativeTabNavigationEventMap = { tabPress: { data: undefined; canPreventDefault: true }; tabLongPress: { data: undefined }; }; // Native-spezifische Tab-Layer-Optionen (iOS 26 Glass-Pill, Haptik, etc.) type NativeOnlyOptions = { sidebarAdaptable?: boolean; hapticFeedbackEnabled?: boolean; disablePageAnimations?: boolean; scrollEdgeAppearance?: 'default' | 'opaque' | 'transparent'; minimizeBehavior?: 'automatic' | 'onScrollDown' | 'onScrollUp' | 'never'; tabBarActiveTintColor?: string; tabBarInactiveTintColor?: string; labeled?: boolean; tabLabelStyle?: { fontFamily?: string; fontWeight?: string; fontSize?: number; }; }; type Props = DefaultNavigatorOptions< ParamListBase, string | undefined, TabNavigationState, NativeTabsScreenOptions, NativeTabNavigationEventMap, NavigationProp > & TabRouterOptions & NativeOnlyOptions; function NativeTabsNavigator({ id, initialRouteName, children, screenOptions, layout, sidebarAdaptable = true, hapticFeedbackEnabled = true, disablePageAnimations, scrollEdgeAppearance, minimizeBehavior, tabBarActiveTintColor, tabBarInactiveTintColor, labeled = true, tabLabelStyle, }: Props) { const { state, descriptors, navigation, NavigationContent } = useNavigationBuilder< TabNavigationState, TabRouterOptions, TabActionHelpers, NativeTabsScreenOptions, NativeTabNavigationEventMap >(TabRouter, { id, initialRouteName, children, screenOptions, layout, }); return ( { const options = descriptors[route.key].options; return { key: route.key, title: options.title ?? route.name, focusedIcon: options.tabBarIcon ? options.tabBarIcon({ focused: true }) : undefined, unfocusedIcon: options.tabBarIcon ? options.tabBarIcon({ focused: false }) : undefined, badge: options.tabBarBadge, hidden: options.href === null, }; }), }} onIndexChange={(index) => { const route = state.routes[index]; const event = navigation.emit({ type: 'tabPress', target: route.key, canPreventDefault: true, }); if (!event.defaultPrevented) { navigation.dispatch({ type: 'NAVIGATE', payload: { name: route.name, merge: true }, target: state.key, }); } }} onTabLongPress={(index) => { const route = state.routes[index]; navigation.emit({ type: 'tabLongPress', target: route.key, }); }} renderScene={({ route }) => descriptors[route.key].render()} /> ); } export const createNativeTabNavigator = createNavigatorFactory(NativeTabsNavigator); const NativeTabNav = createNativeTabNavigator(); // withLayoutContext-wrapped Navigator für Expo-Router-Kompatibilität export const NativeTabs = withLayoutContext(NativeTabNav.Navigator);