Skip to content

Commit 587a07c

Browse files
authored
refactor(design): refactor DatePicker (#5622)
1 parent 3a59614 commit 587a07c

File tree

26 files changed

+178
-847
lines changed

26 files changed

+178
-847
lines changed

packages/design/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
"dayjs": "^1.11.13",
8484
"rc-dropdown": "^4.2.1",
8585
"rc-menu": "^9.16.0",
86-
"rc-picker": "^4.9.0",
8786
"rc-virtual-list": "^3.16.1",
8887
"react-grid-layout": "^1.5.1",
8988
"react-transition-group": "^4.4.5",

packages/design/src/components/calendar/Calendar.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ function DayButton(props: ButtonHTMLAttributes<HTMLButtonElement>) {
4747

4848
interface ICalendarProps {
4949
className?: string;
50+
showTime?: boolean;
51+
max?: Date;
52+
min?: Date;
5053
value?: Date;
5154
onValueChange?: (date: Date) => void;
52-
showTime?: boolean;
5355
}
5456

5557
export function Calendar(props: ICalendarProps) {
56-
const { className, value, onValueChange, showTime = false } = props;
58+
const { className, max, min, showTime = false, value, onValueChange } = props;
5759

5860
const { locale } = useContext(ConfigContext);
5961

@@ -109,7 +111,19 @@ export function Calendar(props: ICalendarProps) {
109111
return day && currentYear === today.getFullYear() && currentMonth === today.getMonth() && day === today.getDate();
110112
}
111113

114+
function isDisabled(day: number) {
115+
if (!day) return false;
116+
const hours = value?.getHours() ?? today.getHours();
117+
const minutes = value?.getMinutes() ?? today.getMinutes();
118+
const seconds = value?.getSeconds() ?? today.getSeconds();
119+
const d = new Date(currentYear, currentMonth, day, hours, minutes, seconds);
120+
if (min && d < min) return true;
121+
if (max && d > max) return true;
122+
return false;
123+
}
124+
112125
function handleChangeDate(day: number) {
126+
if (isDisabled(day)) return;
113127
const hours = value?.getHours() ?? today.getHours();
114128
const minutes = value?.getMinutes() ?? today.getMinutes();
115129
const seconds = value?.getSeconds() ?? today.getSeconds();
@@ -187,11 +201,13 @@ export function Calendar(props: ICalendarProps) {
187201
key={idx}
188202
className={clsx({
189203
'!univer-bg-primary-600 univer-font-bold univer-text-white': isSelected(day),
190-
'univer-hover:bg-primary-100 univer-cursor-pointer univer-text-gray-800': !isSelected(day),
204+
'univer-hover:bg-primary-100 univer-cursor-pointer univer-text-gray-800': !isSelected(day) && !isDisabled(day),
191205
'dark:!univer-text-white': !isToday(day) && !isSelected(day),
192206
'univer-font-semibold univer-text-primary-600 dark:!univer-text-primary-500': isToday(day),
207+
'univer-cursor-not-allowed univer-opacity-40': isDisabled(day),
193208
})}
194209
onClick={() => handleChangeDate(day)}
210+
disabled={isDisabled(day)}
195211
>
196212
{day}
197213
</DayButton>

packages/design/src/components/date-picker/DatePicker.stories.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616

1717
import type { Meta } from '@storybook/react';
18-
import { dayjs } from '@univerjs/core';
1918
import { useState } from 'react';
2019
import { DatePicker } from './DatePicker';
2120

@@ -32,10 +31,10 @@ export default meta;
3231

3332
export const DatePickerBasic = {
3433
render() {
35-
const [value, setValue] = useState<dayjs.Dayjs>(dayjs());
34+
const [value, setValue] = useState(new Date());
3635

3736
return (
38-
<DatePicker value={value} onChange={setValue} />
37+
<DatePicker value={value} onValueChange={setValue} />
3938
);
4039
},
4140
};

packages/design/src/components/date-picker/DatePicker.tsx

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,70 @@
1414
* limitations under the License.
1515
*/
1616

17-
import type { dayjs } from '@univerjs/core';
18-
import type { PickerProps } from 'rc-picker';
1917
import { CalendarIcon } from '@univerjs/icons';
20-
import RcPicker from 'rc-picker';
21-
import generateConfig from 'rc-picker/lib/generate/dayjs';
22-
import { useContext } from 'react';
23-
import { ConfigContext } from '../config-provider/ConfigProvider';
24-
import './index.css';
25-
26-
/** @deprecated */
27-
export interface IDatePickerProps extends Omit<PickerProps<dayjs.Dayjs>, 'value' | 'onChange' | 'locale' | 'generateConfig' | 'prefixCls'> {
18+
import dayjs from 'dayjs';
19+
import { useState } from 'react';
20+
import { borderClassName } from '../../helper/class-utilities';
21+
import { clsx } from '../../helper/clsx';
22+
import { Calendar } from '../calendar/Calendar';
23+
import { Dropdown } from '../dropdown/Dropdown';
24+
25+
interface IDatePickerProps {
26+
/**
27+
* Additional CSS classes for the date picker.
28+
*/
29+
className?: string;
30+
2831
/**
2932
* The value of the date picker.
3033
*/
31-
value: dayjs.Dayjs;
34+
value?: Date;
3235

3336
/**
3437
* Callback when the value of the date picker changes.
3538
*/
36-
onChange: (date: dayjs.Dayjs, dateString: string) => void;
39+
onValueChange?: (date: Date) => void;
3740
}
3841

39-
/** @deprecated */
4042
export function DatePicker(props: IDatePickerProps) {
41-
const { value, onChange, ...ext } = props;
43+
const { value, onValueChange, className } = props;
4244

43-
const { locale } = useContext(ConfigContext);
45+
const [open, setOpen] = useState(false);
4446

45-
function handleChange(date: dayjs.Dayjs | dayjs.Dayjs[], dateString: string | string[]) {
46-
if (!Array.isArray(date) && !Array.isArray(dateString)) {
47-
onChange(date, dateString);
48-
}
47+
function handleValueChange(date: Date) {
48+
onValueChange?.(date);
49+
setOpen(false);
4950
}
5051

5152
return (
52-
<RcPicker<dayjs.Dayjs>
53-
{...ext}
54-
value={value}
55-
prefixCls="univer-date-picker"
56-
generateConfig={generateConfig}
57-
locale={locale?.Picker!}
58-
suffixIcon={<CalendarIcon className="univer-date-picker-suffix-icon" />}
59-
onChange={handleChange}
60-
/>
53+
<Dropdown
54+
align="start"
55+
overlay={(
56+
<div className="univer-p-2">
57+
<Calendar value={value} onValueChange={handleValueChange} />
58+
</div>
59+
)}
60+
open={open}
61+
onOpenChange={setOpen}
62+
>
63+
<button
64+
className={clsx(`
65+
univer-flex univer-h-8 univer-items-center univer-justify-between univer-gap-2 univer-rounded-md
66+
univer-bg-transparent univer-px-2 univer-text-sm univer-text-gray-800 univer-transition-all
67+
hover:univer-border-primary-600
68+
dark:!univer-text-white
69+
`, borderClassName, className)}
70+
type="button"
71+
>
72+
{dayjs(value).format('YYYY-MM-DD')}
73+
74+
<CalendarIcon
75+
className={`
76+
univer-text-gray-600
77+
dark:!univer-text-gray-400
78+
`}
79+
/>
80+
</button>
81+
</Dropdown>
6182
);
6283
}

0 commit comments

Comments
 (0)