import { createContext, forwardRef, useContext, useId } from 'react'; import { Pressable, Text, View, type GestureResponderEvent, } from 'react-native'; import * as Slot from '../slot'; import type { ContentProps, ContentRef, IndicatorProps, IndicatorRef, LabelProps, LabelRef, ListProps, ListRef, RootProps, RootRef, TriggerProps, TriggerRef, } from './tabs.types'; type RootContext = RootProps & { nativeID: string; }; const TabsContext = createContext(null); const Root = forwardRef( ({ asChild, value, onValueChange, ...viewProps }, ref) => { const nativeID = useId(); const Component = asChild ? Slot.View : View; return ( ); } ); Root.displayName = 'HeroUINative.Primitive.Tabs.Root'; function useRootContext() { const context = useContext(TabsContext); if (!context) { throw new Error( 'Tabs compound components cannot be rendered outside the Tabs component' ); } return context; } // -------------------------------------------------- const List = forwardRef(({ asChild, ...props }, ref) => { const Component = asChild ? Slot.View : View; return ; }); List.displayName = 'HeroUINative.Primitive.Tabs.List'; // -------------------------------------------------- const Indicator = forwardRef( ({ asChild, ...props }, ref) => { const Component = asChild ? Slot.View : View; return ( ); } ); Indicator.displayName = 'HeroUINative.Primitive.Tabs.Indicator'; // -------------------------------------------------- type TriggerContext = { value: string; nativeID: string; isSelected: boolean; }; const TriggerContext = createContext(null); const Trigger = forwardRef( ( { asChild, onPress: onPressProp, disabled, value: tabValue, ...props }, ref ) => { const { onValueChange, value: rootValue, nativeID } = useRootContext(); function onPress(ev: GestureResponderEvent) { if (disabled) return; onValueChange(tabValue); onPressProp?.(ev); } const Component = asChild ? Slot.Pressable : Pressable; const tabNativeID = `${nativeID}-tab-${tabValue}`; const isSelected = rootValue === tabValue; return ( ); } ); Trigger.displayName = 'HeroUINative.Primitive.Tabs.Trigger'; function useTriggerContext() { const context = useContext(TriggerContext); if (!context) { throw new Error( 'Tabs.Trigger compound components cannot be rendered outside the Tabs.Trigger component' ); } return context; } // -------------------------------------------------- const Label = forwardRef(({ asChild, ...props }, ref) => { const { nativeID } = useTriggerContext(); const Component = asChild ? Slot.Text : Text; return ( ); }); Label.displayName = 'HeroUINative.Primitive.Tabs.Label'; // -------------------------------------------------- const Content = forwardRef( ({ asChild, forceMount, value: tabValue, ...props }, ref) => { const { value: rootValue, nativeID } = useRootContext(); if (!forceMount) { if (rootValue !== tabValue) { return null; } } const Component = asChild ? Slot.View : View; return ( ); } ); Content.displayName = 'HeroUINative.Primitive.Tabs.Content'; export { Content, Indicator, Label, List, Root, Trigger, useRootContext, useTriggerContext, };