import React , { useRef , useEffect , useCallback , useState } from 'react' ; import { TabBarProps } from './tab-bar' ; import { useFoundation } from '@rmwc/base' ; import { MDCTabBarFoundation } from '@material/tab-bar' ; import { TabScrollerApi } from './tab-scroller' ; import { MDCTabInteractionEvent } from '@material/tab' ; import { TabApi } from './tab' ; export const useTabBarFoundation = ( props ) => { const [ activeTabIndex , setActiveTabIndex ] = useState ( props . activeTabIndex || 0 ) ; const tabScrollerApi = useRef < TabScrollerApi > ( ) ; const setTabScrollerApi = ( api ) => ( tabScrollerApi . current = api ) ; const tabListRef = useRef < TabApi [ ] > ( [ ] ) ; const { foundation , ... elements } = useFoundation ( { props , elements : { rootEl : true } , foundation : ( { rootEl , emit , getProps } ) => { return new MDCTabBarFoundation ( { scrollTo : ( scrollX ) => { tabScrollerApi . current && tabScrollerApi . current . scrollTo ( scrollX ) ; } , incrementScroll : ( scrollXIncrement ) => { tabScrollerApi . current ?. incrementScroll ( scrollXIncrement ) ; } , getScrollPosition : ( ) => tabScrollerApi . current ?. getScrollPosition ( ) || 0 , getScrollContentWidth : ( ) => tabScrollerApi . current ?. getScrollContentWidth ( ) || 0 , getOffsetWidth : ( ) => ( rootEl . ref ? rootEl . ref . offsetWidth : 0 ) , isRTL : ( ) => ! ! rootEl . ref && window . getComputedStyle ( rootEl . ref ) . getPropertyValue ( 'direction' ) === 'rtl' , setActiveTab : ( index ) => { if ( props . activeTabIndex === index || props . activeTabIndex === undefined ) { setActiveTabIndex ( index ) ; } else { foundation . adapter_ . notifyTabActivated ( index ) ; } } , activateTabAtIndex : ( index , clientRect ) => { tabListRef . current [ index ] && tabListRef . current [ index ] . activate ( clientRect ) ; } , deactivateTabAtIndex : ( index ) => tabListRef . current [ index ] && tabListRef . current [ index ] . deactivate ( ) , focusTabAtIndex : ( index ) => tabListRef . current [ index ] . focus ( ) , getTabIndicatorClientRectAtIndex : ( index ) => tabListRef . current [ index ] && tabListRef . current [ index ] . computeIndicatorClientRect ( ) , getTabDimensionsAtIndex : ( index ) => tabListRef . current [ index ] && tabListRef . current [ index ] . computeDimensions ( ) , getPreviousActiveTabIndex : ( ) => { for ( let i = 0 ; i < tabListRef . current . length ; i ++ ) { if ( tabListRef . current [ i ] . getActive ( ) ) { return i ; } } return - 1 ; } , getFocusedTabIndex : ( ) => { const tabElements = [ ] . slice . call ( rootEl . ref ?. querySelectorAll ( MDCTabBarFoundation . strings . TAB_SELECTOR ) ) ; const activeElement = document . activeElement as Element ; return tabElements ? tabElements . indexOf ( activeElement ) : - 1 ; } , getIndexOfTabById : ( id ) => { for ( let i = 0 ; i < tabListRef . current . length ; i ++ ) { if ( tabListRef . current [ i ] . id === id ) { return i ; } } return - 1 ; } , getTabListLength : ( ) => tabListRef . current . length , notifyTabActivated : ( index ) => emit ( 'onActivate' , { index } , true ) } ) ; } } ) ; const { rootEl } = elements ; const registerTab = ( tab ) => { tabListRef . current . push ( tab ) ; tabListRef . current . sort ( ( a , b ) => a . getIndex ( ) - b . getIndex ( ) ) ; } ; const unregisterTab = ( tab ) => { tabListRef . current . splice ( tabListRef . current . indexOf ( tab ) , 1 ) ; tabListRef . current . sort ( ( a , b ) => a . getIndex ( ) - b . getIndex ( ) ) ; } ; const handleTabInteraction = useCallback ( ( evt ) => { foundation . handleTabInteraction ( evt ) ; } , [ foundation ] ) ; const handleKeyDown = ( evt ) => { props . onKeyDown ?. ( evt as React . KeyboardEvent ) ; foundation . handleKeyDown ( evt as KeyboardEvent ) ; } ; rootEl . setProp ( 'onKeyDown' , handleKeyDown , true ) ; useEffect ( ( ) => { props . activeTabIndex !== undefined && setActiveTabIndex ( props . activeTabIndex ) ; } , [ props . activeTabIndex ] ) ; useEffect ( ( ) => { const index = activeTabIndex ; const adapter = foundation . adapter_ ; const previousActiveIndex = adapter . getPreviousActiveTabIndex ( ) ; if ( ! foundation . indexIsInRange_ ( index ) || index === previousActiveIndex ) { return ; } adapter . notifyTabActivated ( index ) ; window . requestAnimationFrame ( ( ) => { adapter . activateTabAtIndex ( index , adapter . getTabIndicatorClientRectAtIndex ( previousActiveIndex ) ) ; foundation . scrollIntoView ( index ) ; } ) ; return ( ) => { window . requestAnimationFrame ( ( ) => { adapter . deactivateTabAtIndex ( index ) ; } ) ; } ; } , [ activeTabIndex , foundation ] ) ; useEffect ( ( ) => { const activeElement = window . document . activeElement ; const [ scrollX , scrollY ] = [ window . scrollX , window . scrollY ] ; window . requestAnimationFrame ( ( ) => { activeElement && activeElement . focus ( ) ; window . scrollTo ( scrollX , scrollY ) ; } ) ; } , [ ] ) ; return { ... elements , setTabScrollerApi , handleTabInteraction , registerTab , unregisterTab } ; } ;