import React, { useCallback, useMemo, useRef } from "react"; import { FlatList, View, ImageBackground } from "react-native"; import { Gutter } from "../Gutter"; import * as R from "ramda"; import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration"; import { FocusableGroup } from "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup"; import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable"; import Tab from "./Tab"; import { getStyles } from "./styles"; import { forceFocusableFocus } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios"; import { getId, scrollToSelectedIndex as scrollToSelectedIndexFn, generateFocusableId, applyFontConfig, } from "./utils"; import { noop } from "@applicaster/zapp-react-native-utils/functionUtils"; import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils"; const VIEW_POSITION = 0.5; const TabsComponent = ({ entry, groupId, id, style, selectedEntryIndex, setSelectedEntry, }: TabsProps & Partial) => { const configuration = useConfiguration(); const config = applyFontConfig(configuration); const styles = useMemo(() => getStyles(config), [config]); const { tab_bar_gutter: horizontalGutter, tab_bar_background_image: bgImage, component_padding_left: componentPaddingLeft, component_padding_right: componentPaddingRight, } = config; const { tabs, tabsWrapper, tabsBackground, tabsListWrapper, tabsListContentContainer, tabsFocusableGroup, } = styles; const flatListRef = useRef(null); const entryLength = R.length(entry); const scrollToSelectedIndex = useMemo(() => { return scrollToSelectedIndexFn(flatListRef, config, entryLength); }, [config]); const forceFocusOnItem = (itemId) => { try { const generatedItemId = generateFocusableId(itemId); forceFocusableFocus(id as string, generatedItemId); } catch (e) { // eslint-disable-next-line no-console console.warn("Failed to force focus on previously selected item", { error: e, itemId, }); } }; const onListElementFocus = useCallback( (index) => { scrollToSelectedIndex(index, VIEW_POSITION); }, [scrollToSelectedIndex] ); const renderItem = useCallback( ({ item, index }) => { const itemId = generateFocusableId(getId(item)); const isSelected = R.equals(index, selectedEntryIndex); const isLast = R.equals(index, entryLength - 1); const isFirst = R.equals(index, 0); const style = { paddingLeft: isFirst ? Number(componentPaddingLeft) : 0, paddingRight: isLast ? Number(componentPaddingRight) : 0, marginLeft: isFirst ? -Number(componentPaddingLeft) : 0, marginRight: isLast ? -Number(componentPaddingRight) : 0, }; return ( onListElementFocus(index)} onPress={() => setSelectedEntry && setSelectedEntry(item)} style={style} > {(focused) => ( )} ); }, [onListElementFocus, id, selectedEntryIndex] ); const renderGutter = useCallback( () => , [horizontalGutter] ); const onLayoutChange = useCallback(() => { forceFocusOnItem(getId(entry[selectedEntryIndex || 0])); scrollToSelectedIndex(selectedEntryIndex, VIEW_POSITION); }, [scrollToSelectedIndex, selectedEntryIndex, entry]); return ( ); }; export const Tabs = React.memo(TabsComponent);