@@ -17,6 +17,7 @@ import setElementCanTab from './shared/setElementCanTab';
17
17
type FocusCellProps = {
18
18
children ?: React . Node ,
19
19
onKeyDown ?: KeyboardEvent => void ,
20
+ colSpan ? : number ,
20
21
} ;
21
22
22
23
type FocusRowProps = {
@@ -25,12 +26,12 @@ type FocusRowProps = {
25
26
26
27
type FocusTableProps = { |
27
28
children : React . Node ,
28
- id ?: string ,
29
29
onKeyboardOut ?: (
30
30
direction : 'left' | 'right' | 'up' | 'down' ,
31
- focusTableByID : ( id : string ) => void ,
31
+ event : KeyboardEvent ,
32
32
) => void ,
33
- wrap ? : boolean ,
33
+ wrapX ?: boolean ,
34
+ wrapY ?: boolean ,
34
35
tabScope ?: ReactScope ,
35
36
allowModifiers ?: boolean ,
36
37
| } ;
@@ -69,30 +70,59 @@ function focusScope(cell: ReactScopeMethods, event?: KeyboardEvent): void {
69
70
}
70
71
}
71
72
72
- function focusCellByIndex (
73
+ // This takes into account colSpan
74
+ function focusCellByColumnIndex (
73
75
row : ReactScopeMethods ,
74
- cellIndex : number ,
76
+ columnIndex : number ,
75
77
event ?: KeyboardEvent ,
76
78
) : void {
77
79
const cells = row . getChildren ( ) ;
78
80
if ( cells !== null ) {
79
- const cell = cells [ cellIndex ] ;
80
- if ( cell ) {
81
- focusScope ( cell , event ) ;
81
+ let colSize = 0 ;
82
+ for ( let i = 0 ; i < cells . length ; i ++ ) {
83
+ const cell = cells [ i ] ;
84
+ if ( cell ) {
85
+ colSize += cell . getProps ( ) . colSpan || 1 ;
86
+ if ( colSize > columnIndex ) {
87
+ focusScope ( cell , event ) ;
88
+ return ;
89
+ }
90
+ }
82
91
}
83
92
}
84
93
}
85
94
95
+ function getCellIndexes (
96
+ cells : Array < ReactScopeMethods > ,
97
+ currentCell : ReactScopeMethods ,
98
+ ) : [ number , number ] {
99
+ let totalColSpan = 0 ;
100
+ for ( let i = 0 ; i < cells . length ; i ++ ) {
101
+ const cell = cells [ i ] ;
102
+ if ( cell === currentCell ) {
103
+ return [ i , i + totalColSpan ] ;
104
+ }
105
+ const colSpan = cell . getProps ( ) . colSpan ;
106
+ if ( colSpan ) {
107
+ totalColSpan += colSpan - 1 ;
108
+ }
109
+ }
110
+ return [ - 1 , - 1 ] ;
111
+ }
112
+
86
113
function getRowCells ( currentCell : ReactScopeMethods ) {
87
114
const row = currentCell . getParent ( ) ;
88
115
if ( row !== null && row . getProps ( ) . type === 'row' ) {
89
116
const cells = row . getChildren ( ) ;
90
117
if ( cells !== null ) {
91
- const rowIndex = cells . indexOf ( currentCell ) ;
92
- return [ cells , rowIndex ] ;
118
+ const [ rowIndex , rowIndexWithColSpan ] = getCellIndexes (
119
+ cells ,
120
+ currentCell ,
121
+ ) ;
122
+ return [ cells , rowIndex , rowIndexWithColSpan ] ;
93
123
}
94
124
}
95
- return [ null , 0 ] ;
125
+ return [ null , - 1 , - 1 ] ;
96
126
}
97
127
98
128
function getRows ( currentCell : ReactScopeMethods ) {
@@ -107,7 +137,7 @@ function getRows(currentCell: ReactScopeMethods) {
107
137
}
108
138
}
109
139
}
110
- return [ null , 0 ] ;
140
+ return [ null , - 1 , - 1 ] ;
111
141
}
112
142
113
143
function triggerNavigateOut (
@@ -122,19 +152,7 @@ function triggerNavigateOut(
122
152
const props = table . getProps ( ) ;
123
153
const onKeyboardOut = props . onKeyboardOut ;
124
154
if ( props . type === 'table' && typeof onKeyboardOut === 'function' ) {
125
- const focusTableByID = ( id : string ) = > {
126
- const topLevelTables = table . getChildrenFromRoot ( ) ;
127
- if ( topLevelTables !== null ) {
128
- for ( let i = 0 ; i < topLevelTables . length ; i ++ ) {
129
- const topLevelTable = topLevelTables [ i ] ;
130
- if ( topLevelTable . getProps ( ) . id === id ) {
131
- focusFirstCellOnTable ( topLevelTable ) ;
132
- return ;
133
- }
134
- }
135
- }
136
- } ;
137
- onKeyboardOut ( direction , focusTableByID ) ;
155
+ onKeyboardOut ( direction , event ) ;
138
156
return ;
139
157
}
140
158
}
@@ -166,8 +184,8 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
166
184
function Table ( {
167
185
children,
168
186
onKeyboardOut,
169
- id ,
170
- wrap ,
187
+ wrapX ,
188
+ wrapY ,
171
189
tabScope : TabScope ,
172
190
allowModifiers,
173
191
} ) : FocusTableProps {
@@ -176,8 +194,8 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
176
194
< TableScope
177
195
type = "table"
178
196
onKeyboardOut = { onKeyboardOut }
179
- id = { id }
180
- wrap = { wrap }
197
+ wrapX = { wrapX }
198
+ wrapY = { wrapY }
181
199
tabScopeRef = { tabScopeRef }
182
200
allowModifiers = { allowModifiers } >
183
201
{ TabScope ? (
@@ -193,7 +211,7 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
193
211
return < TableScope type = "row" > { children} < / T a b l e S c o p e > ;
194
212
}
195
213
196
- function Cell ( { children, onKeyDown} ) : FocusCellProps {
214
+ function Cell ( { children, onKeyDown, colSpan } ) : FocusCellProps {
197
215
const scopeRef = useRef ( null ) ;
198
216
const keyboard = useKeyboard ( {
199
217
onKeyDown ( event : KeyboardEvent ) : void {
@@ -232,18 +250,18 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
232
250
}
233
251
switch ( key ) {
234
252
case 'ArrowUp' : {
235
- const [ cells , cellIndex ] = getRowCells ( currentCell ) ;
253
+ const [ cells , , cellIndexWithColSpan ] = getRowCells ( currentCell ) ;
236
254
if ( cells !== null ) {
237
255
const [ rows , rowIndex ] = getRows ( currentCell ) ;
238
256
if ( rows !== null ) {
239
257
if ( rowIndex > 0 ) {
240
258
const row = rows [ rowIndex - 1 ] ;
241
- focusCellByIndex ( row , cellIndex , event ) ;
259
+ focusCellByColumnIndex ( row , cellIndexWithColSpan , event ) ;
242
260
} else if ( rowIndex === 0 ) {
243
- const wrap = getTableProps ( currentCell ) . wrap ;
244
- if ( wrap ) {
261
+ const wrapY = getTableProps ( currentCell ) . wrapY ;
262
+ if ( wrapY ) {
245
263
const row = rows [ rows . length - 1 ] ;
246
- focusCellByIndex ( row , cellIndex , event ) ;
264
+ focusCellByColumnIndex ( row , cellIndexWithColSpan , event ) ;
247
265
} else {
248
266
triggerNavigateOut ( currentCell , 'up' , event ) ;
249
267
}
@@ -253,22 +271,22 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
253
271
return ;
254
272
}
255
273
case 'ArrowDown' : {
256
- const [ cells , cellIndex ] = getRowCells ( currentCell ) ;
274
+ const [ cells , , cellIndexWithColSpan ] = getRowCells ( currentCell ) ;
257
275
if ( cells !== null ) {
258
276
const [ rows , rowIndex ] = getRows ( currentCell ) ;
259
277
if ( rows !== null ) {
260
278
if ( rowIndex !== - 1 ) {
261
279
if ( rowIndex === rows . length - 1 ) {
262
- const wrap = getTableProps ( currentCell ) . wrap ;
263
- if ( wrap ) {
280
+ const wrapY = getTableProps ( currentCell ) . wrapY ;
281
+ if ( wrapY ) {
264
282
const row = rows [ 0 ] ;
265
- focusCellByIndex ( row , cellIndex , event ) ;
283
+ focusCellByColumnIndex ( row , cellIndexWithColSpan , event ) ;
266
284
} else {
267
285
triggerNavigateOut ( currentCell , 'down' , event ) ;
268
286
}
269
287
} else {
270
288
const row = rows [ rowIndex + 1 ] ;
271
- focusCellByIndex ( row , cellIndex , event ) ;
289
+ focusCellByColumnIndex ( row , cellIndexWithColSpan , event ) ;
272
290
}
273
291
}
274
292
}
@@ -282,8 +300,8 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
282
300
focusScope ( cells [ rowIndex - 1 ] ) ;
283
301
event . preventDefault ( ) ;
284
302
} else if ( rowIndex === 0 ) {
285
- const wrap = getTableProps ( currentCell ) . wrap ;
286
- if ( wrap ) {
303
+ const wrapX = getTableProps ( currentCell ) . wrapX ;
304
+ if ( wrapX ) {
287
305
focusScope ( cells [ cells . length - 1 ] , event ) ;
288
306
} else {
289
307
triggerNavigateOut ( currentCell , 'left' , event ) ;
@@ -297,8 +315,8 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
297
315
if ( cells !== null ) {
298
316
if ( rowIndex !== - 1 ) {
299
317
if ( rowIndex === cells . length - 1 ) {
300
- const wrap = getTableProps ( currentCell ) . wrap ;
301
- if ( wrap ) {
318
+ const wrapX = getTableProps ( currentCell ) . wrapX ;
319
+ if ( wrapX ) {
302
320
focusScope ( cells [ 0 ] , event ) ;
303
321
} else {
304
322
triggerNavigateOut ( currentCell , 'right' , event ) ;
@@ -317,7 +335,11 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
317
335
} ,
318
336
} ) ;
319
337
return (
320
- < TableScope listeners = { keyboard } ref = { scopeRef } type = "cell" >
338
+ < TableScope
339
+ listeners = { keyboard }
340
+ ref = { scopeRef }
341
+ type = "cell"
342
+ colSpan = { colSpan } >
321
343
{ children }
322
344
</ TableScope >
323
345
) ;
0 commit comments