-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
NgocNhi123
committed
Jun 24, 2024
1 parent
8c10d24
commit d02cc67
Showing
16 changed files
with
7,140 additions
and
8,484 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,173 +1,181 @@ | ||
import { ReactNode, useState } from "react"; | ||
import { CaptionElementProps, Modifier } from "react-day-picker"; | ||
import DayPickerInput from "react-day-picker/DayPickerInput"; | ||
import { Input, InputProps } from "../input/input"; | ||
import { PopoverPane } from "../popover/pane/pane"; | ||
import "./date-input.css"; | ||
import { DateInputFormat, dateInputFormats } from "./format"; | ||
import { DateInputMonth } from "./month/month"; | ||
import { DateInputNavbar } from "./navbar/navbar"; | ||
// TODO: Rewrite date input using the new DayPicker component | ||
import { ReactElement } from "react" | ||
import { DayPicker } from "react-day-picker" | ||
|
||
interface Props { | ||
/** | ||
* Date format of the text box. This is used to display the selected date | ||
* and to parse the user's input into `Date`. Choose one from | ||
* `DateInput.formats`. Defaults to "dd/mm/yyyy". | ||
*/ | ||
format?: DateInputFormat; | ||
/** | ||
* The maximum date users can choose in the pop-up calendar. | ||
*/ | ||
maxDate?: Date; | ||
/** | ||
* The minimum date users can choose in the pop-up calendar. | ||
*/ | ||
minDate?: Date; | ||
/** | ||
* Value of the input in controlled mode. Note that it includes "null", | ||
* to represent the state where the user's input is invalid (e.g. | ||
* "31/2/1999"). This follows the behavior in HTML. | ||
*/ | ||
value?: Date | null; | ||
/** | ||
* Handler to set the value in controlled mode. Note that it includes | ||
* "null". See "value" prop for detail. | ||
*/ | ||
setValue?: (date: Date | null) => void; | ||
/** | ||
* Initial value of the input in uncontrolled mode. | ||
*/ | ||
defaultValue?: Date | null; | ||
/** | ||
* Whether the input is disabled. This disables the whole input. If you | ||
* want to disable some days, use "minDate" and "maxDate" | ||
*/ | ||
disabled?: InputProps["disabled"]; | ||
/** | ||
* Size of the text box. Choose one from `DateInput.sizes`. Same default as | ||
* the in "Input" component. | ||
*/ | ||
size?: InputProps["size"]; | ||
/** | ||
* Style of the text box. Choose one from `DateInput.styles`. Same default | ||
* as in the "Input" component. | ||
*/ | ||
style?: InputProps["style"]; | ||
/** | ||
* The icon of the text box. See "Icon" page. | ||
*/ | ||
icon?: InputProps["icon"]; | ||
export const DateInput = (): ReactElement => { | ||
return <DayPicker/> | ||
} | ||
|
||
interface DayPickerOverlayProps { | ||
children: ReactNode; | ||
selectedDay: Date; | ||
month: Date; | ||
input: null; | ||
classNames: { | ||
container: string; // input | ||
overlay: string; | ||
overlayWrapper: string; | ||
}; | ||
} | ||
// import { ReactNode, useState } from "react"; | ||
// import { CaptionElementProps, Modifier } from "react-day-picker"; | ||
// import DayPickerInput from "react-day-picker/DayPickerInput"; | ||
// import { Input, InputProps } from "../input/input"; | ||
// import { PopoverPane } from "../popover/pane/pane"; | ||
// import "./date-input.css"; | ||
// import { DateInputFormat, dateInputFormats } from "./format"; | ||
// import { DateInputMonth } from "./month/month"; | ||
// import { DateInputNavbar } from "./navbar/navbar"; | ||
|
||
interface OverlayProps extends DayPickerOverlayProps { | ||
target: HTMLDivElement | null; | ||
} | ||
// interface Props { | ||
// /** | ||
// * Date format of the text box. This is used to display the selected date | ||
// * and to parse the user's input into `Date`. Choose one from | ||
// * `DateInput.formats`. Defaults to "dd/mm/yyyy". | ||
// */ | ||
// format?: DateInputFormat; | ||
// /** | ||
// * The maximum date users can choose in the pop-up calendar. | ||
// */ | ||
// maxDate?: Date; | ||
// /** | ||
// * The minimum date users can choose in the pop-up calendar. | ||
// */ | ||
// minDate?: Date; | ||
// /** | ||
// * Value of the input in controlled mode. Note that it includes "null", | ||
// * to represent the state where the user's input is invalid (e.g. | ||
// * "31/2/1999"). This follows the behavior in HTML. | ||
// */ | ||
// value?: Date | null; | ||
// /** | ||
// * Handler to set the value in controlled mode. Note that it includes | ||
// * "null". See "value" prop for detail. | ||
// */ | ||
// setValue?: (date: Date | null) => void; | ||
// /** | ||
// * Initial value of the input in uncontrolled mode. | ||
// */ | ||
// defaultValue?: Date | null; | ||
// /** | ||
// * Whether the input is disabled. This disables the whole input. If you | ||
// * want to disable some days, use "minDate" and "maxDate" | ||
// */ | ||
// disabled?: InputProps["disabled"]; | ||
// /** | ||
// * Size of the text box. Choose one from `DateInput.sizes`. Same default as | ||
// * the in "Input" component. | ||
// */ | ||
// size?: InputProps["size"]; | ||
// /** | ||
// * Style of the text box. Choose one from `DateInput.styles`. Same default | ||
// * as in the "Input" component. | ||
// */ | ||
// style?: InputProps["style"]; | ||
// /** | ||
// * The icon of the text box. See "Icon" page. | ||
// */ | ||
// icon?: InputProps["icon"]; | ||
// } | ||
|
||
// interface DayPickerOverlayProps { | ||
// children: ReactNode; | ||
// selectedDay: Date; | ||
// month: Date; | ||
// input: null; | ||
// classNames: { | ||
// container: string; // input | ||
// overlay: string; | ||
// overlayWrapper: string; | ||
// }; | ||
// } | ||
|
||
// interface OverlayProps extends DayPickerOverlayProps { | ||
// target: HTMLDivElement | null; | ||
// } | ||
|
||
const Overlay = (props: OverlayProps): JSX.Element | null => { | ||
// We don't need these props, but we need to remove them from the "rest" so | ||
// that "rest" can be applied to the div element | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const { target, children, selectedDay, classNames, month, input, ...rest } = props; // prettier-ignore | ||
if (target === null) return null; | ||
return ( | ||
<div {...rest}> | ||
<PopoverPane target={target} children={children} /> | ||
</div> | ||
); | ||
}; | ||
// const Overlay = (props: OverlayProps): JSX.Element | null => { | ||
// // We don't need these props, but we need to remove them from the "rest" so | ||
// // that "rest" can be applied to the div element | ||
// // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
// const { target, children, selectedDay, classNames, month, input, ...rest } = props; // prettier-ignore | ||
// if (target === null) return null; | ||
// return ( | ||
// <div {...rest}> | ||
// <PopoverPane target={target} children={children} /> | ||
// </div> | ||
// ); | ||
// }; | ||
|
||
const getValue = (props: Props): Date | undefined => { | ||
// Controlled | ||
if (props.value !== undefined) { | ||
return props.value ?? undefined; | ||
} | ||
// Uncontrolled w initial value | ||
if (props.defaultValue !== undefined) { | ||
return props.defaultValue ?? undefined; | ||
} | ||
// Uncontrolled wo initial value | ||
return undefined; | ||
}; | ||
// const getValue = (props: Props): Date | undefined => { | ||
// // Controlled | ||
// if (props.value !== undefined) { | ||
// return props.value ?? undefined; | ||
// } | ||
// // Uncontrolled w initial value | ||
// if (props.defaultValue !== undefined) { | ||
// return props.defaultValue ?? undefined; | ||
// } | ||
// // Uncontrolled wo initial value | ||
// return undefined; | ||
// }; | ||
|
||
const getDisabledDays = (props: Props): Modifier => { | ||
// This is quite complicated because we need to avoid mutating the "days" | ||
// variable as well as the strictness of Modifier | ||
const { minDate: min, maxDate: max } = props; | ||
let days: Modifier = undefined; | ||
if (max) days = { after: max }; | ||
if (min) days = { ...days, before: min }; | ||
return days; | ||
}; | ||
// const getDisabledDays = (props: Props): Modifier => { | ||
// // This is quite complicated because we need to avoid mutating the "days" | ||
// // variable as well as the strictness of Modifier | ||
// const { minDate: min, maxDate: max } = props; | ||
// let days: Modifier = undefined; | ||
// if (max) days = { after: max }; | ||
// if (min) days = { ...days, before: min }; | ||
// return days; | ||
// }; | ||
|
||
/** | ||
* A date input is a control for users to enter a date, either by typing it or | ||
* choosing from a pop-up calendar. | ||
* | ||
* The Date Input component is based on [React Day Picker][3], as an | ||
* alternative to the built-in `<Input type="date" />`. It works on | ||
* [unsupported browsers][2] and can display custom date format (e.g. "dmy" or | ||
* "mdy"). If you don't need these features, use [Input][1] to have better | ||
* accessibility support. | ||
// /** | ||
// * A date input is a control for users to enter a date, either by typing it or | ||
// * choosing from a pop-up calendar. | ||
// * | ||
// * The Date Input component is based on [React Day Picker][3], as an | ||
// * alternative to the built-in `<Input type="date" />`. It works on | ||
// * [unsupported browsers][2] and can display custom date format (e.g. "dmy" or | ||
// * "mdy"). If you don't need these features, use [Input][1] to have better | ||
// * accessibility support. | ||
|
||
* [1]: /docs/components-input--primary#date | ||
* [2]: https://caniuse.com/input-datetime | ||
* [3]: https://react-day-picker.js.org | ||
* | ||
*/ | ||
export const DateInput = (props: Props): JSX.Element => { | ||
const [target, setTarget] = useState<HTMLDivElement | null>(null); | ||
const [month, setMonth] = useState<Date>(() => new Date()); | ||
const format = props.format ?? DateInput.formats.dmy; | ||
// * [1]: /docs/components-input--primary#date | ||
// * [2]: https://caniuse.com/input-datetime | ||
// * [3]: https://react-day-picker.js.org | ||
// * | ||
// */ | ||
// export const DateInput = (props: Props): JSX.Element => { | ||
// const [target, setTarget] = useState<HTMLDivElement | null>(null); | ||
// const [month, setMonth] = useState<Date>(() => new Date()); | ||
// const format = props.format ?? DateInput.formats.dmy; | ||
|
||
return ( | ||
<div ref={setTarget}> | ||
<DayPickerInput | ||
inputProps={{ | ||
style: props.style, | ||
size: props.size, | ||
disabled: props.disabled, | ||
icon: props.icon, | ||
}} | ||
component={Input} | ||
clickUnselectsDay | ||
overlayComponent={(dayPicker: DayPickerOverlayProps) => ( | ||
<Overlay target={target} {...dayPicker} /> | ||
)} | ||
dayPickerProps={{ | ||
month: month, | ||
navbarElement: DateInputNavbar, | ||
captionElement: ({ date }: CaptionElementProps) => ( | ||
<DateInputMonth value={date} setValue={setMonth} /> | ||
), | ||
disabledDays: getDisabledDays(props), | ||
}} | ||
value={getValue(props)} | ||
// The lib's type is missing "undefined" case | ||
onDayChange={(day: Date | undefined) => { | ||
if (props.setValue === undefined) return; | ||
props.setValue(day ?? null); | ||
}} | ||
// Format | ||
placeholder={format.placeholder} | ||
formatDate={format.format} | ||
parseDate={format.parse} | ||
/> | ||
</div> | ||
); | ||
}; | ||
// return ( | ||
// <div ref={setTarget}> | ||
// <DayPickerInput | ||
// inputProps={{ | ||
// style: props.style, | ||
// size: props.size, | ||
// disabled: props.disabled, | ||
// icon: props.icon, | ||
// }} | ||
// component={Input} | ||
// clickUnselectsDay | ||
// overlayComponent={(dayPicker: DayPickerOverlayProps) => ( | ||
// <Overlay target={target} {...dayPicker} /> | ||
// )} | ||
// dayPickerProps={{ | ||
// month: month, | ||
// navbarElement: DateInputNavbar, | ||
// captionElement: ({ date }: CaptionElementProps) => ( | ||
// <DateInputMonth value={date} setValue={setMonth} /> | ||
// ), | ||
// disabledDays: getDisabledDays(props), | ||
// }} | ||
// value={getValue(props)} | ||
// // The lib's type is missing "undefined" case | ||
// onDayChange={(day: Date | undefined) => { | ||
// if (props.setValue === undefined) return; | ||
// props.setValue(day ?? null); | ||
// }} | ||
// // Format | ||
// placeholder={format.placeholder} | ||
// formatDate={format.format} | ||
// parseDate={format.parse} | ||
// /> | ||
// </div> | ||
// ); | ||
// }; | ||
|
||
DateInput.formats = dateInputFormats; | ||
DateInput.sizes = Input.sizes; | ||
DateInput.styles = Input.styles; | ||
// DateInput.formats = dateInputFormats; | ||
// DateInput.sizes = Input.sizes; | ||
// DateInput.styles = Input.styles; |
Oops, something went wrong.