@@ -12,6 +12,7 @@ import type {KeyboardEvent} from 'react-interactions/events/keyboard';
1212
1313import React from 'react' ;
1414import { useKeyboard } from 'react-interactions/events/keyboard' ;
15+ import { setElementCanTab } from 'react-interactions/accessibility/focus-control' ;
1516
1617type FocusCellProps = {
1718 children ?: React . Node ,
@@ -56,7 +57,7 @@ export function focusFirstCellOnTable(table: ReactScopeMethods): void {
5657 }
5758}
5859
59- function focusCell ( cell : ReactScopeMethods , event ?: KeyboardEvent ) : void {
60+ function focusScope ( cell : ReactScopeMethods , event ?: KeyboardEvent ) : void {
6061 const tabbableNodes = cell . getScopedNodes ( ) ;
6162 if ( tabbableNodes !== null && tabbableNodes . length > 0 ) {
6263 tabbableNodes [ 0 ] . focus ( ) ;
@@ -75,7 +76,7 @@ function focusCellByIndex(
7576 if ( cells !== null ) {
7677 const cell = cells [ cellIndex ] ;
7778 if ( cell ) {
78- focusCell ( cell , event ) ;
79+ focusScope ( cell , event ) ;
7980 }
8081 }
8182}
@@ -139,28 +140,40 @@ function triggerNavigateOut(
139140 event . continuePropagation ( ) ;
140141}
141142
142- function getTableWrapProp ( currentCell : ReactScopeMethods ) : boolean {
143+ function getTableProps ( currentCell : ReactScopeMethods ) : Object {
143144 const row = currentCell . getParent ( ) ;
144145 if ( row !== null && row . getProps ( ) . type === 'row' ) {
145146 const table = row . getParent ( ) ;
146147 if ( table !== null ) {
147- return table . getProps ( ) . wrap || false ;
148+ return table . getProps ( ) ;
148149 }
149150 }
150- return false ;
151+ return { } ;
151152}
152153
153154export function createFocusTable ( scope : ReactScope ) : Array < React . Component > {
154155 const TableScope = React . unstable_createScope ( scope . fn ) ;
155156
156- function Table ( { children, onKeyboardOut, id, wrap} ) : FocusTableProps {
157+ function Table ( {
158+ children,
159+ onKeyboardOut,
160+ id,
161+ wrap,
162+ tabScope : TabScope ,
163+ } ) : FocusTableProps {
164+ const tabScopeRef = useRef ( null ) ;
157165 return (
158166 < TableScope
159167 type = "table"
160168 onKeyboardOut = { onKeyboardOut }
161169 id = { id }
162- wrap = { wrap } >
163- { children }
170+ wrap = { wrap }
171+ tabScopeRef = { tabScopeRef } >
172+ { TabScope ? (
173+ < TabScope ref = { tabScopeRef } > { children } </ TabScope >
174+ ) : (
175+ children
176+ ) }
164177 </ TableScope >
165178 ) ;
166179 }
@@ -179,6 +192,24 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
179192 return ;
180193 }
181194 switch ( event . key ) {
195+ case 'Tab ': {
196+ const tabScope = getTableProps ( currentCell ) . tabScopeRef . current ;
197+ if ( tabScope ) {
198+ const activeNode = document . activeElement ;
199+ const nodes = tabScope . getScopedNodes ( ) ;
200+ for ( let i = 0 ; i < nodes . length ; i ++ ) {
201+ const node = nodes [ i ] ;
202+ if ( node !== activeNode ) {
203+ setElementCanTab ( node , false ) ;
204+ } else {
205+ setElementCanTab ( node , true ) ;
206+ }
207+ }
208+ return ;
209+ }
210+ event . continuePropagation ( ) ;
211+ return ;
212+ }
182213 case 'ArrowUp' : {
183214 const [ cells , cellIndex ] = getRowCells ( currentCell ) ;
184215 if ( cells !== null ) {
@@ -188,7 +219,7 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
188219 const row = rows [ rowIndex - 1 ] ;
189220 focusCellByIndex ( row , cellIndex , event ) ;
190221 } else if ( rowIndex === 0 ) {
191- const wrap = getTableWrapProp ( currentCell ) ;
222+ const wrap = getTableProps ( currentCell ) . wrap ;
192223 if ( wrap ) {
193224 const row = rows [ rows . length - 1 ] ;
194225 focusCellByIndex ( row , cellIndex , event ) ;
@@ -207,7 +238,7 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
207238 if ( rows !== null ) {
208239 if ( rowIndex !== - 1 ) {
209240 if ( rowIndex === rows . length - 1 ) {
210- const wrap = getTableWrapProp ( currentCell ) ;
241+ const wrap = getTableProps ( currentCell ) . wrap ;
211242 if ( wrap ) {
212243 const row = rows [ 0 ] ;
213244 focusCellByIndex ( row , cellIndex , event ) ;
@@ -227,12 +258,12 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
227258 const [ cells , rowIndex ] = getRowCells ( currentCell ) ;
228259 if ( cells !== null ) {
229260 if ( rowIndex > 0 ) {
230- focusCell ( cells [ rowIndex - 1 ] ) ;
261+ focusScope ( cells [ rowIndex - 1 ] ) ;
231262 event . preventDefault ( ) ;
232263 } else if ( rowIndex === 0 ) {
233- const wrap = getTableWrapProp ( currentCell ) ;
264+ const wrap = getTableProps ( currentCell ) . wrap ;
234265 if ( wrap ) {
235- focusCell ( cells [ cells . length - 1 ] , event ) ;
266+ focusScope ( cells [ cells . length - 1 ] , event ) ;
236267 } else {
237268 triggerNavigateOut ( currentCell , 'left ', event ) ;
238269 }
@@ -245,14 +276,14 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
245276 if ( cells !== null ) {
246277 if ( rowIndex !== - 1 ) {
247278 if ( rowIndex === cells . length - 1 ) {
248- const wrap = getTableWrapProp ( currentCell ) ;
279+ const wrap = getTableProps ( currentCell ) . wrap ;
249280 if ( wrap ) {
250- focusCell ( cells [ 0 ] , event ) ;
281+ focusScope ( cells [ 0 ] , event ) ;
251282 } else {
252283 triggerNavigateOut ( currentCell , 'right' , event ) ;
253284 }
254285 } else {
255- focusCell ( cells [ rowIndex + 1 ] , event ) ;
286+ focusScope ( cells [ rowIndex + 1 ] , event ) ;
256287 }
257288 }
258289 }
0 commit comments