@@ -206,6 +206,53 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
206
206
setActiveKey ( nextActiveKey ) ;
207
207
} , [ open , searchValue ] ) ;
208
208
209
+ const getNextMatchingNode = (
210
+ nodes : EventDataNode < any > [ ] ,
211
+ currentKey : Key | null ,
212
+ direction : 'next' | 'prev' = 'next' ,
213
+ ) : EventDataNode < any > | null => {
214
+ const availableNodes : EventDataNode < any > [ ] = [ ] ;
215
+
216
+ const collectNodes = ( nodeList : EventDataNode < any > [ ] ) => {
217
+ nodeList . forEach ( node => {
218
+ if ( ! node . disabled && node . selectable !== false ) {
219
+ // only collect selected nodes
220
+ if ( displayValues ?. some ( v => v . value === node [ fieldNames . value ] ) ) {
221
+ availableNodes . push ( node ) ;
222
+ }
223
+ }
224
+ if ( node [ fieldNames . children ] ) {
225
+ collectNodes ( node [ fieldNames . children ] ) ;
226
+ }
227
+ } ) ;
228
+ } ;
229
+
230
+ collectNodes ( nodes ) ;
231
+
232
+ if ( availableNodes . length === 0 ) {
233
+ return null ;
234
+ }
235
+
236
+ // if no current selected node, return first available node
237
+ if ( ! currentKey ) {
238
+ return availableNodes [ 0 ] ;
239
+ }
240
+
241
+ const currentIndex = availableNodes . findIndex ( node => node [ fieldNames . value ] === currentKey ) ;
242
+
243
+ // if current node is not in available nodes list, return first node
244
+ if ( currentIndex === - 1 ) {
245
+ return availableNodes [ 0 ] ;
246
+ }
247
+
248
+ const nextIndex =
249
+ direction === 'next'
250
+ ? ( currentIndex + 1 ) % availableNodes . length
251
+ : ( currentIndex - 1 + availableNodes . length ) % availableNodes . length ;
252
+
253
+ return availableNodes [ nextIndex ] ;
254
+ } ;
255
+
209
256
// ========================= Keyboard =========================
210
257
React . useImperativeHandle ( ref , ( ) => ( {
211
258
scrollTo : treeRef . current ?. scrollTo ,
@@ -217,7 +264,18 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
217
264
case KeyCode . DOWN :
218
265
case KeyCode . LEFT :
219
266
case KeyCode . RIGHT :
220
- treeRef . current ?. onKeyDown ( event as React . KeyboardEvent < HTMLDivElement > ) ;
267
+ if ( isOverMaxCount ) {
268
+ event . preventDefault ( ) ;
269
+ const direction = which === KeyCode . UP || which === KeyCode . LEFT ? 'prev' : 'next' ;
270
+ const nextNode = getNextMatchingNode ( memoTreeData , activeKey , direction ) ;
271
+ if ( nextNode ) {
272
+ setActiveKey ( nextNode [ fieldNames . value ] ) ;
273
+ // ensure scroll to visible area
274
+ treeRef . current ?. scrollTo ( { key : nextNode [ fieldNames . value ] } ) ;
275
+ }
276
+ } else {
277
+ treeRef . current ?. onKeyDown ( event as React . KeyboardEvent < HTMLDivElement > ) ;
278
+ }
221
279
break ;
222
280
223
281
// >>> Select item
@@ -251,10 +309,15 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
251
309
) ;
252
310
253
311
const onActiveChange = ( key : Key ) => {
254
- if ( isOverMaxCount && ! displayValues ?. some ( v => v . value === key ) ) {
312
+ if ( ! isOverMaxCount ) {
313
+ setActiveKey ( key ) ;
255
314
return ;
256
315
}
257
- setActiveKey ( key ) ;
316
+
317
+ const nextNode = getNextMatchingNode ( memoTreeData , key ) ;
318
+ if ( nextNode ) {
319
+ setActiveKey ( nextNode [ fieldNames . value ] ) ;
320
+ }
258
321
} ;
259
322
260
323
// ========================== Render ==========================
0 commit comments