mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-23 13:01:59 +03:00
feat(component): remove react-datepicker (#5681)
This commit is contained in:
parent
8d746f17de
commit
67dffc2a5a
@ -60,7 +60,6 @@
|
||||
"nanoid": "^5.0.3",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "18.2.0",
|
||||
"react-datepicker": "^6.0.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-error-boundary": "^4.0.11",
|
||||
"react-is": "^18.2.0",
|
||||
@ -94,7 +93,6 @@
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@types/bytes": "^3.1.3",
|
||||
"@types/react": "^18.2.28",
|
||||
"@types/react-datepicker": "^6.0.0",
|
||||
"@types/react-dnd": "^3.0.2",
|
||||
"@types/react-dom": "^18.2.13",
|
||||
"@vanilla-extract/css": "^1.13.0",
|
||||
|
@ -1,37 +0,0 @@
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
import dayjs from 'dayjs';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { AFFiNEDatePicker } from '.';
|
||||
|
||||
export default {
|
||||
title: 'UI/Date Picker/AFFiNE Date Picker',
|
||||
} satisfies Meta<typeof AFFiNEDatePicker>;
|
||||
|
||||
const _format = 'YYYY-MM-DD';
|
||||
|
||||
const Template: StoryFn<typeof AFFiNEDatePicker> = args => {
|
||||
const [date, setDate] = useState(dayjs().format(_format));
|
||||
return (
|
||||
<div style={{ minHeight: 400, maxWidth: 600, margin: '0 auto' }}>
|
||||
<div style={{ marginBottom: 20 }}>Selected Date: {date}</div>
|
||||
|
||||
<AFFiNEDatePicker
|
||||
value={date}
|
||||
{...args}
|
||||
onChange={e => {
|
||||
setDate(dayjs(e, _format).format(_format));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof AFFiNEDatePicker> = Template.bind(undefined);
|
||||
Basic.args = {};
|
||||
|
||||
export const Inline: StoryFn<typeof AFFiNEDatePicker> =
|
||||
Template.bind(undefined);
|
||||
Inline.args = {
|
||||
inline: true,
|
||||
};
|
@ -1,274 +0,0 @@
|
||||
import {
|
||||
ArrowDownSmallIcon,
|
||||
ArrowLeftSmallIcon,
|
||||
ArrowRightSmallIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import clsx from 'clsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { type HTMLAttributes, useCallback, useEffect, useState } from 'react';
|
||||
import DatePicker, { type ReactDatePickerProps } from 'react-datepicker';
|
||||
|
||||
import * as styles from './index.css';
|
||||
const months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
];
|
||||
export interface AFFiNEDatePickerProps
|
||||
extends Omit<ReactDatePickerProps, 'onChange' | 'onSelect'> {
|
||||
value?: string;
|
||||
onChange?: (value: string) => void;
|
||||
onSelect?: (value: string) => void;
|
||||
}
|
||||
|
||||
interface HeaderLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
||||
length: number;
|
||||
left: React.ReactNode;
|
||||
right: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `DatePicker` should work with different width
|
||||
* This is a hack to make header's item align with calendar cell's label, **instead of the cell**
|
||||
* @param length: number of items that calendar body row has
|
||||
*/
|
||||
const HeaderLayout = ({
|
||||
length,
|
||||
left,
|
||||
right,
|
||||
className,
|
||||
...attrs
|
||||
}: HeaderLayoutProps) => {
|
||||
return (
|
||||
<div className={clsx(styles.row, className)} {...attrs}>
|
||||
{Array.from({ length })
|
||||
.fill(0)
|
||||
.map((_, index) => {
|
||||
const isLeft = index === 0;
|
||||
const isRight = index === length - 1;
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
data-is-left={isLeft}
|
||||
data-is-right={isRight}
|
||||
className={styles.headerLayoutCell}
|
||||
>
|
||||
<div className={styles.headerLayoutCellOrigin}>
|
||||
{isLeft ? left : isRight ? right : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const AFFiNEDatePicker = ({
|
||||
value,
|
||||
onChange,
|
||||
onSelect,
|
||||
|
||||
calendarClassName,
|
||||
|
||||
...props
|
||||
}: AFFiNEDatePickerProps) => {
|
||||
const [openMonthPicker, setOpenMonthPicker] = useState(false);
|
||||
const [selectedDate, setSelectedDate] = useState<Date | null>(
|
||||
value ? dayjs(value).toDate() : null
|
||||
);
|
||||
const handleOpenMonthPicker = useCallback(() => {
|
||||
setOpenMonthPicker(true);
|
||||
}, []);
|
||||
const handleCloseMonthPicker = useCallback(() => {
|
||||
setOpenMonthPicker(false);
|
||||
}, []);
|
||||
const handleDateChange = (date: Date | null) => {
|
||||
if (date) {
|
||||
setSelectedDate(date);
|
||||
onChange?.(dayjs(date).format('YYYY-MM-DD'));
|
||||
setOpenMonthPicker(false);
|
||||
}
|
||||
};
|
||||
const handleDateSelect = (date: Date | null) => {
|
||||
if (date) {
|
||||
onSelect?.(dayjs(date).format('YYYY-MM-DD'));
|
||||
setOpenMonthPicker(false);
|
||||
}
|
||||
};
|
||||
const renderCustomHeader = ({
|
||||
date,
|
||||
decreaseMonth,
|
||||
increaseMonth,
|
||||
prevMonthButtonDisabled,
|
||||
nextMonthButtonDisabled,
|
||||
}: {
|
||||
date: Date;
|
||||
decreaseMonth: () => void;
|
||||
increaseMonth: () => void;
|
||||
prevMonthButtonDisabled: boolean;
|
||||
nextMonthButtonDisabled: boolean;
|
||||
}) => {
|
||||
const selectedYear = dayjs(date).year();
|
||||
const selectedMonth = dayjs(date).month();
|
||||
return (
|
||||
<HeaderLayout
|
||||
length={7}
|
||||
className={styles.headerStyle}
|
||||
left={
|
||||
<div className={styles.headerLabel}>
|
||||
<div
|
||||
data-testid="date-picker-current-month"
|
||||
className={styles.mouthStyle}
|
||||
>
|
||||
{months[selectedMonth]}
|
||||
</div>
|
||||
<div
|
||||
data-testid="date-picker-current-year"
|
||||
className={styles.yearStyle}
|
||||
>
|
||||
{selectedYear}
|
||||
</div>
|
||||
<div
|
||||
data-testid="month-picker-button"
|
||||
className={styles.arrowDownStyle}
|
||||
onClick={handleOpenMonthPicker}
|
||||
>
|
||||
<ArrowDownSmallIcon />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className={styles.headerActionWrapper}>
|
||||
<button
|
||||
data-testid="date-picker-prev-button"
|
||||
className={styles.headerAction}
|
||||
onClick={decreaseMonth}
|
||||
disabled={prevMonthButtonDisabled}
|
||||
>
|
||||
<ArrowLeftSmallIcon />
|
||||
</button>
|
||||
<button
|
||||
data-testid="date-picker-next-button"
|
||||
className={styles.headerAction}
|
||||
onClick={increaseMonth}
|
||||
disabled={nextMonthButtonDisabled}
|
||||
>
|
||||
<ArrowRightSmallIcon />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderCustomMonthHeader = ({
|
||||
date,
|
||||
decreaseYear,
|
||||
increaseYear,
|
||||
prevYearButtonDisabled,
|
||||
nextYearButtonDisabled,
|
||||
}: {
|
||||
date: Date;
|
||||
decreaseYear: () => void;
|
||||
increaseYear: () => void;
|
||||
prevYearButtonDisabled: boolean;
|
||||
nextYearButtonDisabled: boolean;
|
||||
}) => {
|
||||
const selectedYear = dayjs(date).year();
|
||||
return (
|
||||
<HeaderLayout
|
||||
length={3}
|
||||
className={styles.monthHeaderStyle}
|
||||
left={
|
||||
<div
|
||||
data-testid="month-picker-current-year"
|
||||
className={styles.monthTitleStyle}
|
||||
>
|
||||
{selectedYear}
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className={styles.headerActionWrapper}>
|
||||
<button
|
||||
data-testid="month-picker-prev-button"
|
||||
className={styles.headerAction}
|
||||
onClick={decreaseYear}
|
||||
disabled={prevYearButtonDisabled}
|
||||
>
|
||||
<ArrowLeftSmallIcon />
|
||||
</button>
|
||||
<button
|
||||
data-testid="month-picker-next-button"
|
||||
className={styles.headerAction}
|
||||
onClick={increaseYear}
|
||||
disabled={nextYearButtonDisabled}
|
||||
>
|
||||
<ArrowRightSmallIcon />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedDate(value ? dayjs(value).toDate() : null);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<DatePicker
|
||||
onClickOutside={handleCloseMonthPicker}
|
||||
className={styles.inputStyle}
|
||||
calendarClassName={clsx(styles.calendarStyle, calendarClassName)}
|
||||
weekDayClassName={() => styles.weekStyle}
|
||||
dayClassName={() => styles.dayStyle}
|
||||
popperClassName={styles.popperStyle}
|
||||
monthClassName={() => styles.mouthsStyle}
|
||||
selected={selectedDate}
|
||||
onChange={handleDateChange}
|
||||
onSelect={handleDateSelect}
|
||||
showPopperArrow={false}
|
||||
dateFormat="MMM dd"
|
||||
showMonthYearPicker={openMonthPicker}
|
||||
shouldCloseOnSelect={!openMonthPicker}
|
||||
renderCustomHeader={({
|
||||
date,
|
||||
decreaseYear,
|
||||
increaseYear,
|
||||
decreaseMonth,
|
||||
increaseMonth,
|
||||
prevYearButtonDisabled,
|
||||
nextYearButtonDisabled,
|
||||
prevMonthButtonDisabled,
|
||||
nextMonthButtonDisabled,
|
||||
}) =>
|
||||
openMonthPicker
|
||||
? renderCustomMonthHeader({
|
||||
date,
|
||||
decreaseYear,
|
||||
increaseYear,
|
||||
prevYearButtonDisabled,
|
||||
nextYearButtonDisabled,
|
||||
})
|
||||
: renderCustomHeader({
|
||||
date,
|
||||
decreaseMonth,
|
||||
increaseMonth,
|
||||
prevMonthButtonDisabled,
|
||||
nextMonthButtonDisabled,
|
||||
})
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AFFiNEDatePicker;
|
@ -1,15 +0,0 @@
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
|
||||
import { BlocksuiteDatePicker } from './blocksuite-date-picker';
|
||||
|
||||
export default {
|
||||
title: 'UI/Date Picker/Blocksuite Date Picker',
|
||||
} satisfies Meta<typeof BlocksuiteDatePicker>;
|
||||
|
||||
export const Basic: StoryFn<typeof BlocksuiteDatePicker> = () => {
|
||||
return (
|
||||
<div style={{ width: 300 }}>
|
||||
<BlocksuiteDatePicker />
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { DatePicker } from '@blocksuite/blocks/src/_common/components/date-picker/index';
|
||||
import { createComponent } from '@lit/react';
|
||||
import React from 'react';
|
||||
|
||||
export const BlocksuiteDatePicker = createComponent({
|
||||
tagName: 'date-picker',
|
||||
elementClass: DatePicker,
|
||||
react: React,
|
||||
events: {},
|
||||
});
|
@ -1,3 +1,2 @@
|
||||
export * from './affine-date-picker';
|
||||
export * from './calendar';
|
||||
export * from './week-date-picker';
|
||||
|
@ -1,16 +0,0 @@
|
||||
import { AFFiNEDatePicker } from '@affine/component';
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
|
||||
export default {
|
||||
title: 'AFFiNE/AFFiNEDatePicker',
|
||||
component: AFFiNEDatePicker,
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
},
|
||||
} satisfies Meta<typeof AFFiNEDatePicker>;
|
||||
|
||||
export const Default: StoryFn = () => {
|
||||
const [value, setValue] = useState<string>(new Date().toString());
|
||||
return <AFFiNEDatePicker value={value} onChange={setValue} />;
|
||||
};
|
64
yarn.lock
64
yarn.lock
@ -244,7 +244,6 @@ __metadata:
|
||||
"@toeverything/theme": "npm:^0.7.29"
|
||||
"@types/bytes": "npm:^3.1.3"
|
||||
"@types/react": "npm:^18.2.28"
|
||||
"@types/react-datepicker": "npm:^6.0.0"
|
||||
"@types/react-dnd": "npm:^3.0.2"
|
||||
"@types/react-dom": "npm:^18.2.13"
|
||||
"@vanilla-extract/css": "npm:^1.13.0"
|
||||
@ -265,7 +264,6 @@ __metadata:
|
||||
nanoid: "npm:^5.0.3"
|
||||
next-themes: "npm:^0.2.1"
|
||||
react: "npm:18.2.0"
|
||||
react-datepicker: "npm:^6.0.0"
|
||||
react-dom: "npm:18.2.0"
|
||||
react-error-boundary: "npm:^4.0.11"
|
||||
react-is: "npm:^18.2.0"
|
||||
@ -5305,7 +5303,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.0.8":
|
||||
"@floating-ui/react-dom@npm:^2.0.0":
|
||||
version: 2.0.8
|
||||
resolution: "@floating-ui/react-dom@npm:2.0.8"
|
||||
dependencies:
|
||||
@ -5331,20 +5329,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/react@npm:^0.26.2":
|
||||
version: 0.26.8
|
||||
resolution: "@floating-ui/react@npm:0.26.8"
|
||||
dependencies:
|
||||
"@floating-ui/react-dom": "npm:^2.0.8"
|
||||
"@floating-ui/utils": "npm:^0.2.1"
|
||||
tabbable: "npm:^6.0.1"
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: 10/809af37e13baf67426be5542a8d608b7d9b904b5a386e7e5147da584dc154c3e977c67daefa4a3df1980dee07152a44f4997b8269132b732b62eb5e64b0a9809
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/utils@npm:^0.2.1":
|
||||
version: 0.2.1
|
||||
resolution: "@floating-ui/utils@npm:0.2.1"
|
||||
@ -14110,17 +14094,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-datepicker@npm:^6.0.0":
|
||||
version: 6.0.1
|
||||
resolution: "@types/react-datepicker@npm:6.0.1"
|
||||
dependencies:
|
||||
"@floating-ui/react": "npm:^0.26.2"
|
||||
"@types/react": "npm:*"
|
||||
date-fns: "npm:^3.3.1"
|
||||
checksum: 10/b54432c0dbea42675973365081d40381e7c0a4d006ae2dea6f663a7f99cfca0abfc5490bbe182f999706a7172b156f691629eb09ec566c351554cef63ea38f17
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-dnd@npm:^3.0.2":
|
||||
version: 3.0.2
|
||||
resolution: "@types/react-dnd@npm:3.0.2"
|
||||
@ -17312,13 +17285,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"classnames@npm:^2.2.6":
|
||||
version: 2.3.2
|
||||
resolution: "classnames@npm:2.3.2"
|
||||
checksum: 10/ba3151c12e8b6a84c64b340ab4259ad0408947652009314462d828e94631505989c6a7d7e796bec1d309be9295d3111b498ad18a9d533fe3e6f859e51e574cbb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-css@npm:^5.2.2":
|
||||
version: 5.3.2
|
||||
resolution: "clean-css@npm:5.3.2"
|
||||
@ -18612,7 +18578,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"date-fns@npm:^3.3.0, date-fns@npm:^3.3.1":
|
||||
"date-fns@npm:^3.3.0":
|
||||
version: 3.3.1
|
||||
resolution: "date-fns@npm:3.3.1"
|
||||
checksum: 10/98231936765dfb6fc6897676319b500a06a39f051b2c3ecbdd541a07ce9b1344b770277b8bfb1049fb7a2f70bf365ac8e6f1e2bb452b10e1a8101d518ca7f95d
|
||||
@ -30362,22 +30328,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-datepicker@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "react-datepicker@npm:6.0.0"
|
||||
dependencies:
|
||||
"@floating-ui/react": "npm:^0.26.2"
|
||||
classnames: "npm:^2.2.6"
|
||||
date-fns: "npm:^3.3.1"
|
||||
prop-types: "npm:^15.7.2"
|
||||
react-onclickoutside: "npm:^6.13.0"
|
||||
peerDependencies:
|
||||
react: ^16.9.0 || ^17 || ^18
|
||||
react-dom: ^16.9.0 || ^17 || ^18
|
||||
checksum: 10/cbc43b9d5ce68c32bca0e6584291796bad776004511a548e1a0de9175fb94b5c9d4a6344dc6adf9af31c5bbc32305ce4bd9a1f72100f7ab627d49ac418b32af2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dnd@npm:*":
|
||||
version: 16.0.1
|
||||
resolution: "react-dnd@npm:16.0.1"
|
||||
@ -30536,16 +30486,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-onclickoutside@npm:^6.13.0":
|
||||
version: 6.13.0
|
||||
resolution: "react-onclickoutside@npm:6.13.0"
|
||||
peerDependencies:
|
||||
react: ^15.5.x || ^16.x || ^17.x || ^18.x
|
||||
react-dom: ^15.5.x || ^16.x || ^17.x || ^18.x
|
||||
checksum: 10/4c302e97e7d0009bf06eec35b1cfdb990661bdd144a474f36f29859e43e6c7d9b05e4b13189381e9d1679b83153f4c3d874bcff5a1808390ac4e1c358c92891e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-paginate@npm:^8.2.0":
|
||||
version: 8.2.0
|
||||
resolution: "react-paginate@npm:8.2.0"
|
||||
|
Loading…
Reference in New Issue
Block a user