Skip to content

Commit e5483d8

Browse files
authored
fix: defaultOpenValue merged to pickerValue (#720)
* chore: update defaultOpenValue warning * chore: part of it * fix: OK click
1 parent f09409a commit e5483d8

File tree

8 files changed

+127
-88
lines changed

8 files changed

+127
-88
lines changed

docs/examples/debug.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export default () => {
128128
const singleRef = React.useRef<PickerRef>(null);
129129

130130
const [value, setValue] = React.useState<Dayjs>(null);
131-
const [rangeValue, setRangeValue] = React.useState<[Dayjs?, Dayjs?]>(
131+
const [rangeValue, setRangeValue] = React.useState<[Dayjs, Dayjs]>(
132132
// [dayjs('2000-12-15'), dayjs('2020-12-22')],
133133
// null,
134134
undefined,
@@ -149,24 +149,27 @@ export default () => {
149149
<SinglePicker
150150
// Shared
151151
{...sharedLocale}
152-
// picker="week"
153152
// multiple
154-
format="YYYY-MM-DD"
155-
showTime
153+
// format="YYYY-MM-DD"
154+
// showTime={{
155+
// defaultValue: dayjs('2000-01-01 03:05:08'),
156+
// }}
156157
// autoFocus
157-
defaultValue={[
158-
dayjs(),
159-
// dayjs('2000-01-01'),
160-
// dayjs('2000-01-03'),
161-
// dayjs('2000-01-05'),
162-
// dayjs('2000-01-07'),
163-
// dayjs('2000-01-09'),
164-
]}
158+
// defaultValue={[
159+
// dayjs(),
160+
// // dayjs('2000-01-01'),
161+
// // dayjs('2000-01-03'),
162+
// // dayjs('2000-01-05'),
163+
// // dayjs('2000-01-07'),
164+
// // dayjs('2000-01-09'),
165+
// ]}
165166
// disabledDate={(date) => date.date() >= 5}
166-
getPopupContainer={(node) => {
167-
console.log('Popup!', node);
168-
return node.parentElement!;
169-
}}
167+
// getPopupContainer={(node) => {
168+
// console.log('Popup!', node);
169+
// return node.parentElement!;
170+
// }}
171+
picker="time"
172+
defaultPickerValue={dayjs('2000-01-01 03:05:08')}
170173
presets={[
171174
{
172175
label: 'Good',
@@ -193,7 +196,7 @@ export default () => {
193196
}}
194197
/>
195198
<br />
196-
<RangePicker
199+
{/* <RangePicker
197200
{...sharedLocale}
198201
value={rangeValue}
199202
separator="~~~~~"
@@ -235,7 +238,7 @@ export default () => {
235238
start: 'inputStart',
236239
end: 'inputEnd',
237240
}}
238-
/>
241+
/> */}
239242
<br />
240243

241244
<button

src/PickerInput/Popup/Footer.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ export interface FooterProps<DateType extends object = any> {
2828
onSubmit: (date?: DateType) => void;
2929
needConfirm: boolean;
3030

31-
// OK
32-
onOk: VoidFunction;
33-
3431
// Now
3532
onNow: (now: DateType) => void;
3633
}
@@ -43,7 +40,6 @@ export default function Footer(props: FooterProps) {
4340
showNow,
4441
showTime,
4542
onSubmit,
46-
onOk,
4743
onNow,
4844
invalid,
4945
needConfirm,
@@ -91,13 +87,7 @@ export default function Footer(props: FooterProps) {
9187
// >>> OK
9288
const okNode = needConfirm && (
9389
<li className={`${prefixCls}-ok`}>
94-
<Button
95-
disabled={invalid}
96-
onClick={() => {
97-
onOk();
98-
onSubmit();
99-
}}
100-
>
90+
<Button disabled={invalid} onClick={onSubmit}>
10191
{locale.ok}
10292
</Button>
10393
</li>

src/PickerInput/Popup/index.tsx

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface PopupProps<DateType extends object = any, PresetValue = DateTyp
2828
// Change
2929
needConfirm: boolean;
3030
isInvalid: (date: DateType | DateType[]) => boolean;
31+
onOk: VoidFunction;
3132
}
3233

3334
export default function Popup<DateType extends object = any>(props: PopupProps<DateType>) {
@@ -56,7 +57,11 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
5657

5758
// Change
5859
value,
60+
onSelect,
5961
isInvalid,
62+
pickerValue,
63+
onOk,
64+
onSubmit,
6065
} = props;
6166

6267
const { prefixCls } = React.useContext(PickerContext);
@@ -90,16 +95,40 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
9095
}, [containerWidth, activeOffset, range]);
9196

9297
// ======================== Custom ========================
93-
const disableSubmit = React.useMemo(() => {
94-
const valueList = toArray(value).filter((val) => val);
98+
function filterEmpty<T>(list: T[]) {
99+
return list.filter((item) => item);
100+
}
101+
102+
const valueList = React.useMemo(() => filterEmpty(toArray(value)), [value]);
103+
104+
const isTimePicker = picker === 'time';
105+
const isEmptyValue = !valueList.length;
106+
107+
const footerSubmitValue = React.useMemo(() => {
108+
if (isTimePicker && isEmptyValue) {
109+
return filterEmpty([pickerValue]);
110+
}
111+
return valueList;
112+
}, [isTimePicker, valueList, isEmptyValue, pickerValue]);
95113

114+
const disableSubmit = React.useMemo(() => {
96115
// Empty is invalid
97-
if (!valueList.length) {
116+
if (!footerSubmitValue.length) {
98117
return true;
99118
}
100119

101-
return valueList.some((val) => isInvalid(val));
102-
}, [value, isInvalid]);
120+
return footerSubmitValue.some((val) => isInvalid(val));
121+
}, [footerSubmitValue, isInvalid]);
122+
123+
const onFooterSubmit = () => {
124+
// For TimePicker, we will additional trigger the value update
125+
if (isTimePicker && isEmptyValue) {
126+
onSelect(pickerValue);
127+
}
128+
129+
onOk();
130+
onSubmit();
131+
};
103132

104133
let mergedNodes: React.ReactNode = (
105134
<div className={`${prefixCls}-panel-layout`}>
@@ -112,7 +141,12 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
112141
/>
113142
<div>
114143
<PopupPanel {...props} />
115-
<Footer {...props} showNow={multiple ? false : showNow} invalid={disableSubmit} />
144+
<Footer
145+
{...props}
146+
showNow={multiple ? false : showNow}
147+
invalid={disableSubmit}
148+
onSubmit={onFooterSubmit}
149+
/>
116150
</div>
117151
</div>
118152
);

src/PickerInput/RangePicker.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ export interface BaseRangePickerProps<DateType extends object>
7979
*
8080
* Note: `defaultPickerValue` priority is higher than `value` for the first open.
8181
*/
82-
defaultPickerValue?: [DateType, DateType] | null;
82+
defaultPickerValue?: [DateType, DateType] | DateType | null;
8383
/**
8484
* Config each start & end field popup panel date.
8585
* When config `pickerValue`, you must also provide `onPickerValueChange` to handle changes.
8686
*/
87-
pickerValue?: [DateType, DateType] | null;
87+
pickerValue?: [DateType, DateType] | DateType | null;
8888
/**
8989
* Each popup panel `pickerValue` includes `mode` change will trigger the callback.
9090
* @param date The changed picker value

src/PickerInput/hooks/useFilledProps.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { warning } from 'rc-util';
22
import * as React from 'react';
3-
import { toArray } from '../../utils/miscUtil';
43
import { fillLocale } from '../../hooks/useLocale';
54
import { getTimeConfig } from '../../hooks/useTimeConfig';
65
import type { FormatType, InternalMode } from '../../interface';
6+
import { toArray } from '../../utils/miscUtil';
77
import type { RangePickerProps } from '../RangePicker';
88
import { fillClearIcon } from '../Selector/hooks/useClearIcon';
99
import useDisabledBoundary from './useDisabledBoundary';
@@ -32,6 +32,7 @@ type PickedProps<DateType extends object = any> = Pick<
3232
| 'disabledDate'
3333
| 'minDate'
3434
| 'maxDate'
35+
| 'defaultOpenValue'
3536
> & {
3637
multiple?: boolean;
3738
// RangePicker showTime definition is different with Picker
@@ -48,8 +49,16 @@ type GetGeneric<T> = T extends PickedProps<infer U> ? U : never;
4849

4950
type ToArrayType<T, DateType> = T extends any[] ? T : DateType[];
5051

51-
function useList<T>(value: T | T[]) {
52-
const values = React.useMemo(() => (value ? toArray(value) : value), [value]);
52+
function useList<T>(value: T | T[], fillMode = false) {
53+
const values = React.useMemo(() => {
54+
const list = value ? toArray(value) : value;
55+
56+
if (fillMode && list) {
57+
list[1] = list[1] || list[0];
58+
}
59+
60+
return list;
61+
}, [value, fillMode]);
5362
return values;
5463
}
5564

@@ -105,25 +114,32 @@ export default function useFilledProps<
105114
defaultValue,
106115
pickerValue,
107116
defaultPickerValue,
117+
defaultOpenValue,
108118
} = props;
109119

110120
const values = useList(value);
111121
const defaultValues = useList(defaultValue);
122+
const defaultOpenValues = useList(defaultOpenValue, true);
112123
const pickerValues = useList(pickerValue);
113-
const defaultPickerValues = useList(defaultPickerValue);
124+
const defaultPickerValues = useList(defaultPickerValue) || defaultOpenValues;
114125

115126
const mergedLocale = fillLocale(locale);
116127
const mergedShowTime = getTimeConfig(props);
117128

118129
// ======================= Warning ========================
119-
if (
120-
process.env.NODE_ENV !== 'production' &&
121-
picker === 'time' &&
122-
['disabledHours', 'disabledMinutes', 'disabledSeconds'].some((key) => (props as any)[key])
123-
) {
130+
if (process.env.NODE_ENV !== 'production' && picker === 'time') {
131+
if (
132+
['disabledHours', 'disabledMinutes', 'disabledSeconds'].some((key) => (props as any)[key])
133+
) {
134+
warning(
135+
false,
136+
`'disabledHours', 'disabledMinutes', 'disabledSeconds' will be removed in the next major version, please use 'disabledTime' instead.`,
137+
);
138+
}
139+
124140
warning(
125-
false,
126-
`'disabledHours', 'disabledMinutes', 'disabledSeconds' will be removed in the next major version, please use 'disabledTime' instead.`,
141+
!defaultOpenValue,
142+
`'defaultOpenValue' is deprecated which merged into 'defaultPickerValue' instead.`,
127143
);
128144
}
129145

src/PickerInput/hooks/useRangePickerValue.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,21 @@ export default function useRangePickerValue<DateType extends object, ValueType e
7676
});
7777

7878
// Current PickerValue
79-
const currentPickerValue = React.useMemo(
80-
() =>
81-
// Merge the `showTime.defaultValue` into `pickerValue`
82-
fillTime(
83-
generateConfig,
84-
[mergedStartPickerValue, mergedEndPickerValue][mergedActiveIndex],
85-
timeDefaultValue[mergedActiveIndex],
86-
),
87-
[
88-
mergedStartPickerValue,
89-
mergedEndPickerValue,
90-
mergedActiveIndex,
91-
generateConfig,
92-
timeDefaultValue,
93-
],
94-
);
79+
const currentPickerValue = React.useMemo(() => {
80+
const current = [mergedStartPickerValue, mergedEndPickerValue][mergedActiveIndex];
81+
82+
// Merge the `showTime.defaultValue` into `pickerValue`
83+
return pickerMode === 'time'
84+
? current
85+
: fillTime(generateConfig, current, timeDefaultValue[mergedActiveIndex]);
86+
}, [
87+
pickerMode,
88+
mergedStartPickerValue,
89+
mergedEndPickerValue,
90+
mergedActiveIndex,
91+
generateConfig,
92+
timeDefaultValue,
93+
]);
9594

9695
const setCurrentPickerValue = (
9796
nextPickerValue: DateType,

src/interface.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ export interface SharedPickerProps<DateType extends object = any>
368368
maxDate?: DateType;
369369

370370
// Open
371+
/** @deprecated Please use `defaultPickerValue` instead */
372+
defaultOpenValue?: DateType;
371373
defaultOpen?: boolean;
372374
open?: boolean;
373375
onOpenChange?: (open: boolean) => void;

tests/picker.spec.tsx

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -777,11 +777,9 @@ describe('Picker.Basic', () => {
777777

778778
it('not open when disabled', () => {
779779
const { rerender } = render(<DayPicker disabled />);
780-
// document.querySelector('.rc-picker').simulate('click');
781780
fireEvent.click(document.querySelector('.rc-picker'));
782781
expect(isOpen()).toBeFalsy();
783782

784-
// wrapper.setProps({ disabled: false });
785783
rerender(<DayPicker disabled={false} />);
786784
expect(isOpen()).toBeFalsy();
787785
});
@@ -791,38 +789,35 @@ describe('Picker.Basic', () => {
791789
const inputElement = document.querySelector('input');
792790
inputElement.focus = jest.fn();
793791

794-
// document.querySelector('.rc-picker').simulate('mouseup');
795792
fireEvent.mouseUp(document.querySelector('.rc-picker'));
796793
expect(inputElement.focus).toHaveBeenCalledTimes(0);
797794
expect(isOpen()).toBeFalsy();
798795
});
799796

800-
// Removed `defaultOpenValue`
801-
// it('defaultOpenValue in timePicker', () => {
802-
// resetWarned();
803-
// const onChange = jest.fn();
804-
// const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
797+
it('defaultOpenValue in timePicker', () => {
798+
resetWarned();
799+
const onChange = jest.fn();
800+
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
805801

806-
// const { container } = render(
807-
// <DayPicker
808-
// picker="time"
809-
// defaultOpenValue={getDay('2000-01-01 00:10:23')}
810-
// onChange={onChange}
811-
// />,
812-
// );
802+
const { container } = render(
803+
<DayPicker
804+
picker="time"
805+
defaultOpenValue={getDay('2000-01-01 00:10:23')}
806+
onChange={onChange}
807+
/>,
808+
);
813809

814-
// expect(errSpy).toHaveBeenCalledWith(
815-
// 'Warning: `defaultOpenValue` may confuse user for the current value status. Please use `defaultValue` instead.',
816-
// );
810+
expect(errSpy).toHaveBeenCalledWith(
811+
"Warning: 'defaultOpenValue' is deprecated which merged into 'defaultPickerValue' instead.",
812+
);
817813

818-
// openPicker(container);
819-
// // document.querySelector('.rc-picker-ok button').simulate('click');
820-
// fireEvent.click(document.querySelector('.rc-picker-ok button'));
814+
openPicker(container);
815+
fireEvent.click(document.querySelector('.rc-picker-ok button'));
821816

822-
// expect(isSame(onChange.mock.calls[0][0], '2000-01-01 00:10:23')).toBeTruthy();
817+
expect(isSame(onChange.mock.calls[0][0], '2000-01-01 00:10:23')).toBeTruthy();
823818

824-
// errSpy.mockRestore();
825-
// });
819+
errSpy.mockRestore();
820+
});
826821

827822
it('close to reset', () => {
828823
const { container } = render(<DayPicker defaultValue={getDay('2000-01-01')} />);

0 commit comments

Comments
 (0)