diff --git a/docs/examples/basic.tsx b/docs/examples/basic.tsx
index e1357e44d..6076e2c23 100644
--- a/docs/examples/basic.tsx
+++ b/docs/examples/basic.tsx
@@ -33,6 +33,10 @@ export default () => {
label: 'Hello World!',
value: moment(),
},
+ {
+ label: 'Now',
+ value: () => moment(),
+ }
],
};
diff --git a/docs/examples/range.tsx b/docs/examples/range.tsx
index 3cb68d413..688fd24f5 100644
--- a/docs/examples/range.tsx
+++ b/docs/examples/range.tsx
@@ -62,6 +62,16 @@ export default () => {
defaultValue={[moment('1990-09-03'), moment('1989-11-28')]}
clearIcon={X}
suffixIcon={O}
+ presets={[
+ {
+ label: 'Last week',
+ value: [moment().subtract(1, 'week'), moment()],
+ },
+ {
+ label: 'Last 3 days',
+ value: () => [moment().subtract(3, 'days'), moment().add(3, 'days')],
+ },
+ ]}
/>
{...sharedProps}
diff --git a/src/PresetPanel.tsx b/src/PresetPanel.tsx
index 3459803b8..8665aa837 100644
--- a/src/PresetPanel.tsx
+++ b/src/PresetPanel.tsx
@@ -1,5 +1,6 @@
import * as React from 'react';
import type { PresetDate } from './interface';
+import { executeValue } from './utils/miscUtil';
export interface PresetPanelProps {
prefixCls: string;
@@ -21,20 +22,14 @@ export default function PresetPanel(props: PresetPanelProps) {
{presets.map(({ label, value }, index) => (
{
- onClick(value);
- }}
- onMouseEnter={() => {
- onHover?.(value);
- }}
- onMouseLeave={() => {
- onHover?.(null);
- }}
+ onClick={() => onClick?.(executeValue(value))}
+ onMouseEnter={() => onHover?.(executeValue(value))}
+ onMouseLeave={() => onHover?.(null)}
>
{label}
))}
-
+
);
}
diff --git a/src/hooks/usePresets.ts b/src/hooks/usePresets.ts
index 506ed2f91..cacc08b2a 100644
--- a/src/hooks/usePresets.ts
+++ b/src/hooks/usePresets.ts
@@ -14,17 +14,10 @@ export default function usePresets(
if (legacyRanges) {
warning(false, '`ranges` is deprecated. Please use `presets` instead.');
- const rangeLabels = Object.keys(legacyRanges);
-
- return rangeLabels.map((label) => {
- const range = legacyRanges[label];
- const newValues = typeof range === 'function' ? (range as any)() : range;
-
- return {
- label,
- value: newValues,
- };
- });
+ return Object.entries(legacyRanges).map(([label, value]) => ({
+ label,
+ value,
+ }));
}
return [];
diff --git a/src/interface.ts b/src/interface.ts
index 0e167d655..4d74ff074 100644
--- a/src/interface.ts
+++ b/src/interface.ts
@@ -123,7 +123,7 @@ export type CustomFormat = (value: DateType) => string;
export interface PresetDate {
label: React.ReactNode;
- value: T;
+ value: T | (() => T);
}
// https://stackoverflow.com/a/39495173; need TypeScript >= 4.5
diff --git a/src/utils/miscUtil.ts b/src/utils/miscUtil.ts
index f0f0081bc..68db23632 100644
--- a/src/utils/miscUtil.ts
+++ b/src/utils/miscUtil.ts
@@ -50,3 +50,7 @@ export function updateValues(
return (newValues as unknown) as R;
}
+
+export function executeValue(value: T | (() => T)): T {
+ return typeof value === 'function' ? (value as () => T)() : value;
+}
diff --git a/tests/picker.spec.tsx b/tests/picker.spec.tsx
index fe286df6d..dff905fbb 100644
--- a/tests/picker.spec.tsx
+++ b/tests/picker.spec.tsx
@@ -1030,4 +1030,39 @@ describe('Picker.Basic', () => {
expect(onChange.mock.calls[0][0].format('YYYY-MM-DD')).toEqual('2000-09-03');
});
+
+ it('presets support callback', () => {
+ const onChange = jest.fn();
+ const mockPresetValue = jest.fn().mockImplementationOnce(() => moment('2000-09-03'));
+
+ render(
+ ,
+ );
+
+ const firstPreset = document.querySelector('.rc-picker-presets li');
+ expect(firstPreset.textContent).toBe('Bamboo');
+
+ fireEvent.click(firstPreset);
+
+ expect(mockPresetValue).toHaveBeenCalled();
+ expect(onChange.mock.calls[0][0].format('YYYY-MM-DD')).toEqual('2000-09-03');
+
+ mockPresetValue.mockImplementationOnce(() => moment('2023-05-01 12:34:56'));
+
+ fireEvent.click(firstPreset);
+
+ expect(mockPresetValue).toBeCalledTimes(2);
+ expect(onChange).toBeCalledTimes(2);
+
+ expect(onChange.mock.calls[1][0].format('YYYY-MM-DD HH:mm:ss')).toEqual('2023-05-01 12:34:56');
+ });
});
diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx
index 786adca4f..3ebcb0c44 100644
--- a/tests/range.spec.tsx
+++ b/tests/range.spec.tsx
@@ -1,5 +1,6 @@
import { act, createEvent, fireEvent, render } from '@testing-library/react';
-import moment, { Moment } from 'moment';
+import type { Moment } from 'moment';
+import moment from 'moment';
import KeyCode from 'rc-util/lib/KeyCode';
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
import React from 'react';
@@ -18,6 +19,7 @@ import {
openPicker,
selectCell,
} from './util/commonUtil';
+import type { RangePickerProps } from '../src/RangePicker';
describe('Picker.Range', () => {
function matchValues(container: HTMLElement, value1: string, value2: string) {
@@ -331,15 +333,32 @@ describe('Picker.Range', () => {
});
});
- describe('ranges', () => {
- it('work', () => {
+ function testRangePickerPresetRange(propsType: 'ranges' | 'presets') {
+
+ const genProps = (ranges: Record) => {
+ const props: Partial> = {};
+ if (propsType === 'ranges') {
+ // ranges is deprecated, but the case needs to be retained for a while
+ props.ranges = ranges;
+ } else if (propsType === 'presets') {
+ props.presets = [];
+ Object.entries(ranges).forEach(([label, value]) => {
+ props.presets.push({ label, value });
+ })
+ }
+ return props as RangePickerProps;
+ }
+
+ it(`${propsType} work`, () => {
const onChange = jest.fn();
const { container } = render(
[getMoment('2000-01-01'), getMoment('2010-11-11')],
- }}
+ {...genProps(
+ {
+ test: [getMoment('1989-11-28'), getMoment('1990-09-03')],
+ func: () => [getMoment('2000-01-01'), getMoment('2010-11-11')],
+ }
+ )}
onChange={onChange}
/>,
);
@@ -371,12 +390,14 @@ describe('Picker.Range', () => {
expect(isOpen()).toBeFalsy();
});
- it('hover className', () => {
+ it(`${propsType} hover className`, () => {
const { container } = render(
,
);
@@ -391,6 +412,12 @@ describe('Picker.Range', () => {
expect(findCell(12)).not.toHaveClass('rc-picker-cell-in-range');
expect(findCell(13)).not.toHaveClass('rc-picker-cell-range-end');
});
+
+ }
+
+ describe('ranges or presets', () => {
+ testRangePickerPresetRange('ranges');
+ testRangePickerPresetRange('presets');
});
it('placeholder', () => {