Skip to content

Commit

Permalink
fix: onPanelChange with RangePicker is also array value
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Nov 30, 2019
1 parent a058f3c commit 2685b2d
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 8 deletions.
3 changes: 2 additions & 1 deletion src/PickerPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
PanelRefProps,
PickerMode,
DisabledTime,
OnPanelChange,
} from './interface';
import { isEqual } from './utils/dateUtil';
import PanelContext from './PanelContext';
Expand Down Expand Up @@ -55,7 +56,7 @@ export interface PickerPanelSharedProps<DateType> {
// Event
onSelect?: (value: DateType) => void;
onChange?: (value: DateType) => void;
onPanelChange?: (value: DateType, mode: PanelMode) => void;
onPanelChange?: OnPanelChange<DateType>;
onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
}

Expand Down
88 changes: 81 additions & 7 deletions src/RangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import {
DisabledTime,
PickerMode,
PanelMode,
OnPanelChange,
} from './interface';
import { toArray } from './utils/miscUtil';
import RangeContext from './RangeContext';
import { isSameDate } from './utils/dateUtil';
import { getDefaultFormat } from './utils/uiUtil';
import { SharedTimeProps } from './panels/TimePanel';

type RangeValue<DateType> = [DateType | null, DateType | null] | null;
type EventValue<DateType> = DateType | null;
type RangeValue<DateType> = [EventValue<DateType>, EventValue<DateType>] | null;

