1- import { useState , KeyboardEvent , useRef , useEffect } from 'react' ;
1+ import { useState , useRef , useEffect } from 'react' ;
22
33import useConfig from '../../hooks/useConfig' ;
44import { getSelectValueArr } from '../util/helper' ;
55
6- import type { SelectOption , TdOptionProps , SelectValue } from '../type' ;
6+ import type { SelectOption , TdOptionProps , SelectValueChangeTrigger , SelectValue } from '../type' ;
77
88export type useKeyboardControlType = {
9- displayOptions : TdOptionProps [ ] ;
10- innerPopupVisible : boolean ;
11- setInnerPopupVisible : any ;
12- onCheckAllChange : ( checkAll : boolean , e ?: React . MouseEvent < HTMLLIElement > ) => void ;
13- setInnerValue : Function ;
14- innerValue : SelectValue < SelectOption > ;
15- multiple : boolean ;
169 max : number ;
10+ multiple : boolean ;
11+ value : SelectValue < SelectOption > ;
12+ handleChange : (
13+ value : SelectValue ,
14+ context : {
15+ e : React . KeyboardEvent < HTMLInputElement > ;
16+ trigger : SelectValueChangeTrigger ;
17+ } ,
18+ ) => void ;
19+ innerPopupVisible : boolean ;
20+ handlePopupVisibleChange : ( visible : boolean , ctx : { e : React . KeyboardEvent < HTMLInputElement > } ) => void ;
21+ displayOptions : TdOptionProps [ ] ;
22+ onCheckAllChange : ( checkAll : boolean , e ?: React . KeyboardEvent < HTMLInputElement > ) => void ;
1723 selectInputRef : any ;
1824} ;
1925
2026export default function useKeyboardControl ( {
21- displayOptions,
22- innerPopupVisible,
23- setInnerPopupVisible,
24- setInnerValue,
25- innerValue,
26- multiple,
2727 max,
28+ multiple,
29+ value,
30+ handleChange,
31+ innerPopupVisible,
32+ handlePopupVisibleChange,
33+ displayOptions,
2834 onCheckAllChange,
2935 selectInputRef,
3036} : useKeyboardControlType ) {
@@ -35,9 +41,10 @@ export default function useKeyboardControl({
3541 // 全选判断
3642 const isCheckAll = useRef ( false ) ;
3743 useEffect ( ( ) => {
38- if ( ! Array . isArray ( innerValue ) ) return ;
39- isCheckAll . current = innerValue . length === displayOptions . filter ( ( v ) => ! ( v . disabled || v . checkAll ) ) . length ;
40- } , [ innerValue , displayOptions ] ) ;
44+ if ( ! Array . isArray ( value ) ) return ;
45+ isCheckAll . current =
46+ value . length === displayOptions . filter ( ( v ) => ! ( ( v . disabled || v . checkAll ) && ! value . includes ( v . value ) ) ) . length ;
47+ } , [ value , displayOptions ] ) ;
4148
4249 const handleKeyboardScroll = ( hoverIndex : number ) => {
4350 const popupContent = selectInputRef . current . getPopupContentElement ( ) ;
@@ -56,65 +63,57 @@ export default function useKeyboardControl({
5663 }
5764 } ;
5865
59- const handleKeyDown = ( _value , { e } : { e : KeyboardEvent } ) => {
66+ useEffect ( ( ) => {
67+ changeHoverOption ( hoverIndex === - 1 ? undefined : displayOptions [ hoverIndex ] ) ;
68+ } , [ hoverIndex , displayOptions ] ) ;
69+
70+ const handleKeyDown = ( _value , { e } : { e : React . KeyboardEvent < HTMLInputElement > } ) => {
6071 const optionsListLength = displayOptions . length ;
6172
6273 let newIndex = hoverIndex ;
6374
6475 switch ( e . code ) {
6576 case 'ArrowUp' :
6677 e . preventDefault ( ) ;
67- if ( hoverIndex === - 1 ) {
68- newIndex = 0 ;
69- } else if ( hoverIndex === 0 || hoverIndex > optionsListLength - 1 ) {
70- newIndex = optionsListLength - 1 ;
71- } else {
72- newIndex -= 1 ;
73- }
74- if ( displayOptions [ newIndex ] ?. disabled ) {
75- newIndex -= 1 ;
76- }
77- changeHoverIndex ( newIndex ) ;
78+ if ( hoverIndex === - 1 ) newIndex = 0 ;
79+ else if ( hoverIndex === 0 || hoverIndex > optionsListLength - 1 ) newIndex = optionsListLength - 1 ;
80+ else newIndex -= 1 ;
7881
79- changeHoverOption ( displayOptions [ newIndex ] ) ;
82+ if ( displayOptions [ newIndex ] ?. disabled ) newIndex -= 1 ;
83+
84+ changeHoverIndex ( newIndex ) ;
8085 handleKeyboardScroll ( newIndex ) ;
8186 break ;
8287 case 'ArrowDown' :
8388 e . preventDefault ( ) ;
89+ if ( hoverIndex === - 1 || hoverIndex >= optionsListLength - 1 ) newIndex = 0 ;
90+ else newIndex += 1 ;
8491
85- if ( hoverIndex === - 1 || hoverIndex >= optionsListLength - 1 ) {
86- newIndex = 0 ;
87- } else {
88- newIndex += 1 ;
89- }
90- if ( displayOptions [ newIndex ] ?. disabled ) {
91- newIndex += 1 ;
92- }
93- changeHoverIndex ( newIndex ) ;
94- changeHoverOption ( displayOptions [ newIndex ] ) ;
92+ if ( displayOptions [ newIndex ] ?. disabled ) newIndex += 1 ;
9593
94+ changeHoverIndex ( newIndex ) ;
9695 handleKeyboardScroll ( newIndex ) ;
9796 break ;
9897 case 'Enter' :
99- if ( hoverIndex === - 1 ) break ;
100-
10198 if ( ! innerPopupVisible ) {
102- setInnerPopupVisible ( true , { e } ) ;
99+ handlePopupVisibleChange ( true , { e } ) ;
103100 break ;
104101 }
105102
103+ if ( hoverIndex === - 1 ) return ;
104+
106105 if ( ! multiple ) {
107106 const selectedOptions = displayOptions [ hoverIndex ] ;
108- setInnerValue ( selectedOptions . value , {
109- option : selectedOptions ?. [ 0 ] ,
110- selectedOptions : displayOptions [ hoverIndex ] ,
111- trigger : 'check' ,
112- e,
113- } ) ;
114- setInnerPopupVisible ( false , { e } ) ;
115- } else {
116- if ( hoverIndex === - 1 ) return ;
117107
108+ if ( selectedOptions )
109+ handleChange ( selectedOptions . value , {
110+ trigger : 'check' ,
111+ e,
112+ } ) ;
113+ handlePopupVisibleChange ( false , { e } ) ;
114+ changeHoverIndex ( - 1 ) ;
115+ handleKeyboardScroll ( 0 ) ;
116+ } else {
118117 if ( displayOptions [ hoverIndex ] . checkAll ) {
119118 onCheckAllChange ( ! isCheckAll . current ) ;
120119 return ;
@@ -123,22 +122,23 @@ export default function useKeyboardControl({
123122 const optionValue = displayOptions [ hoverIndex ] ?. value ;
124123
125124 if ( ! optionValue ) return ;
126- const newValue = innerValue as Array < SelectValue > ;
125+ const newValue = value as Array < SelectValue > ;
127126 const valueIndex = newValue . indexOf ( optionValue ) ;
128127 const isSelected = valueIndex > - 1 ;
129128
130- const values = getSelectValueArr ( innerValue , optionValue , isSelected ) ;
129+ const values = getSelectValueArr ( value , optionValue , isSelected ) ;
131130
132131 if ( max > 0 && values . length > max ) return ; // 如果已选达到最大值 则不处理
133- setInnerValue ( values , {
134- option : [ ] ,
132+ handleChange ( values , {
135133 trigger : ! isSelected ? 'check' : 'uncheck' ,
136134 e,
137135 } ) ;
138136 }
139137 break ;
140138 case 'Escape' :
141- setInnerPopupVisible ( false , { e } ) ;
139+ handlePopupVisibleChange ( false , { e } ) ;
140+ changeHoverIndex ( - 1 ) ;
141+ handleKeyboardScroll ( 0 ) ;
142142 }
143143 } ;
144144
0 commit comments