From afeca4d41909904b158d0f74548a7a97ba2a454a Mon Sep 17 00:00:00 2001 From: zombiej Date: Sun, 12 Apr 2020 21:39:55 +0800 Subject: [PATCH 1/2] fix datePicker disabled keyboard --- src/Picker.tsx | 55 +++++++++++-------------------------- src/PickerPanel.tsx | 2 +- src/hooks/usePickerInput.ts | 10 ++----- 3 files changed, 20 insertions(+), 47 deletions(-) diff --git a/src/Picker.tsx b/src/Picker.tsx index 975e0c41e..8479728c7 100644 --- a/src/Picker.tsx +++ b/src/Picker.tsx @@ -26,11 +26,7 @@ import { isEqual } from './utils/dateUtil'; import getDataOrAriaProps, { toArray } from './utils/miscUtil'; import PanelContext, { ContextOperationRefProps } from './PanelContext'; import { PickerMode } from './interface'; -import { - getDefaultFormat, - getInputSize, - elementsContains, -} from './utils/uiUtil'; +import { getDefaultFormat, getInputSize, elementsContains } from './utils/uiUtil'; import usePickerInput from './hooks/usePickerInput'; import useTextValueMapping from './hooks/useTextValueMapping'; import useValueTexts from './hooks/useValueTexts'; @@ -120,9 +116,7 @@ export type PickerProps = interface MergedPickerProps extends Omit< - PickerBaseProps & - PickerDateProps & - PickerTimeProps, + PickerBaseProps & PickerDateProps & PickerTimeProps, 'picker' > { picker?: PickerMode; @@ -173,13 +167,10 @@ function InnerPicker(props: PickerProps) { const inputRef = React.useRef(null); - const needConfirmButton: boolean = - (picker === 'date' && !!showTime) || picker === 'time'; + const needConfirmButton: boolean = (picker === 'date' && !!showTime) || picker === 'time'; // ============================= State ============================= - const formatList = toArray( - getDefaultFormat(format, picker, showTime, use12Hours), - ); + const formatList = toArray(getDefaultFormat(format, picker, showTime, use12Hours)); // Panel ref const panelDivRef = React.useRef(null); @@ -192,9 +183,7 @@ function InnerPicker(props: PickerProps) { }); // Selected value - const [selectedValue, setSelectedValue] = React.useState( - mergedValue, - ); + const [selectedValue, setSelectedValue] = React.useState(mergedValue); // Operation ref const operationRef: React.MutableRefObject = React.useRef< @@ -227,11 +216,7 @@ function InnerPicker(props: PickerProps) { const [text, triggerTextChange, resetText] = useTextValueMapping({ valueTexts, onTextChange: newText => { - const inputDate = generateConfig.locale.parse( - locale.locale, - newText, - formatList, - ); + const inputDate = generateConfig.locale.parse(locale.locale, newText, formatList); if (inputDate && (!disabledDate || !disabledDate(inputDate))) { setSelectedValue(inputDate); } @@ -246,17 +231,12 @@ function InnerPicker(props: PickerProps) { if (onChange && !isEqual(generateConfig, mergedValue, newValue)) { onChange( newValue, - newValue - ? generateConfig.locale.format(locale.locale, newValue, formatList[0]) - : '', + newValue ? generateConfig.locale.format(locale.locale, newValue, formatList[0]) : '', ); } }; - const triggerOpen = ( - newOpen: boolean, - preventChangeEvent: boolean = false, - ) => { + const triggerOpen = (newOpen: boolean, preventChangeEvent: boolean = false) => { triggerInnerOpen(newOpen); if (!newOpen && !preventChangeEvent) { triggerChange(selectedValue); @@ -280,9 +260,7 @@ function InnerPicker(props: PickerProps) { } }; - const onInternalMouseUp: React.MouseEventHandler = ( - ...args - ) => { + const onInternalMouseUp: React.MouseEventHandler = (...args) => { if (onMouseUp) { onMouseUp(...args); } @@ -300,14 +278,16 @@ function InnerPicker(props: PickerProps) { triggerOpen, forwardKeyDown, isClickOutside: target => - !elementsContains( - [panelDivRef.current, inputDivRef.current], - target as HTMLElement, - ), + !elementsContains([panelDivRef.current, inputDivRef.current], target as HTMLElement), onSubmit: () => { + if (disabledDate && disabledDate(selectedValue)) { + return false; + } + triggerChange(selectedValue); triggerOpen(false, true); resetText(); + return true; }, onCancel: () => { triggerOpen(false, true); @@ -428,10 +408,7 @@ function InnerPicker(props: PickerProps) { } // ============================ Return ============================= - const onContextSelect = ( - date: DateType, - type: 'key' | 'mouse' | 'submit', - ) => { + const onContextSelect = (date: DateType, type: 'key' | 'mouse' | 'submit') => { if (type === 'submit' || (type !== 'key' && !needConfirmButton)) { // triggerChange will also update selected values triggerChange(date); diff --git a/src/PickerPanel.tsx b/src/PickerPanel.tsx index 8c8102dfd..dcf37b7f9 100644 --- a/src/PickerPanel.tsx +++ b/src/PickerPanel.tsx @@ -440,7 +440,7 @@ function PickerPanel(props: PickerPanelProps) { prefixCls, components, needConfirmButton, - okDisabled: !mergedValue, + okDisabled: !mergedValue || (disabledDate && disabledDate(mergedValue)), locale, onNow: needConfirmButton && diff --git a/src/hooks/usePickerInput.ts b/src/hooks/usePickerInput.ts index 70403ea3d..4c03b66c5 100644 --- a/src/hooks/usePickerInput.ts +++ b/src/hooks/usePickerInput.ts @@ -18,14 +18,11 @@ export default function usePickerInput({ triggerOpen: (open: boolean) => void; forwardKeyDown: (e: React.KeyboardEvent) => boolean; blurToCancel?: boolean; - onSubmit: () => void; + onSubmit: () => void | boolean; onCancel: () => void; onFocus?: React.FocusEventHandler; onBlur?: React.FocusEventHandler; -}): [ - React.DOMAttributes, - { focused: boolean; typing: boolean }, -] { +}): [React.DOMAttributes, { focused: boolean; typing: boolean }] { const [typing, setTyping] = React.useState(false); const [focused, setFocused] = React.useState(false); @@ -45,8 +42,7 @@ export default function usePickerInput({ case KeyCode.ENTER: { if (!open) { triggerOpen(true); - } else { - onSubmit(); + } else if (onSubmit() !== false) { setTyping(true); } From 51fb0276465e77a4223485ac75b2624c0dbb212d Mon Sep 17 00:00:00 2001 From: zombiej Date: Sun, 12 Apr 2020 21:51:36 +0800 Subject: [PATCH 2/2] test case --- tests/keyboard.spec.tsx | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/keyboard.spec.tsx b/tests/keyboard.spec.tsx index 16f02ff86..b1114622e 100644 --- a/tests/keyboard.spec.tsx +++ b/tests/keyboard.spec.tsx @@ -455,4 +455,36 @@ describe('Picker.Keyboard', () => { expect(preventDefault).toHaveBeenCalled(); }); + + it('keyboard should not trigger on disabledDate', () => { + const onChange = jest.fn(); + const onSelect = jest.fn(); + const wrapper = mount( + date.date() % 2 === 0} + />, + ); + wrapper.find('input').simulate('focus'); + wrapper.keyDown(KeyCode.ENTER); + wrapper.keyDown(KeyCode.TAB); + wrapper.keyDown(KeyCode.TAB); + wrapper.keyDown(KeyCode.DOWN); + expect(isSame(onSelect.mock.calls[0][0], '1990-09-10')).toBeTruthy(); + + // Not enter to change + wrapper.keyDown(KeyCode.ENTER); + expect(onChange).not.toHaveBeenCalled(); + + // Not button enabled + expect(wrapper.find('.rc-picker-ok button').props().disabled).toBeTruthy(); + + // Another can be enter + wrapper.keyDown(KeyCode.RIGHT); + expect(wrapper.find('.rc-picker-ok button').props().disabled).toBeFalsy(); + wrapper.keyDown(KeyCode.ENTER); + expect(onChange).toHaveBeenCalled(); + }); });