@@ -15,6 +15,7 @@ import {useKeyboard} from 'react-interactions/events/keyboard';
1515
1616type FocusCellProps = {
1717 children ?: React . Node ,
18+ onKeyDown ?: KeyboardEvent => void ,
1819} ;
1920
2021type FocusRowProps = {
@@ -28,6 +29,7 @@ type FocusTableProps = {|
2829 direction : 'left' | 'right' | 'up' | 'down' ,
2930 focusTableByID : ( id : string ) => void ,
3031 ) => void ,
32+ wrap ? : boolean ,
3133| } ;
3234
3335const { useRef} = React ;
@@ -54,19 +56,26 @@ export function focusFirstCellOnTable(table: ReactScopeMethods): void {
5456 }
5557}
5658
57- function focusCell ( cell : ReactScopeMethods ) : void {
59+ function focusCell ( cell : ReactScopeMethods , event ?: KeyboardEvent ) : void {
5860 const tabbableNodes = cell . getScopedNodes ( ) ;
5961 if ( tabbableNodes !== null && tabbableNodes . length > 0 ) {
6062 tabbableNodes [ 0 ] . focus ( ) ;
63+ if ( event ) {
64+ event . preventDefault ( ) ;
65+ }
6166 }
6267}
6368
64- function focusCellByIndex ( row : ReactScopeMethods , cellIndex : number ) : void {
69+ function focusCellByIndex (
70+ row : ReactScopeMethods ,
71+ cellIndex : number ,
72+ event ?: KeyboardEvent ,
73+ ) : void {
6574 const cells = row . getChildren ( ) ;
6675 if ( cells !== null ) {
6776 const cell = cells [ cellIndex ] ;
6877 if ( cell ) {
69- focusCell ( cell ) ;
78+ focusCell ( cell , event ) ;
7079 }
7180 }
7281}
@@ -130,12 +139,27 @@ function triggerNavigateOut(
130139 event . continuePropagation ( ) ;
131140}
132141
142+ function getTableWrapProp ( currentCell : ReactScopeMethods ) : boolean {
143+ const row = currentCell . getParent ( ) ;
144+ if ( row !== null && row . getProps ( ) . type === 'row' ) {
145+ const table = row . getParent ( ) ;
146+ if ( table !== null ) {
147+ return table . getProps ( ) . wrap || false ;
148+ }
149+ }
150+ return false ;
151+ }
152+
133153export function createFocusTable ( scope : ReactScope ) : Array < React . Component > {
134154 const TableScope = React . unstable_createScope ( scope . fn ) ;
135155
136- function Table ( { children, onKeyboardOut, id} ) : FocusTableProps {
156+ function Table ( { children, onKeyboardOut, id, wrap } ) : FocusTableProps {
137157 return (
138- < TableScope type = "table" onKeyboardOut = { onKeyboardOut } id = { id } >
158+ < TableScope
159+ type = "table"
160+ onKeyboardOut = { onKeyboardOut }
161+ id = { id }
162+ wrap = { wrap } >
139163 { children }
140164 </ TableScope >
141165 ) ;
@@ -145,7 +169,7 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
145169 return < TableScope type = "row" > { children } </ TableScope > ;
146170 }
147171
148- function Cell ( { children} ) : FocusCellProps {
172+ function Cell ( { children, onKeyDown } ) : FocusCellProps {
149173 const scopeRef = useRef ( null ) ;
150174 const keyboard = useKeyboard ( {
151175 onKeyDown ( event : KeyboardEvent ) : void {
@@ -162,10 +186,15 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
162186 if ( rows !== null ) {
163187 if ( rowIndex > 0 ) {
164188 const row = rows [ rowIndex - 1 ] ;
165- focusCellByIndex ( row , cellIndex ) ;
166- event . preventDefault ( ) ;
189+ focusCellByIndex ( row , cellIndex , event ) ;
167190 } else if ( rowIndex === 0 ) {
168- triggerNavigateOut ( currentCell , 'up' , event ) ;
191+ const wrap = getTableWrapProp ( currentCell ) ;
192+ if ( wrap ) {
193+ const row = rows [ rows . length - 1 ] ;
194+ focusCellByIndex ( row , cellIndex , event ) ;
195+ } else {
196+ triggerNavigateOut ( currentCell , 'up' , event ) ;
197+ }
169198 }
170199 }
171200 }
@@ -178,11 +207,16 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
178207 if ( rows !== null ) {
179208 if ( rowIndex !== - 1 ) {
180209 if ( rowIndex === rows . length - 1 ) {
181- triggerNavigateOut ( currentCell , 'down' , event ) ;
210+ const wrap = getTableWrapProp ( currentCell ) ;
211+ if ( wrap ) {
212+ const row = rows [ 0 ] ;
213+ focusCellByIndex ( row , cellIndex , event ) ;
214+ } else {
215+ triggerNavigateOut ( currentCell , 'down' , event ) ;
216+ }
182217 } else {
183218 const row = rows [ rowIndex + 1 ] ;
184- focusCellByIndex ( row , cellIndex ) ;
185- event . preventDefault ( ) ;
219+ focusCellByIndex ( row , cellIndex , event ) ;
186220 }
187221 }
188222 }
@@ -196,7 +230,12 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
196230 focusCell ( cells [ rowIndex - 1 ] ) ;
197231 event . preventDefault ( ) ;
198232 } else if ( rowIndex === 0 ) {
199- triggerNavigateOut ( currentCell , 'left' , event ) ;
233+ const wrap = getTableWrapProp ( currentCell ) ;
234+ if ( wrap ) {
235+ focusCell ( cells [ cells . length - 1 ] , event ) ;
236+ } else {
237+ triggerNavigateOut ( currentCell , 'left ', event ) ;
238+ }
200239 }
201240 }
202241 return ;
@@ -206,16 +245,23 @@ export function createFocusTable(scope: ReactScope): Array<React.Component> {
206245 if ( cells !== null ) {
207246 if ( rowIndex !== - 1 ) {
208247 if ( rowIndex === cells . length - 1 ) {
209- triggerNavigateOut ( currentCell , 'right' , event ) ;
248+ const wrap = getTableWrapProp ( currentCell ) ;
249+ if ( wrap ) {
250+ focusCell ( cells [ 0 ] , event ) ;
251+ } else {
252+ triggerNavigateOut ( currentCell , 'right' , event) ;
253+ }
210254 } else {
211- focusCell ( cells [ rowIndex + 1 ] ) ;
212- event . preventDefault ( ) ;
255+ focusCell ( cells [ rowIndex + 1 ] , event ) ;
213256 }
214257 }
215258 }
216259 return ;
217260 }
218261 }
262+ if ( onKeyDown ) {
263+ onKeyDown ( event ) ;
264+ }
219265 } ,
220266 } ) ;
221267 return (
0 commit comments