0
# Date Picker State
1
2
State management for date picker components that combine a text field with a calendar popover. Provides comprehensive date and time selection with validation, formatting, and overlay state management.
3
4
## Capabilities
5
6
### useDatePickerState Hook
7
8
Creates a state object for managing date picker component state including date/time values, overlay visibility, and validation.
9
10
```typescript { .api }
11
/**
12
* Provides state management for a date picker component.
13
* A date picker combines a DateField and a Calendar popover to allow users to enter or select a date and time value.
14
* @param props - Configuration options for the date picker state
15
* @returns DatePickerState object with date/time management and overlay controls
16
*/
17
function useDatePickerState<T extends DateValue = DateValue>(
18
props: DatePickerStateOptions<T>
19
): DatePickerState;
20
21
interface DatePickerStateOptions<T extends DateValue> extends DatePickerProps<T> {
22
/**
23
* Determines whether the date picker popover should close automatically when a date is selected.
24
* @default true
25
*/
26
shouldCloseOnSelect?: boolean | (() => boolean);
27
}
28
29
interface DatePickerState extends OverlayTriggerState, FormValidationState {
30
/** The currently selected date. */
31
value: DateValue | null;
32
/** The default date. */
33
defaultValue: DateValue | null;
34
/** Sets the selected date. */
35
setValue(value: DateValue | null): void;
36
/** The date portion of the value. This may be set prior to `value` if the user has selected a date but has not yet selected a time. */
37
dateValue: DateValue | null;
38
/** Sets the date portion of the value. */
39
setDateValue(value: DateValue): void;
40
/** The time portion of the value. This may be set prior to `value` if the user has selected a time but has not yet selected a date. */
41
timeValue: TimeValue | null;
42
/** Sets the time portion of the value. */
43
setTimeValue(value: TimeValue): void;
44
/** The granularity for the field, based on the `granularity` prop and current value. */
45
granularity: Granularity;
46
/** Whether the date picker supports selecting a time, according to the `granularity` prop and current value. */
47
hasTime: boolean;
48
/** Whether the calendar popover is currently open. */
49
isOpen: boolean;
50
/** Sets whether the calendar popover is open. */
51
setOpen(isOpen: boolean): void;
52
/** The current validation state of the date picker, based on the `validationState`, `minValue`, and `maxValue` props. @deprecated Use `isInvalid` instead. */
53
validationState: ValidationState | null;
54
/** Whether the date picker is invalid, based on the `isInvalid`, `minValue`, and `maxValue` props. */
55
isInvalid: boolean;
56
/** Formats the selected value using the given options. */
57
formatValue(locale: string, fieldOptions: FieldOptions): string;
58
/** Gets a formatter based on state's props. */
59
getDateFormatter(locale: string, formatOptions: FormatterOptions): DateFormatter;
60
}
61
```
62
63
**Usage Examples:**
64
65
```typescript
66
import { useDatePickerState } from "@react-stately/datepicker";
67
import { CalendarDate, CalendarDateTime } from "@internationalized/date";
68
69
// Basic date picker
70
function BasicDatePicker() {
71
const state = useDatePickerState({
72
defaultValue: new CalendarDate(2023, 6, 15),
73
onChange: (value) => console.log("Selected:", value?.toString())
74
});
75
76
return (
77
<div>
78
<input
79
value={state.formatValue('en-US', {})}
80
readOnly
81
onClick={() => state.setOpen(true)}
82
/>
83
{state.isOpen && <div>Calendar popover</div>}
84
</div>
85
);
86
}
87
88
// Date and time picker with validation
89
function DateTimePicker() {
90
const state = useDatePickerState({
91
granularity: 'minute',
92
minValue: new CalendarDateTime(2023, 1, 1, 0, 0),
93
maxValue: new CalendarDateTime(2024, 12, 31, 23, 59),
94
isInvalid: false,
95
onChange: (value) => {
96
if (value) {
97
console.log("Date:", value.toDate('UTC'));
98
}
99
}
100
});
101
102
return (
103
<div>
104
<input
105
value={state.formatValue('en-US', { hour: 'numeric', minute: '2-digit' })}
106
style={{ borderColor: state.isInvalid ? 'red' : 'gray' }}
107
readOnly
108
onClick={() => state.setOpen(true)}
109
/>
110
{state.hasTime && <span>Includes time selection</span>}
111
</div>
112
);
113
}
114
115
// Controlled date picker with custom close behavior
116
function ControlledDatePicker({ value, onChange }) {
117
const state = useDatePickerState({
118
value,
119
onChange,
120
shouldCloseOnSelect: () => !state.hasTime, // Keep open for time selection
121
granularity: 'second'
122
});
123
124
return (
125
<div>
126
<button onClick={() => state.setOpen(!state.isOpen)}>
127
{state.value?.toString() || "Select date & time"}
128
</button>
129
{state.isOpen && (
130
<div>
131
{!state.hasTime ? "Date only" : "Date and time"}
132
<button onClick={() => state.setOpen(false)}>Close</button>
133
</div>
134
)}
135
</div>
136
);
137
}
138
```
139
140
### State Value Management
141
142
The date picker state manages separate date and time portions that are combined into the final value.
143
144
```typescript { .api }
145
/**
146
* Sets the date portion of the value
147
* @param value - The date value to set
148
*/
149
setDateValue(value: DateValue): void;
150
151
/**
152
* Sets the time portion of the value
153
* @param value - The time value to set
154
*/
155
setTimeValue(value: TimeValue): void;
156
```
157
158
### Overlay State Management
159
160
Extends OverlayTriggerState to provide popover/modal control for the calendar.
161
162
```typescript { .api }
163
/**
164
* Sets whether the calendar popover is open
165
* Automatically commits selected date/time when closing if hasTime is true
166
* @param isOpen - Whether the popover should be open
167
*/
168
setOpen(isOpen: boolean): void;
169
```
170
171
### Formatting and Validation
172
173
Provides formatting and validation capabilities integrated with form validation.
174
175
```typescript { .api }
176
/**
177
* Formats the selected value using the given options
178
* @param locale - The locale to format in (e.g. 'en-US', 'fr-FR')
179
* @param fieldOptions - Formatting options for different date/time parts
180
* @returns Formatted date string or empty string if no value
181
*/
182
formatValue(locale: string, fieldOptions: FieldOptions): string;
183
184
/**
185
* Gets a formatter based on state's props
186
* @param locale - The locale for formatting
187
* @param formatOptions - Additional formatting options
188
* @returns DateFormatter instance for custom formatting
189
*/
190
getDateFormatter(locale: string, formatOptions: FormatterOptions): DateFormatter;
191
```
192
193
## Props Interface
194
195
```typescript { .api }
196
interface DatePickerProps<T extends DateValue> {
197
/** The current value (controlled). */
198
value?: T | null;
199
/** The default value (uncontrolled). */
200
defaultValue?: T | null;
201
/** Handler that is called when the value changes. */
202
onChange?: (value: MappedDateValue<T> | null) => void;
203
/** The minimum allowed date that a user may select. */
204
minValue?: DateValue;
205
/** The maximum allowed date that a user may select. */
206
maxValue?: DateValue;
207
/** Callback that is called for each date of the calendar. If true, the date is unavailable. */
208
isDateUnavailable?: (date: DateValue) => boolean;
209
/** Whether the calendar is disabled. */
210
isDisabled?: boolean;
211
/** Whether the calendar is read only. */
212
isReadOnly?: boolean;
213
/** The date that is focused in the calendar on first mount. */
214
autoFocus?: boolean;
215
/** A placeholder date that influences the format of the placeholder shown when no value is selected. */
216
placeholderValue?: T;
217
/** Determines the smallest unit that is displayed in the date picker. */
218
granularity?: Granularity;
219
/** Whether to hide the time zone abbreviation. */
220
hideTimeZone?: boolean;
221
/** Whether to display the time in 12 or 24 hour format. */
222
hourCycle?: 12 | 24;
223
/** Whether to always show leading zeros in the month, day, and hour fields. */
224
shouldForceLeadingZeros?: boolean;
225
/** Whether the element should receive focus on render. */
226
autoFocus?: boolean;
227
/** The name of the input element, used when submitting an HTML form. */
228
name?: string;
229
/** Whether user input is required on the input before form submission. */
230
isRequired?: boolean;
231
/** Whether the input value is invalid. */
232
isInvalid?: boolean;
233
/** The current validation state of the date picker. */
234
validationState?: ValidationState;
235
/** An error message for the field. */
236
errorMessage?: ReactNode;
237
/** A description for the field. */
238
description?: ReactNode;
239
}
240
```