UNPKG

2.14 kBTypeScriptView Raw
1import React, { useId, useState } from "react";
2
3import { format, isValid, parse } from "date-fns";
4import { DayPicker } from "react-day-picker";
5
6/** Render an input field bound to a DayPicker calendar. */
7export function Input() {
8 const inputId = useId();
9
10 // Hold the month in state to control the calendar when the input changes
11 const [month, setMonth] = useState(new Date());
12
13 // Hold the selected date in state
14 const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
15
16 // Hold the input value in state
17 const [inputValue, setInputValue] = useState("");
18
19 /**
20 * Function to handle the DayPicker select event: update the input value and
21 * the selected date, and set the month.
22 */
23 const handleDayPickerSelect = (date: Date | undefined) => {
24 if (!date) {
25 setInputValue("");
26 setSelectedDate(undefined);
27 } else {
28 setSelectedDate(date);
29 setMonth(date);
30 setInputValue(format(date, "MM/dd/yyyy"));
31 }
32 };
33
34 /**
35 * Handle the input change event: parse the input value to a date, update the
36 * selected date and set the month.
37 */
38 const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
39 setInputValue(e.target.value); // keep the input value in sync
40
41 const parsedDate = parse(e.target.value, "MM/dd/yyyy", new Date());
42
43 if (isValid(parsedDate)) {
44 setSelectedDate(parsedDate);
45 setMonth(parsedDate);
46 } else {
47 setSelectedDate(undefined);
48 }
49 };
50
51 return (
52 <div>
53 <label htmlFor={inputId}>
54 <strong>Date:</strong>
55 </label>
56 <input
57 style={{ fontSize: "inherit", padding: "0.25em 0.5em" }}
58 id={inputId}
59 type="text"
60 value={inputValue}
61 placeholder="MM/dd/yyyy"
62 onChange={handleInputChange}
63 />
64 <div style={{ marginBlock: "1em" }}>
65 <DayPicker
66 month={month}
67 onMonthChange={setMonth}
68 mode="single"
69 selected={selectedDate}
70 onSelect={handleDayPickerSelect}
71 footer={`Selected: ${selectedDate?.toDateString()}`}
72 />
73 </div>
74 </div>
75 );
76}