@@ -12,6 +12,7 @@ import type {KeyboardEvent} from 'react-interactions/events/keyboard';
12
12
13
13
import React from 'react' ;
14
14
import { useKeyboard } from 'react-interactions/events/keyboard' ;
15
+ import { setElementCanTab } from 'react-interactions/accessibility/focus-control' ;
15
16
16
17
type FocusCellProps = {
17
18
children ?: React . Node ,
@@ -56,7 +57,7 @@ export function focusFirstCellOnTable(table: ReactScopeMethods): void {
56
57
}
57
58
}
58
59
59
- function focusCell ( cell : ReactScopeMethods , event ?: KeyboardEvent ) : void {
60
+ function focusScope ( cell : ReactScopeMethods , event ?: KeyboardEvent ) : void {
60
61
const tabbableNodes = cell . getScopedNodes ( ) ;
61
62
if ( tabbableNodes !== null && tabbableNodes . length > 0 ) {
62
63
tabbableNodes [ 0 ] . focus ( ) ;
@@ -75,7 +76,7 @@ function focusCellByIndex(
75
76
if ( cells !== null ) {
76
77
const cell = cells [ cellIndex ] ;
77
78
if ( cell ) {
78
- focusCell ( cell , event ) ;
79
+ focusScope ( cell , event ) ;
79
80
}
80
81
}
81
82
}
@@ -139,28 +140,40 @@ function triggerNavigateOut(
139
140
event . continuePropagation ( ) ;
140
141
}
141
142
142
- function getTableWrapProp ( currentCell : ReactScopeMethods ) : boolean {
143
+ function getTableProps ( currentCell : ReactScopeMethods ) : Object {
143
144
const row = currentCell . getParent ( ) ;
144
145
if ( row !== null && row . getProps ( ) . type === 'row' ) {
145
146
const table = row . getParent ( ) ;
146
147
if ( table !== null ) {
147
- return table . getProps ( ) . wrap || false ;
148
+ return table . getProps ( ) ;
148
149
}
149
150
}
150
- return false ;
151
+ return { } ;
151
152
}
152
153
153
154
export function createFocusTable ( scope : ReactScope ) : Array < React . Component > {
154
155
const TableScope = React . unstable_createScope ( scope . fn ) ;
155
156
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 ) ;
157
165
return (
158
166
< TableScope
159
167
type = "table"
160
168
onKeyboardOut = { onKeyboardOut }
161
169
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
+ ) }
164
177
</ TableScope >
165
178
) ;
166
179
}
@@ -179,6 +192,24 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
179
192
return ;
180
193
}
181
194
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
+ }
182
213
case 'ArrowUp' : {
183
214
const [ cells , cellIndex ] = getRowCells ( currentCell ) ;
184
215
if ( cells !== null ) {
@@ -188,7 +219,7 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
188
219
const row = rows [ rowIndex - 1 ] ;
189
220
focusCellByIndex ( row , cellIndex , event ) ;
190
221
} else if ( rowIndex === 0 ) {
191
- const wrap = getTableWrapProp ( currentCell ) ;
222
+ const wrap = getTableProps ( currentCell ) . wrap ;
192
223
if ( wrap ) {
193
224
const row = rows [ rows . length - 1 ] ;
194
225
focusCellByIndex ( row , cellIndex , event ) ;
@@ -207,7 +238,7 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
207
238
if ( rows !== null ) {
208
239
if ( rowIndex !== - 1 ) {
209
240
if ( rowIndex === rows . length - 1 ) {
210
- const wrap = getTableWrapProp ( currentCell ) ;
241
+ const wrap = getTableProps ( currentCell ) . wrap ;
211
242
if ( wrap ) {
212
243
const row = rows [ 0 ] ;
213
244
focusCellByIndex ( row , cellIndex , event ) ;
@@ -227,12 +258,12 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
227
258
const [ cells , rowIndex ] = getRowCells ( currentCell ) ;
228
259
if ( cells !== null ) {
229
260
if ( rowIndex > 0 ) {
230
- focusCell ( cells [ rowIndex - 1 ] ) ;
261
+ focusScope ( cells [ rowIndex - 1 ] ) ;
231
262
event . preventDefault ( ) ;
232
263
} else if ( rowIndex === 0 ) {
233
- const wrap = getTableWrapProp ( currentCell ) ;
264
+ const wrap = getTableProps ( currentCell ) . wrap ;
234
265
if ( wrap ) {
235
- focusCell ( cells [ cells . length - 1 ] , event ) ;
266
+ focusScope ( cells [ cells . length - 1 ] , event ) ;
236
267
} else {
237
268
triggerNavigateOut ( currentCell , 'left ', event ) ;
238
269
}
@@ -245,14 +276,14 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
245
276
if ( cells !== null ) {
246
277
if ( rowIndex !== - 1 ) {
247
278
if ( rowIndex === cells . length - 1 ) {
248
- const wrap = getTableWrapProp ( currentCell ) ;
279
+ const wrap = getTableProps ( currentCell ) . wrap ;
249
280
if ( wrap ) {
250
- focusCell ( cells [ 0 ] , event ) ;
281
+ focusScope ( cells [ 0 ] , event ) ;
251
282
} else {
252
283
triggerNavigateOut ( currentCell , 'right' , event ) ;
253
284
}
254
285
} else {
255
- focusCell ( cells [ rowIndex + 1 ] , event ) ;
286
+ focusScope ( cells [ rowIndex + 1 ] , event ) ;
256
287
}
257
288
}
258
289
}
0 commit comments