1- import React , {
2- createContext ,
3- useCallback ,
4- useEffect ,
5- useState ,
6- useRef ,
7- } from 'react' ;
1+ import React , { createContext , useEffect , useState } from 'react' ;
82import {
93 TabsContextProps ,
104 ITabsContext ,
@@ -35,188 +29,17 @@ const TabsProvider = ({
3529 themeContainerId,
3630 statgrouptheme,
3731 value,
38- disabledTabIndexes = [ ] ,
39- enableArrowNav = true ,
4032 variant = TabVariant . default ,
4133} : TabsContextProps ) => {
42- const [ currentActiveTab , setCurrentActiveTab ] = useState ( value ) ;
43- const [ focusedTabIndex , setFocusedTabIndex ] = useState < number | null > ( null ) ;
44- const tabsRef = useRef < HTMLElement [ ] > ( [ ] ) ;
45- const tabListRef = useRef < HTMLElement | null > ( null ) ;
46- const tabsValuesRef = useRef < TabValue [ ] > ( [ ] ) ;
34+ const [ currentActiveTab , setCurrentActiveTab ] = useState < TabValue > ( value ) ;
4735
4836 useEffect ( ( ) => {
4937 setCurrentActiveTab ( value ) ;
5038 } , [ value ] ) ;
5139
52- const registerTab = useCallback (
53- ( tabElement : HTMLElement | null , index : number ) => {
54- if ( tabElement ) {
55- tabsRef . current [ index ] = tabElement ;
56- const tabValue = tabElement . getAttribute ( 'data-value' ) ;
57- if ( tabValue ) {
58- tabsValuesRef . current [ index ] = tabValue ;
59- }
60- }
61- } ,
62- [ ]
63- ) ;
64-
65- const registerTablist = useCallback ( ( tabListElement : HTMLElement | null ) => {
66- tabListRef . current = tabListElement ;
67- } , [ ] ) ;
68-
69- const onTabClick = useCallback (
70- ( value : TabValue , e : SelectTabEvent ) => {
71- if ( ! readOnly ) {
72- setCurrentActiveTab ( value ) ;
73- onChange ( value , e ) ;
74- }
75- } ,
76- [ onChange , readOnly ]
77- ) ;
78-
79- const moveFocusToNextTab = useCallback ( ( ) => {
80- const tabValues = tabsValuesRef . current . filter ( Boolean ) ;
81- if ( tabValues . length === 0 ) return ;
82-
83- let currentIndex =
84- focusedTabIndex !== null
85- ? focusedTabIndex
86- : tabValues . indexOf ( currentActiveTab ) ;
87- if ( currentIndex === - 1 ) currentIndex = 0 ;
88-
89- let nextIndex = currentIndex ;
90- do {
91- nextIndex = ( nextIndex + 1 ) % tabValues . length ;
92- if ( nextIndex === currentIndex ) break ;
93- } while ( disabledTabIndexes . includes ( nextIndex ) ) ;
94-
95- const nextTab = tabsRef . current [ nextIndex ] ;
96- if ( nextTab && ! disabledTabIndexes . includes ( nextIndex ) ) {
97- nextTab . focus ( ) ;
98- setFocusedTabIndex ( nextIndex ) ;
99- }
100- } , [ focusedTabIndex , currentActiveTab , disabledTabIndexes ] ) ;
101-
102- const moveFocusToPreviousTab = useCallback ( ( ) => {
103- const tabValues = tabsValuesRef . current . filter ( Boolean ) ;
104- if ( tabValues . length == 0 ) return ;
105-
106- let currentIndex =
107- focusedTabIndex !== null
108- ? focusedTabIndex
109- : tabValues . indexOf ( currentActiveTab ) ;
110- if ( currentIndex === - 1 ) currentIndex = 0 ;
111-
112- let prevIndex = currentIndex ;
113- do {
114- prevIndex = ( prevIndex - 1 + tabValues . length ) % tabValues . length ;
115- if ( prevIndex === currentIndex ) break ;
116- } while ( disabledTabIndexes . includes ( prevIndex ) ) ;
117-
118- const prevTab = tabsRef . current [ prevIndex ] ;
119- if ( prevTab && ! disabledTabIndexes . includes ( prevIndex ) ) {
120- prevTab . focus ( ) ;
121- setFocusedTabIndex ( prevIndex ) ;
122- }
123- } , [ focusedTabIndex , currentActiveTab , disabledTabIndexes ] ) ;
124-
125- useEffect ( ( ) => {
126- const handleKeyDown = ( event : globalThis . KeyboardEvent ) => {
127- if ( enableArrowNav ) return ;
128- if ( event . key == 'Tab' ) {
129- const activeElement = document . activeElement ;
130- const tabList = tabListRef . current ;
131-
132- if (
133- tabList &&
134- tabList . contains ( activeElement ) &&
135- activeElement ?. getAttribute ( 'role' ) === 'tab'
136- ) {
137- event . preventDefault ( ) ;
138- if ( event . shiftKey ) {
139- moveFocusToPreviousTab ( ) ;
140- } else {
141- moveFocusToNextTab ( ) ;
142- }
143- }
144- }
145- } ;
146- document . addEventListener ( 'keydown' , handleKeyDown ) ;
147- return ( ) => {
148- document . removeEventListener ( 'keydown' , handleKeyDown ) ;
149- } ;
150- } , [ moveFocusToNextTab , moveFocusToPreviousTab ] ) ;
151-
152- const handleKeyDown = useCallback (
153- ( event : React . KeyboardEvent , tabIndex : number ) => {
154- if ( ! enableArrowNav || readOnly ) return ;
155-
156- if ( event . key === 'Tab' ) {
157- return ;
158- }
159-
160- const enableTabIndexes = tabsRef . current
161- . map ( ( _ , index ) => index )
162- . filter ( ( index ) => ! disabledTabIndexes . includes ( index ) ) ;
163-
164- const currentEnabledIndex = enableTabIndexes . indexOf ( tabIndex ) ;
165-
166- if ( currentEnabledIndex === - 1 ) return ;
167-
168- let nextFocusIndex : number | null = null ;
169-
170- switch ( event . key ) {
171- case 'ArrowLeft' :
172- nextFocusIndex =
173- currentEnabledIndex === 0
174- ? enableTabIndexes [ enableTabIndexes . length - 1 ]
175- : enableTabIndexes [ currentEnabledIndex - 1 ] ;
176- event . preventDefault ( ) ;
177- break ;
178- case 'ArrowRight' :
179- nextFocusIndex =
180- currentEnabledIndex === enableTabIndexes . length - 1
181- ? enableTabIndexes [ 0 ]
182- : enableTabIndexes [ currentEnabledIndex + 1 ] ;
183- event . preventDefault ( ) ;
184- break ;
185- case 'Home' :
186- nextFocusIndex = enableTabIndexes [ 0 ] ;
187- event . preventDefault ( ) ;
188- break ;
189- case 'End' :
190- nextFocusIndex = enableTabIndexes [ enableTabIndexes . length - 1 ] ;
191- event . preventDefault ( ) ;
192- break ;
193- case 'Enter' :
194- const currentTab = tabsRef . current [ tabIndex ] ;
195- if ( currentTab ) {
196- const tabValue = currentTab . getAttribute ( 'data-value' ) ;
197- if ( tabValue ) {
198- setCurrentActiveTab ( tabValue ) ;
199- onChange ?.( tabValue , {
200- currentTarget : currentTab ,
201- } as SelectTabEvent ) ;
202- }
203- }
204- event . preventDefault ( ) ;
205- return ;
206- default :
207- return ;
208- }
209-
210- if ( nextFocusIndex !== null ) {
211- const nextTab = tabsRef . current [ nextFocusIndex ] ;
212- if ( nextTab ) {
213- nextTab . focus ( ) ;
214- setFocusedTabIndex ( nextFocusIndex ) ;
215- }
216- }
217- } ,
218- [ enableArrowNav , disabledTabIndexes , readOnly , onChange ]
219- ) ;
40+ const onTabClick = ( value : TabValue , e : SelectTabEvent ) => {
41+ onChange ( value , e ) ;
42+ } ;
22043
22144 return (
22245 < TabsContext . Provider
@@ -236,12 +59,6 @@ const TabsProvider = ({
23659 theme,
23760 themeContainerId,
23861 variant,
239- registerTab,
240- registerTablist,
241- handleKeyDown,
242- enableArrowNav,
243- disabledTabIndexes,
244- focusedTabIndex,
24562 } }
24663 >
24764 { children }
0 commit comments