Skip to content

Commit 2685b2d

Browse files
committed
fix: onPanelChange with RangePicker is also array value
1 parent a058f3c commit 2685b2d

File tree

4 files changed

+148
-8
lines changed

4 files changed

+148
-8
lines changed

src/PickerPanel.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
PanelRefProps,
1919
PickerMode,
2020
DisabledTime,
21+
OnPanelChange,
2122
} from './interface';
2223
import { isEqual } from './utils/dateUtil';
2324
import PanelContext from './PanelContext';
@@ -55,7 +56,7 @@ export interface PickerPanelSharedProps<DateType> {
5556
// Event
5657
onSelect?: (value: DateType) => void;
5758
onChange?: (value: DateType) => void;
58-
onPanelChange?: (value: DateType, mode: PanelMode) => void;
59+
onPanelChange?: OnPanelChange<DateType>;
5960
onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
6061
}
6162

src/RangePicker.tsx

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ import {
1111
DisabledTime,
1212
PickerMode,
1313
PanelMode,
14+
OnPanelChange,
1415
} from './interface';
1516
import { toArray } from './utils/miscUtil';
1617
import RangeContext from './RangeContext';
1718
import { isSameDate } from './utils/dateUtil';
1819
import { getDefaultFormat } from './utils/uiUtil';
1920
import { SharedTimeProps } from './panels/TimePanel';
2021

21-
type RangeValue<DateType> = [DateType | null, DateType | null] | null;
22+
type EventValue<DateType> = DateType | null;
23+
type RangeValue<DateType> = [EventValue<DateType>, EventValue<DateType>] | null;
2224

