Skip to content
33 changes: 32 additions & 1 deletion src/PickerInput/Selector/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,36 @@ const Input = React.forwardRef<InputRef, InputProps>((props, ref) => {
});

// ======================= Keyboard =======================
/**
* Handle manual clear when user selects all text and presses Delete/Backspace
* @returns true if input was cleared, false otherwise
*/
const handleManualClear = (event: React.KeyboardEvent<HTMLInputElement>): boolean => {
const inputElement = inputRef.current;
if (
inputElement &&
inputElement.selectionStart === 0 &&
inputElement.selectionEnd === inputValue.length &&
inputValue.length > 0
) {
onChange('');
setInputValue('');
// Prevent default browser behavior (e.g., navigation) after clearing
event.preventDefault();
return true;
}
return false;
};

const onSharedKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
const { key } = event;

if ((key === 'Backspace' || key === 'Delete') && !format) {
if (handleManualClear(event)) {
return;
}
}

if (event.key === 'Enter' && validateFormat(inputValue)) {
onSubmit();
}
Expand Down Expand Up @@ -264,10 +293,12 @@ const Input = React.forwardRef<InputRef, InputProps>((props, ref) => {
// =============== Remove ===============
case 'Backspace':
case 'Delete':
if (handleManualClear(event)) {
return;
}
nextCellText = '';
nextFillText = cellFormat;
break;

// =============== Arrows ===============
// Left key
case 'ArrowLeft':
Expand Down
12 changes: 9 additions & 3 deletions src/PickerInput/Selector/SingleSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,14 @@ function SingleSelector<DateType extends object = any>(
const rootProps = useRootProps(restProps);

// ======================== Change ========================
const onSingleChange = (date: DateType) => {
onChange([date]);
const handleSingleChange = (date: DateType) => {
if (date === null) {
// When date is null (from manual clear), delegate to onClear handler
// to properly trigger onChange and close the picker
onClear?.();
} else {
onChange([date]);
}
};

const onMultipleRemove = (date: DateType) => {
Expand All @@ -150,7 +156,7 @@ function SingleSelector<DateType extends object = any>(
const [getInputProps, getText] = useInputProps<DateType>(
{
...props,
onChange: onSingleChange,
onChange: handleSingleChange,
},
({ valueTexts }) => ({
value: valueTexts[0] || '',
Expand Down
8 changes: 7 additions & 1 deletion src/PickerInput/Selector/hooks/useInputProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,14 @@ export default function useInputProps<DateType extends object = any>(
return;
}

// Handle intentional clearing: when text is empty, trigger onChange with null
if (text === '') {
onInvalid(false, index); // Reset invalid state before clearing the value
onChange(null, index);
return;
}

// Tell outer that the value typed is invalid.
// If text is empty, it means valid.
onInvalid(!!text, index);
},
onHelp: () => {
Expand Down
Loading