From 7c0b0a46bc83d5e38cb1d3cda559ed386b3d67d8 Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Fri, 26 Jun 2020 10:56:00 +0100 Subject: [PATCH 1/7] Add support for onSelect callback for RangePicker --- README.md | 1 + src/RangePicker.tsx | 12 ++++++++++++ tests/range.spec.tsx | 16 ++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/README.md b/README.md index 79eed2bce..464b9d116 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,7 @@ render(, mountNode); | allowEmpty | [Boolean, Boolean] | | allow range picker clearing text | | selectable | [Boolean, Boolean] | | whether to selected picker | | disabled | Boolean | false | whether the range picker is disabled | +| onSelect | Function(value: moment, formatString: string, info: 'start' | 'end') | a callback function for when a start or end date is selected | | onChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the selected time is changing | | onCalendarChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the start time or the end time of the range is changing | | direction | String: ltr or rtl | | Layout direction of picker component, it supports RTL direction too. | diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index 5ca56f2a7..2b796b9fb 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -85,6 +85,7 @@ export interface RangePickerSharedProps { separator?: React.ReactNode; allowEmpty?: [boolean, boolean]; mode?: [PanelMode, PanelMode]; + onSelect?: (value: DateType, formatString: string, info: 'start' | 'end') => void; onChange?: (values: RangeValue, formatString: [string, string]) => void; onCalendarChange?: (values: RangeValue, formatString: [string, string]) => void; onPanelChange?: (values: RangeValue, modes: [PanelMode, PanelMode]) => void; @@ -190,6 +191,7 @@ function InnerRangePicker(props: RangePickerProps) { inputReadOnly, mode, renderExtraFooter, + onSelect, onChange, onOpenChange, onPanelChange, @@ -415,6 +417,16 @@ function InnerRangePicker(props: RangePickerProps) { ? generateConfig.locale.format(locale.locale, values[1], formatList[0]) : ''; + if (onSelect) { + if (!isEqual(generateConfig, getValue(mergedValue, 0), startValue)) { + onSelect(startValue, startStr, 'start'); + } + + if (!isEqual(generateConfig, getValue(mergedValue, 1), endValue)) { + onSelect(endValue, endStr, 'end'); + } + } + if (onCalendarChange) { onCalendarChange(values, [startStr, endStr]); } diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx index 334b66497..644104a7c 100644 --- a/tests/range.spec.tsx +++ b/tests/range.spec.tsx @@ -1299,4 +1299,20 @@ describe('Picker.Range', () => { expect(wrapper.isOpen()).toBeFalsy(); }); }); + + it('selection triggers onSelect callback', () => { + const onSelect = jest.fn(); + + const wrapper = mount(); + + wrapper.openPicker(); + + // Start date + wrapper.selectCell(11); + expect(onSelect).toHaveBeenCalledWith(expect.anything(), '1990-09-11', 'start'); + + // End date + wrapper.selectCell(23); + expect(onSelect).toHaveBeenCalledWith(expect.anything(), '1990-09-23', 'end'); + }); }); From d7a5e618ec508d46ee176e10a76d3251a74c0cfb Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Fri, 26 Jun 2020 10:57:20 +0100 Subject: [PATCH 2/7] Correctly escape character in markdown --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 464b9d116..eb316b57d 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ render(, mountNode); | allowEmpty | [Boolean, Boolean] | | allow range picker clearing text | | selectable | [Boolean, Boolean] | | whether to selected picker | | disabled | Boolean | false | whether the range picker is disabled | -| onSelect | Function(value: moment, formatString: string, info: 'start' | 'end') | a callback function for when a start or end date is selected | +| onSelect | Function(value: moment, formatString: string, info: 'start'\|'end') | a callback function for when a start or end date is selected | | onChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the selected time is changing | | onCalendarChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the start time or the end time of the range is changing | | direction | String: ltr or rtl | | Layout direction of picker component, it supports RTL direction too. | From b28baee21a13ffbf58f9ec3cd09896e5338668c0 Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Fri, 26 Jun 2020 10:59:54 +0100 Subject: [PATCH 3/7] Fix incorrect markdown separation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb316b57d..945d04806 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ render(, mountNode); | allowEmpty | [Boolean, Boolean] | | allow range picker clearing text | | selectable | [Boolean, Boolean] | | whether to selected picker | | disabled | Boolean | false | whether the range picker is disabled | -| onSelect | Function(value: moment, formatString: string, info: 'start'\|'end') | a callback function for when a start or end date is selected | +| onSelect | Function(value: moment, formatString: string, info: 'start' \| 'end') | | a callback function for when a start or end date is selected | | onChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the selected time is changing | | onCalendarChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the start time or the end time of the range is changing | | direction | String: ltr or rtl | | Layout direction of picker component, it supports RTL direction too. | From e4d2f196e0046079c96ff9de990c1159f5290a6a Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Tue, 7 Jul 2020 18:47:50 +0100 Subject: [PATCH 4/7] Update onCalendarChange parameters instead of adding onSelect callback. --- README.md | 3 +-- src/RangePicker.tsx | 28 +++++++++++++++------------- tests/range.spec.tsx | 35 +++++++++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 945d04806..41dd2f619 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,8 @@ render(, mountNode); | allowEmpty | [Boolean, Boolean] | | allow range picker clearing text | | selectable | [Boolean, Boolean] | | whether to selected picker | | disabled | Boolean | false | whether the range picker is disabled | -| onSelect | Function(value: moment, formatString: string, info: 'start' \| 'end') | | a callback function for when a start or end date is selected | | onChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the selected time is changing | -| onCalendarChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the start time or the end time of the range is changing | +| onCalendarChange | Function(value:[moment], formatString: [string, string], info: 'start'\|'end'\|'none') | | a callback function, can be executed when the start time or the end time of the range is changing | | direction | String: ltr or rtl | | Layout direction of picker component, it supports RTL direction too. | | order | Boolean | true | (TimeRangePicker only) `false` to disable auto order | diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index e5b53c4cb..8753c854d 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -85,9 +85,12 @@ export interface RangePickerSharedProps { separator?: React.ReactNode; allowEmpty?: [boolean, boolean]; mode?: [PanelMode, PanelMode]; - onSelect?: (value: DateType, formatString: string, info: 'start' | 'end') => void; onChange?: (values: RangeValue, formatString: [string, string]) => void; - onCalendarChange?: (values: RangeValue, formatString: [string, string]) => void; + onCalendarChange?: ( + values: RangeValue, + formatString: [string, string], + info: 'start' | 'end' | 'none', + ) => void; onPanelChange?: (values: RangeValue, modes: [PanelMode, PanelMode]) => void; onFocus?: React.FocusEventHandler; onBlur?: React.FocusEventHandler; @@ -191,7 +194,6 @@ function InnerRangePicker(props: RangePickerProps) { inputReadOnly, mode, renderExtraFooter, - onSelect, onChange, onOpenChange, onPanelChange, @@ -428,18 +430,18 @@ function InnerRangePicker(props: RangePickerProps) { ? generateConfig.locale.format(locale.locale, values[1], formatList[0]) : ''; - if (onSelect) { - if (!isEqual(generateConfig, getValue(mergedValue, 0), startValue)) { - onSelect(startValue, startStr, 'start'); + if (onCalendarChange) { + const startChanged = !isEqual(generateConfig, getValue(selectedValue, 0), startValue); + const endChanged = !isEqual(generateConfig, getValue(selectedValue, 1), endValue); + let info = 'none'; + + if (startChanged) { + info = 'start'; + } else if (endChanged) { + info = 'end'; } - if (!isEqual(generateConfig, getValue(mergedValue, 1), endValue)) { - onSelect(endValue, endStr, 'end'); - } - } - - if (onCalendarChange) { - onCalendarChange(values, [startStr, endStr]); + onCalendarChange(values, [startStr, endStr], info); } // >>>>> Trigger `onChange` event diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx index ac3d62b4d..50cdf3394 100644 --- a/tests/range.spec.tsx +++ b/tests/range.spec.tsx @@ -840,14 +840,29 @@ describe('Picker.Range', () => { // Not trigger when not value expect(wrapper.find('.rc-picker-ok button').props().disabled).toBeTruthy(); + expect(onCalendarChange).not.toHaveBeenCalled(); - // Trigger when valued + // Trigger when start Ok'd onCalendarChange.mockReset(); wrapper.selectCell(11); + expect(onCalendarChange).not.toHaveBeenCalled(); wrapper.find('.rc-picker-ok button').simulate('click'); expect(onCalendarChange).toHaveBeenCalledWith( [expect.anything(), null], ['1990-09-11 00:00:00', ''], + 'none', + ); + expect(onOk).toHaveBeenCalled(); + + // Trigger when end Ok'd + onCalendarChange.mockReset(); + wrapper.selectCell(23); + expect(onCalendarChange).not.toHaveBeenCalled(); + wrapper.find('.rc-picker-ok button').simulate('click'); + expect(onCalendarChange).toHaveBeenCalledWith( + [expect.anything(), expect.anything()], + ['1990-09-11 00:00:00', '1990-09-23 00:00:00'], + 'none', ); expect(onOk).toHaveBeenCalled(); }); @@ -1347,20 +1362,28 @@ describe('Picker.Range', () => { }); describe('Selection callbacks', () => { - it('selection triggers onSelect callback', () => { - const onSelect = jest.fn(); + it('selection provide info for onCalendarChange', () => { + const onCalendarChange = jest.fn(); - const wrapper = mount(); + const wrapper = mount(); wrapper.openPicker(); // Start date wrapper.selectCell(11); - expect(onSelect).toHaveBeenCalledWith(expect.anything(), '1990-09-11', 'start'); + expect(onCalendarChange).toHaveBeenCalledWith( + [expect.anything(), null], + ['1990-09-11', ''], + 'start', + ); // End date wrapper.selectCell(23); - expect(onSelect).toHaveBeenCalledWith(expect.anything(), '1990-09-23', 'end'); + expect(onCalendarChange).toHaveBeenCalledWith( + [expect.anything(), expect.anything()], + ['1990-09-11', '1990-09-23'], + 'end', + ); }); }); }); From f23332d4a8e36e73ba003f25afba5138d492be24 Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Tue, 7 Jul 2020 18:47:50 +0100 Subject: [PATCH 5/7] Update onCalendarChange parameters instead of adding onSelect callback. --- README.md | 3 +-- src/RangePicker.tsx | 28 +++++++++++++++------------- tests/range.spec.tsx | 35 +++++++++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 945d04806..41dd2f619 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,8 @@ render(, mountNode); | allowEmpty | [Boolean, Boolean] | | allow range picker clearing text | | selectable | [Boolean, Boolean] | | whether to selected picker | | disabled | Boolean | false | whether the range picker is disabled | -| onSelect | Function(value: moment, formatString: string, info: 'start' \| 'end') | | a callback function for when a start or end date is selected | | onChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the selected time is changing | -| onCalendarChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the start time or the end time of the range is changing | +| onCalendarChange | Function(value:[moment], formatString: [string, string], info: 'start'\|'end'\|'none') | | a callback function, can be executed when the start time or the end time of the range is changing | | direction | String: ltr or rtl | | Layout direction of picker component, it supports RTL direction too. | | order | Boolean | true | (TimeRangePicker only) `false` to disable auto order | diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index 639921dd9..03cecd5fa 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -85,9 +85,12 @@ export interface RangePickerSharedProps { separator?: React.ReactNode; allowEmpty?: [boolean, boolean]; mode?: [PanelMode, PanelMode]; - onSelect?: (value: DateType, formatString: string, info: 'start' | 'end') => void; onChange?: (values: RangeValue, formatString: [string, string]) => void; - onCalendarChange?: (values: RangeValue, formatString: [string, string]) => void; + onCalendarChange?: ( + values: RangeValue, + formatString: [string, string], + info: 'start' | 'end' | 'none', + ) => void; onPanelChange?: (values: RangeValue, modes: [PanelMode, PanelMode]) => void; onFocus?: React.FocusEventHandler; onBlur?: React.FocusEventHandler; @@ -193,7 +196,6 @@ function InnerRangePicker(props: RangePickerProps) { inputReadOnly, mode, renderExtraFooter, - onSelect, onChange, onOpenChange, onPanelChange, @@ -437,18 +439,18 @@ function InnerRangePicker(props: RangePickerProps) { ? generateConfig.locale.format(locale.locale, values[1], formatList[0]) : ''; - if (onSelect) { - if (!isEqual(generateConfig, getValue(mergedValue, 0), startValue)) { - onSelect(startValue, startStr, 'start'); + if (onCalendarChange) { + const startChanged = !isEqual(generateConfig, getValue(selectedValue, 0), startValue); + const endChanged = !isEqual(generateConfig, getValue(selectedValue, 1), endValue); + let info = 'none'; + + if (startChanged) { + info = 'start'; + } else if (endChanged) { + info = 'end'; } - if (!isEqual(generateConfig, getValue(mergedValue, 1), endValue)) { - onSelect(endValue, endStr, 'end'); - } - } - - if (onCalendarChange) { - onCalendarChange(values, [startStr, endStr]); + onCalendarChange(values, [startStr, endStr], info); } // >>>>> Trigger `onChange` event diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx index 5fe58dc98..31b2a37aa 100644 --- a/tests/range.spec.tsx +++ b/tests/range.spec.tsx @@ -843,14 +843,29 @@ describe('Picker.Range', () => { // Not trigger when not value expect(wrapper.find('.rc-picker-ok button').props().disabled).toBeTruthy(); + expect(onCalendarChange).not.toHaveBeenCalled(); - // Trigger when valued + // Trigger when start Ok'd onCalendarChange.mockReset(); wrapper.selectCell(11); + expect(onCalendarChange).not.toHaveBeenCalled(); wrapper.find('.rc-picker-ok button').simulate('click'); expect(onCalendarChange).toHaveBeenCalledWith( [expect.anything(), null], ['1990-09-11 00:00:00', ''], + 'none', + ); + expect(onOk).toHaveBeenCalled(); + + // Trigger when end Ok'd + onCalendarChange.mockReset(); + wrapper.selectCell(23); + expect(onCalendarChange).not.toHaveBeenCalled(); + wrapper.find('.rc-picker-ok button').simulate('click'); + expect(onCalendarChange).toHaveBeenCalledWith( + [expect.anything(), expect.anything()], + ['1990-09-11 00:00:00', '1990-09-23 00:00:00'], + 'none', ); expect(onOk).toHaveBeenCalled(); }); @@ -1389,20 +1404,28 @@ describe('Picker.Range', () => { }); describe('Selection callbacks', () => { - it('selection triggers onSelect callback', () => { - const onSelect = jest.fn(); + it('selection provide info for onCalendarChange', () => { + const onCalendarChange = jest.fn(); - const wrapper = mount(); + const wrapper = mount(); wrapper.openPicker(); // Start date wrapper.selectCell(11); - expect(onSelect).toHaveBeenCalledWith(expect.anything(), '1990-09-11', 'start'); + expect(onCalendarChange).toHaveBeenCalledWith( + [expect.anything(), null], + ['1990-09-11', ''], + 'start', + ); // End date wrapper.selectCell(23); - expect(onSelect).toHaveBeenCalledWith(expect.anything(), '1990-09-23', 'end'); + expect(onCalendarChange).toHaveBeenCalledWith( + [expect.anything(), expect.anything()], + ['1990-09-11', '1990-09-23'], + 'end', + ); }); }); }); From 64bc8ecbc4775dbd8b5bd5d23429921ced10304d Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Tue, 7 Jul 2020 18:58:21 +0100 Subject: [PATCH 6/7] Fix type of info --- src/RangePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index 03cecd5fa..906520236 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -442,7 +442,7 @@ function InnerRangePicker(props: RangePickerProps) { if (onCalendarChange) { const startChanged = !isEqual(generateConfig, getValue(selectedValue, 0), startValue); const endChanged = !isEqual(generateConfig, getValue(selectedValue, 1), endValue); - let info = 'none'; + let info: 'start' | 'end' | 'none' = 'none'; if (startChanged) { info = 'start'; From d6e24654121b163ad95a6b3c7ddd745bfa6a24c5 Mon Sep 17 00:00:00 2001 From: Kim-Wing-Fung Date: Wed, 8 Jul 2020 08:39:25 +0100 Subject: [PATCH 7/7] Refactor info type and simplify change logic --- README.md | 2 +- src/RangePicker.tsx | 24 ++++++++++-------------- tests/range.spec.tsx | 14 ++++++-------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 41dd2f619..6a071668d 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ render(, mountNode); | selectable | [Boolean, Boolean] | | whether to selected picker | | disabled | Boolean | false | whether the range picker is disabled | | onChange | Function(value:[moment], formatString: [string, string]) | | a callback function, can be executed when the selected time is changing | -| onCalendarChange | Function(value:[moment], formatString: [string, string], info: 'start'\|'end'\|'none') | | a callback function, can be executed when the start time or the end time of the range is changing | +| onCalendarChange | Function(value:[moment], formatString: [string, string], info: { range:'start'\|'end' }) | | a callback function, can be executed when the start time or the end time of the range is changing | | direction | String: ltr or rtl | | Layout direction of picker component, it supports RTL direction too. | | order | Boolean | true | (TimeRangePicker only) `false` to disable auto order | diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index 906520236..3b232da18 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -62,12 +62,16 @@ function canValueTrigger( return false; } +export type RangeType = 'start' | 'end'; + +export interface RangeInfo { + range: RangeType; +} + export type RangeDateRender = ( currentDate: DateType, today: DateType, - info: { - range: 'start' | 'end'; - }, + info: RangeInfo, ) => React.ReactNode; export interface RangePickerSharedProps { @@ -77,7 +81,7 @@ export interface RangePickerSharedProps { defaultPickerValue?: [DateType, DateType]; placeholder?: [string, string]; disabled?: boolean | [boolean, boolean]; - disabledTime?: (date: EventValue, type: 'start' | 'end') => DisabledTimes; + disabledTime?: (date: EventValue, type: RangeType) => DisabledTimes; ranges?: Record< string, Exclude, null> | (() => Exclude, null>) @@ -89,7 +93,7 @@ export interface RangePickerSharedProps { onCalendarChange?: ( values: RangeValue, formatString: [string, string], - info: 'start' | 'end' | 'none', + info: RangeInfo, ) => void; onPanelChange?: (values: RangeValue, modes: [PanelMode, PanelMode]) => void; onFocus?: React.FocusEventHandler; @@ -440,15 +444,7 @@ function InnerRangePicker(props: RangePickerProps) { : ''; if (onCalendarChange) { - const startChanged = !isEqual(generateConfig, getValue(selectedValue, 0), startValue); - const endChanged = !isEqual(generateConfig, getValue(selectedValue, 1), endValue); - let info: 'start' | 'end' | 'none' = 'none'; - - if (startChanged) { - info = 'start'; - } else if (endChanged) { - info = 'end'; - } + const info: RangeInfo = { range: sourceIndex === 0 ? 'start' : 'end' }; onCalendarChange(values, [startStr, endStr], info); } diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx index 31b2a37aa..78919ce47 100644 --- a/tests/range.spec.tsx +++ b/tests/range.spec.tsx @@ -853,7 +853,7 @@ describe('Picker.Range', () => { expect(onCalendarChange).toHaveBeenCalledWith( [expect.anything(), null], ['1990-09-11 00:00:00', ''], - 'none', + { range: 'start' }, ); expect(onOk).toHaveBeenCalled(); @@ -865,7 +865,7 @@ describe('Picker.Range', () => { expect(onCalendarChange).toHaveBeenCalledWith( [expect.anything(), expect.anything()], ['1990-09-11 00:00:00', '1990-09-23 00:00:00'], - 'none', + { range: 'end' }, ); expect(onOk).toHaveBeenCalled(); }); @@ -1413,18 +1413,16 @@ describe('Picker.Range', () => { // Start date wrapper.selectCell(11); - expect(onCalendarChange).toHaveBeenCalledWith( - [expect.anything(), null], - ['1990-09-11', ''], - 'start', - ); + expect(onCalendarChange).toHaveBeenCalledWith([expect.anything(), null], ['1990-09-11', ''], { + range: 'start', + }); // End date wrapper.selectCell(23); expect(onCalendarChange).toHaveBeenCalledWith( [expect.anything(), expect.anything()], ['1990-09-11', '1990-09-23'], - 'end', + { range: 'end' }, ); }); });