2325
function canTriggerChange<DateType>(
24-
dates: [DateType | null, DateType | null],
26+
dates: [EventValue<DateType>, EventValue<DateType>],
2527
allowEmpty?: [boolean, boolean],
2628
): boolean {
2729
const passStart = dates[0] || (allowEmpty && allowEmpty[0]);
@@ -35,7 +37,7 @@ export interface RangePickerSharedProps<DateType> {
3537
defaultPickerValue?: [DateType, DateType];
3638
placeholder?: [string, string];
3739
disabledTime?: (
38-
date: DateType | null,
40+
date: EventValue<DateType>,
3941
type: 'start' | 'end',
4042
) => DisabledTimes;
4143
ranges?: Record<
@@ -48,13 +50,17 @@ export interface RangePickerSharedProps<DateType> {
4850
selectable?: [boolean, boolean];
4951
mode?: [PanelMode, PanelMode];
5052
onChange?: (
51-
value: RangeValue<DateType>,
53+
values: RangeValue<DateType>,
5254
formatString: [string, string],
5355
) => void;
5456
onCalendarChange?: (
55-
value: RangeValue<DateType>,
57+
values: RangeValue<DateType>,
5658
formatString: [string, string],
5759
) => void;
60+
onPanelChange?: (
61+
values: RangeValue<DateType>,
62+
modes: [PanelMode, PanelMode],
63+
) => void;
5864
onFocus?: React.FocusEventHandler<HTMLInputElement>;
5965
onBlur?: React.FocusEventHandler<HTMLInputElement>;
6066
}
@@ -64,13 +70,14 @@ type OmitPickerProps<Props> = Omit<
6470
| 'value'
6571
| 'defaultValue'
6672
| 'defaultPickerValue'
67-
| 'onChange'
68-
| 'onSelect'
6973
| 'placeholder'
7074
| 'disabledTime'
7175
| 'showToday'
7276
| 'showTime'
7377
| 'mode'
78+
| 'onChange'
79+
| 'onSelect'
80+
| 'onPanelChange'
7481
>;
7582

7683
export interface RangePickerBaseProps<DateType>
@@ -135,6 +142,7 @@ function InternalRangePicker<DateType>(
135142
disabled,
136143
onChange,
137144
onCalendarChange,
145+
onPanelChange,
138146
onFocus,
139147
onBlur,
140148
} = props as MergedRangePickerProps<DateType> & {
@@ -248,6 +256,69 @@ function InternalRangePicker<DateType>(
248256
}
249257
};
250258

259+
// ============================== Mode ==============================
260+
261+
/**
262+
* [Legacy] handle internal `onPanelChange`
263+
*/
264+
const [innerModes, setInnerModes] = React.useState((): [
265+
PanelMode,
266+
PanelMode,
267+
] => {
268+
if (mode) {
269+
return mode;
270+
}
271+
if (picker) {
272+
return [picker, picker];
273+
}
274+
return showTime ? ['datetime', 'datetime'] : ['date', 'date'];
275+
});
276+
const [onStartPanelChange, onEndPanelChange] = React.useMemo<
277+
[OnPanelChange<DateType> | undefined, OnPanelChange<DateType> | undefined]
278+
>(() => {
279+
const onInternalPanelChange = (
280+
newValue: DateType,
281+
newMode: PanelMode,
282+
source: 'start' | 'end',
283+
) => {
284+
const values: [EventValue<DateType>, EventValue<DateType>] = [
285+
...(mergedValue || []),
286+
] as [EventValue<DateType>, EventValue<DateType>];
287+
const modes: [PanelMode, PanelMode] = [...innerModes] as [
288+
PanelMode,
289+
PanelMode,
290+
];
291+
292+
if (source === 'start') {
293+
values[0] = newValue;
294+
modes[0] = newMode;
295+
} else {
296+
values[1] = newValue;
297+
modes[1] = newMode;
298+
}
299+
setInnerModes(modes);
300+
301+
if (onPanelChange) {
302+
onPanelChange(values, modes);
303+
}
304+
};
305+
306+
return [
307+
(newVal: DateType, newMode: PanelMode) => {
308+
onInternalPanelChange(newVal, newMode, 'start');
309+
},
310+
(newVal: DateType, newMode: PanelMode) => {
311+
onInternalPanelChange(newVal, newMode, 'end');
312+
},
313+
];
314+
}, [onPanelChange, mode, picker]);
315+
316+
React.useEffect(() => {
317+
if (mode) {
318+
setInnerModes(mode);
319+
}
320+
}, [mode]);
321+
251322
// ============================= Render =============================
252323
const pickerProps = {
253324
...props,
@@ -257,6 +328,7 @@ function InternalRangePicker<DateType>(
257328
style: undefined,
258329
placeholder: undefined,
259330
disabledTime: undefined,
331+
onPanelChange: undefined,
260332
};
261333

262334
// Time
@@ -344,6 +416,7 @@ function InternalRangePicker<DateType>(
344416
onSelect={onStartSelect}
345417
onFocus={onFocus}
346418
onBlur={onBlur}
419+
onPanelChange={onStartPanelChange}
347420
/>
348421
{separator}
349422
<Picker<DateType>
@@ -362,6 +435,7 @@ function InternalRangePicker<DateType>(
362435
onSelect={onEndSelect}
363436
onFocus={onFocus}
364437
onBlur={onBlur}
438+
onPanelChange={onEndPanelChange}
365439
/>
366440
</div>
367441
</RangeContext.Provider>

src/interface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,8 @@ export interface DisabledTimes {
9292
}
9393

9494
export type DisabledTime<DateType> = (date: DateType | null) => DisabledTimes;
95+
96+
export type OnPanelChange<DateType> = (
97+
value: DateType,
98+
mode: PanelMode,
99+
) => void;

tests/range.spec.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,4 +456,64 @@ describe('Range', () => {
456456
wrapper.openPicker(1);
457457
expect(wrapper.find('.rc-picker-month-panel')).toHaveLength(1);
458458
});
459+
460+
describe('onPanelChange is array args', () => {
461+
it('mode', () => {
462+
const onPanelChange = jest.fn();
463+
const wrapper = mount(
464+
<MomentRangePicker
465+
mode={['month', 'year']}
466+
onPanelChange={onPanelChange}
467+
/>,
468+
);
469+
470+
wrapper.openPicker();
471+
wrapper.selectCell('Feb');
472+
expect(isSame(onPanelChange.mock.calls[0][0][0], '1990-02-03'));
473+
expect(onPanelChange.mock.calls[0][1]).toEqual(['date', 'year']);
474+
475+
wrapper.closePicker();
476+
onPanelChange.mockReset();
477+
478+
wrapper.openPicker(1);
479+
wrapper.selectCell(1993, 1);
480+
expect(isSame(onPanelChange.mock.calls[0][0][1], '1993-09-03'));
481+
expect(onPanelChange.mock.calls[0][1]).toEqual(['month', 'month']);
482+
});
483+
484+
it('picker', () => {
485+
const onPanelChange = jest.fn();
486+
const wrapper = mount(
487+
<MomentRangePicker picker="month" onPanelChange={onPanelChange} />,
488+
);
489+
490+
// First go to year panel
491+
wrapper.openPicker();
492+
wrapper.find('.rc-picker-month-panel-year-btn').simulate('click');
493+
expect(isSame(onPanelChange.mock.calls[0][0][0], '1990-09-03'));
494+
expect(onPanelChange.mock.calls[0][1]).toEqual(['year', 'month']);
495+
496+
// First nack to month panel
497+
onPanelChange.mockReset();
498+
wrapper.selectCell(1993);
499+
expect(onPanelChange).toHaveBeenCalled();
500+
expect(isSame(onPanelChange.mock.calls[0][0][0], '1993-09-03'));
501+
expect(onPanelChange.mock.calls[0][1]).toEqual(['month', 'month']);
502+
503+
// Last go to year panel
504+
wrapper.closePicker();
505+
wrapper.openPicker(1);
506+
wrapper
507+
.find('Picker')
508+
.last()
509+
.find('.rc-picker-month-panel-year-btn')
510+
.simulate('click');
511+
onPanelChange.mockReset();
512+
513+
// Last nack to month panel
514+
wrapper.selectCell(1998, 1);
515+
expect(isSame(onPanelChange.mock.calls[0][0][1], '1998-09-03'));
516+
expect(onPanelChange.mock.calls[0][1]).toEqual(['month', 'month']);
517+
});
518+
});
459519
});

0 commit comments

Comments
 (0)