Skip to content

Commit f9e8a2c

Browse files
committed
chore: adjust logic
1 parent 3ca6f16 commit f9e8a2c

4 files changed

Lines changed: 98 additions & 69 deletions

File tree

src/BaseSelect/index.tsx

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -519,65 +519,65 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
519519
const keyLockRef = React.useRef(false);
520520

521521
// KeyDown
522-
// const onInternalKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event, ...rest) => {
523-
// const clearLock = getClearLock();
524-
// const { key } = event;
522+
const onInternalKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event) => {
523+
// const clearLock = getClearLock();
524+
const { key } = event;
525525

526-
// const isEnterKey = key === 'Enter';
526+
const isEnterKey = key === 'Enter';
527527

528-
// if (isEnterKey) {
529-
// // Do not submit form when type in the input
530-
// if (mode !== 'combobox') {
531-
// event.preventDefault();
532-
// }
528+
if (isEnterKey) {
529+
// Do not submit form when type in the input
530+
if (mode !== 'combobox') {
531+
event.preventDefault();
532+
}
533533

534-
// // We only manage open state here, close logic should handle by list component
535-
// if (!mergedOpen) {
536-
// onToggleOpen(true);
537-
// }
538-
// }
534+
// We only manage open state here, close logic should handle by list component
535+
if (!mergedOpen) {
536+
triggerOpen(true);
537+
}
538+
}
539539

540-
// setClearLock(!!mergedSearchValue);
541-
542-
// // Remove value by `backspace`
543-
// if (
544-
// key === 'Backspace' &&
545-
// !clearLock &&
546-
// multiple &&
547-
// !mergedSearchValue &&
548-
// displayValues.length
549-
// ) {
550-
// const cloneDisplayValues = [...displayValues];
551-
// let removedDisplayValue = null;
552-
553-
// for (let i = cloneDisplayValues.length - 1; i >= 0; i -= 1) {
554-
// const current = cloneDisplayValues[i];
555-
556-
// if (!current.disabled) {
557-
// cloneDisplayValues.splice(i, 1);
558-
// removedDisplayValue = current;
559-
// break;
560-
// }
561-
// }
540+
// setClearLock(!!mergedSearchValue);
541+
542+
// // Remove value by `backspace`
543+
// if (
544+
// key === 'Backspace' &&
545+
// !clearLock &&
546+
// multiple &&
547+
// !mergedSearchValue &&
548+
// displayValues.length
549+
// ) {
550+
// const cloneDisplayValues = [...displayValues];
551+
// let removedDisplayValue = null;
552+
553+
// for (let i = cloneDisplayValues.length - 1; i >= 0; i -= 1) {
554+
// const current = cloneDisplayValues[i];
555+
556+
// if (!current.disabled) {
557+
// cloneDisplayValues.splice(i, 1);
558+
// removedDisplayValue = current;
559+
// break;
560+
// }
561+
// }
562562

563-
// if (removedDisplayValue) {
564-
// onDisplayValuesChange(cloneDisplayValues, {
565-
// type: 'remove',
566-
// values: [removedDisplayValue],
567-
// });
568-
// }
569-
// }
563+
// if (removedDisplayValue) {
564+
// onDisplayValuesChange(cloneDisplayValues, {
565+
// type: 'remove',
566+
// values: [removedDisplayValue],
567+
// });
568+
// }
569+
// }
570570

571-
// if (mergedOpen && (!isEnterKey || !keyLockRef.current)) {
572-
// // Lock the Enter key after it is pressed to avoid repeated triggering of the onChange event.
573-
// if (isEnterKey) {
574-
// keyLockRef.current = true;
575-
// }
576-
// listRef.current?.onKeyDown(event, ...rest);
577-
// }
571+
if (mergedOpen && (!isEnterKey || !keyLockRef.current)) {
572+
// Lock the Enter key after it is pressed to avoid repeated triggering of the onChange event.
573+
if (isEnterKey) {
574+
keyLockRef.current = true;
575+
}
576+
listRef.current?.onKeyDown(event);
577+
}
578578

579-
// onKeyDown?.(event, ...rest);
580-
// };
579+
onKeyDown?.(event);
580+
};
581581

582582
// // KeyUp
583583
// const onInternalKeyUp: React.KeyboardEventHandler<HTMLDivElement> = (event, ...rest) => {
@@ -929,6 +929,7 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
929929
onFocus={onInternalFocus}
930930
onBlur={onInternalBlur}
931931
onClearMouseDown={onClearMouseDown}
932+
onKeyDown={onInternalKeyDown}
932933
// Open
933934
onMouseDown={onInternalMouseDown}
934935
/>