function canTriggerChange<DateType>(
dates: [DateType | null, DateType | null],
dates: [EventValue<DateType>, EventValue<DateType>],
allowEmpty?: [boolean, boolean],
): boolean {
const passStart = dates[0] || (allowEmpty && allowEmpty[0]);
Expand All @@ -35,7 +37,7 @@ export interface RangePickerSharedProps<DateType> {
defaultPickerValue?: [DateType, DateType];
placeholder?: [string, string];
disabledTime?: (
date: DateType | null,
date: EventValue<DateType>,
type: 'start' | 'end',
) => DisabledTimes;
ranges?: Record<
Expand All @@ -48,13 +50,17 @@ export interface RangePickerSharedProps<DateType> {
selectable?: [boolean, boolean];
mode?: [PanelMode, PanelMode];
onChange?: (
value: RangeValue<DateType>,
values: RangeValue<DateType>,
formatString: [string, string],
) => void;
onCalendarChange?: (
value: RangeValue<DateType>,
values: RangeValue<DateType>,
formatString: [string, string],
) => void;
onPanelChange?: (
values: RangeValue<DateType>,
modes: [PanelMode, PanelMode],
) => void;
onFocus?: React.FocusEventHandler<HTMLInputElement>;
onBlur?: React.FocusEventHandler<HTMLInputElement>;
}
Expand All @@ -64,13 +70,14 @@ type OmitPickerProps<Props> = Omit<
| 'value'
| 'defaultValue'
| 'defaultPickerValue'
| 'onChange'
| 'onSelect'
| 'placeholder'
| 'disabledTime'
| 'showToday'
| 'showTime'
| 'mode'
| 'onChange'
| 'onSelect'
| 'onPanelChange'
>;

export interface RangePickerBaseProps<DateType>
Expand Down Expand Up @@ -135,6 +142,7 @@ function InternalRangePicker<DateType>(
disabled,
onChange,
onCalendarChange,
onPanelChange,
onFocus,
onBlur,
} = props as MergedRangePickerProps<DateType> & {
Expand Down Expand Up @@ -248,6 +256,69 @@ function InternalRangePicker<DateType>(
}
};

// ============================== Mode ==============================

/**
* [Legacy] handle internal `onPanelChange`
*/
const [innerModes, setInnerModes] = React.useState((): [
PanelMode,
PanelMode,
] => {
if (mode) {
return mode;
}
if (picker) {
return [picker, picker];
}
return showTime ? ['datetime', 'datetime'] : ['date', 'date'];
});
const [onStartPanelChange, onEndPanelChange] = React.useMemo<
[OnPanelChange<DateType> | undefined, OnPanelChange<DateType> | undefined]
>(() => {
const onInternalPanelChange = (
newValue: DateType,
newMode: PanelMode,
source: 'start' | 'end',
) => {
const values: [EventValue<DateType>, EventValue<DateType>] = [
...(mergedValue || []),
] as [EventValue<DateType>, EventValue<DateType>];
const modes: [PanelMode, PanelMode] = [...innerModes] as [
PanelMode,
PanelMode,
];

if (source === 'start') {
values[0] = newValue;
modes[0] = newMode;
} else {
values[1] = newValue;
modes[1] = newMode;
}
setInnerModes(modes);

if (onPanelChange) {
onPanelChange(values, modes);
}
};

return [
(newVal: DateType, newMode: PanelMode) => {
onInternalPanelChange(newVal, newMode, 'start');
},
(newVal: DateType, newMode: PanelMode) => {
onInternalPanelChange(newVal, newMode, 'end');
},
];
}, [onPanelChange, mode, picker]);

React.useEffect(() => {
if (mode) {
setInnerModes(mode);
}
}, [mode]);

// ============================= Render =============================
const pickerProps = {
...props,
Expand All @@ -257,6 +328,7 @@ function InternalRangePicker<DateType>(
style: undefined,
placeholder: undefined,
disabledTime: undefined,
onPanelChange: undefined,
};

// Time
Expand Down Expand Up @@ -344,6 +416,7 @@ function InternalRangePicker<DateType>(
onSelect={onStartSelect}
onFocus={onFocus}
onBlur={onBlur}
onPanelChange={onStartPanelChange}
/>
{separator}
<Picker<DateType>
Expand All @@ -362,6 +435,7 @@ function InternalRangePicker<DateType>(
onSelect={onEndSelect}
onFocus={onFocus}
onBlur={onBlur}
onPanelChange={onEndPanelChange}
/>
</div>
</RangeContext.Provider>
Expand Down
5 changes: 5 additions & 0 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,8 @@ export interface DisabledTimes {
}

export type DisabledTime<DateType> = (date: DateType | null) => DisabledTimes;

export type OnPanelChange<DateType> = (
value: DateType,
mode: PanelMode,
) => void;
60 changes: 60 additions & 0 deletions tests/range.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -456,4 +456,64 @@ describe('Range', () => {
wrapper.openPicker(1);
expect(wrapper.find('.rc-picker-month-panel')).toHaveLength(1);
});

describe('onPanelChange is array args', () => {
it('mode', () => {
const onPanelChange = jest.fn();
const wrapper = mount(
<MomentRangePicker
mode={['month', 'year']}
onPanelChange={onPanelChange}
/>,
);

wrapper.openPicker();
wrapper.selectCell('Feb');
expect(isSame(onPanelChange.mock.calls[0][0][0], '1990-02-03'));
expect(onPanelChange.mock.calls[0][1]).toEqual(['date', 'year']);

wrapper.closePicker();
onPanelChange.mockReset();

wrapper.openPicker(1);
wrapper.selectCell(1993, 1);
expect(isSame(onPanelChange.mock.calls[0][0][1], '1993-09-03'));
expect(onPanelChange.mock.calls[0][1]).toEqual(['month', 'month']);
});

it('picker', () => {
const onPanelChange = jest.fn();
const wrapper = mount(
<MomentRangePicker picker="month" onPanelChange={onPanelChange} />,
);

// First go to year panel
wrapper.openPicker();
wrapper.find('.rc-picker-month-panel-year-btn').simulate('click');
expect(isSame(onPanelChange.mock.calls[0][0][0], '1990-09-03'));
expect(onPanelChange.mock.calls[0][1]).toEqual(['year', 'month']);

// First nack to month panel
onPanelChange.mockReset();
wrapper.selectCell(1993);
expect(onPanelChange).toHaveBeenCalled();
expect(isSame(onPanelChange.mock.calls[0][0][0], '1993-09-03'));
expect(onPanelChange.mock.calls[0][1]).toEqual(['month', 'month']);

// Last go to year panel
wrapper.closePicker();
wrapper.openPicker(1);
wrapper
.find('Picker')
.last()
.find('.rc-picker-month-panel-year-btn')
.simulate('click');
onPanelChange.mockReset();

// Last nack to month panel
wrapper.selectCell(1998, 1);
expect(isSame(onPanelChange.mock.calls[0][0][1], '1998-09-03'));
expect(onPanelChange.mock.calls[0][1]).toEqual(['month', 'month']);
});
});
});

1 comment on commit 2685b2d

@vercel
Copy link

@vercel vercel bot commented on 2685b2d Nov 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.