src/SelectInput/Input.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export interface InputProps {
1818

1919
const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
2020
const { onChange, onKeyDown, onBlur, ...restProps } = props;
21-
const { prefixCls, mode, onSearch, onSearchSubmit, onInputBlur, autoFocus } =
21+
const { prefixCls, mode, onSearch, onSearchSubmit, onInputBlur, onInputKeyDown, autoFocus } =
2222
useSelectInputContext();
2323

2424
const inputCls = `${prefixCls}-input`;
@@ -44,6 +44,12 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
4444
const { key } = event;
4545
const { value } = event.currentTarget;
4646

47+
// Call the internal keyboard handler from context first
48+
// This handles up/down arrow prevention and validate open keys
49+
if (onInputKeyDown) {
50+
onInputKeyDown(event);
51+
}
52+
4753
// Handle Enter key submission - referencing Selector implementation
4854
if (key === 'Enter' && mode === 'tags' && !compositionStatusRef.current && onSearchSubmit) {
4955
onSearchSubmit(value);

src/SelectInput/index.tsx

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export interface SelectInputProps extends Omit<React.HTMLAttributes<HTMLDivEleme
3535
}
3636
import useBaseProps from '../hooks/useBaseProps';
3737
import { omit, useEvent } from '@rc-component/util';
38+
import KeyCode from '@rc-component/util/lib/KeyCode';
39+
import { isValidateOpenKey } from '../utils/keyUtil';
3840

3941
const DEFAULT_OMIT_PROPS = [
4042
'value',
@@ -95,15 +97,37 @@ export default React.forwardRef<SelectInputRef, SelectInputProps>(function Selec
9597
const rootRef = React.useRef<HTMLDivElement>(null);
9698
const inputRef = React.useRef<HTMLInputElement>(null);
9799

98-
// Wrap onSearch to trigger dropdown open when typing
99-
const onInternalSearch = useEvent(
100-
(searchText: string, fromTyping: boolean, isCompositing: boolean) => {
101-
// Open dropdown when user is typing and not compositing
102-
if (fromTyping && !isCompositing && !triggerOpen) {
103-
toggleOpen(true);
100+
// Handle keyboard events similar to original Selector
101+
const onInternalInputKeyDown = useEvent(
102+
(event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
103+
const { which } = event;
104+
105+
// Compatible with multiple lines in TextArea
106+
const isTextAreaElement = inputRef.current instanceof HTMLTextAreaElement;
107+
108+
// Prevent default behavior for up/down arrows when dropdown is open
109+
if (!isTextAreaElement && triggerOpen && (which === KeyCode.UP || which === KeyCode.DOWN)) {
110+
event.preventDefault();
111+
}
112+
113+
// Call the original onInputKeyDown callback
114+
if (onInputKeyDown) {
115+
onInputKeyDown(event);
104116
}
105117

106-
onSearch?.(searchText, fromTyping, isCompositing);
118+
// Move within the text box for TextArea
119+
if (
120+
isTextAreaElement &&
121+
!triggerOpen &&
122+
~[KeyCode.UP, KeyCode.DOWN, KeyCode.LEFT, KeyCode.RIGHT].indexOf(which)
123+
) {
124+
return;
125+
}
126+
127+
// Open dropdown when a valid open key is pressed
128+
if (isValidateOpenKey(which)) {
129+
toggleOpen(true);
130+
}
107131
},
108132
);
109133

@@ -146,10 +170,10 @@ export default React.forwardRef<SelectInputRef, SelectInputProps>(function Selec
146170
// ===================== Render =====================
147171
const domProps = omit(restProps, DEFAULT_OMIT_PROPS);
148172

149-
// Create context value with wrapped onSearch
173+
// Create context value with wrapped callbacks
150174
const contextValue = {
151175
...props,
152-
onSearch: onInternalSearch,
176+
onInputKeyDown: onInternalInputKeyDown,
153177
};
154178

155179
return (

tests/Combobox.test.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,17 +239,13 @@ describe('Select.Combobox', () => {
239239
fireEvent.change(container.querySelector('input')!, { target: { value: '0' } });
240240
expectOpen(container);
241241

242-
console.log('!11111111111111');
243242
selectItem(container);
244-
console.log('!2222222222222');
245243
jest.runAllTimers();
246244
expectOpen(container, false);
247245
jest.useRealTimers();
248246
});
249247
});
250248

251-
return;
252-
253249
describe('backfill', () => {
254250
it('basic', () => {
255251
const handleChange = jest.fn();
@@ -350,7 +346,7 @@ describe('Select.Combobox', () => {
350346
</Select>,
351347
);
352348

353-
expect(container.querySelector('.rc-select-clear-icon')).toBeTruthy();
349+
expect(container.querySelector('.rc-select-clear')).toBeTruthy();
354350
});
355351

356352
it("should hide clear icon when inputValue is ''", () => {
@@ -362,11 +358,13 @@ describe('Select.Combobox', () => {
362358
);
363359

364360
fireEvent.change(container.querySelector('input')!, { target: { value: '1' } });
365-
expect(container.querySelector('.rc-select-clear-icon')).toBeTruthy();
361+
expect(container.querySelector('.rc-select-clear')).toBeTruthy();
366362
fireEvent.change(container.querySelector('input')!, { target: { value: '' } });
367-
expect(container.querySelector('.rc-select-clear-icon')).toBeFalsy();
363+
expect(container.querySelector('.rc-select-clear')).toBeFalsy();
368364
});
369365

366+
return;
367+
370368
it('autocomplete - option update when input change', () => {
371369
class App extends React.Component {
372370
public state = {

0 commit comments

Comments
 (0)