DateRangeInput

A calendar component for date selection with support for single, range, and multiple date picking

Installation

Terminal
pnpm add @choice-ui/calendar

Import

Component.tsx
import { type MonthCalendarProps, MonthCalendar, DateInput, DateRangeInput, type TimeCalendarProps, TimeCalendar, TimeInput, TimeRangeInput, type QuarterCalendarProps, QuarterCalendar, type YearCalendarProps, YearCalendar, dateUtils, generateWeekdayNames, generateCalendarDays, formatMonthTitle, calculateWeekNumbers, inferSelectionMode, inferMonthFromValue, isCalendarValueEqual, LOCALE_MAP, resolveLocale, getSupportedLocales, isChineseLocale, type DateComparisonMode, type DateParts, createTimeZoneContext, isSameDayInTimeZone, isSameMonthInTimeZone, isSameYearInTimeZone, isSameWeekInTimeZone, isTodayInTimeZone, isWithinRange, getDateParts, getDateKey, areDatesEqual, clearTimeZoneCache, parseMonthName, englishMonths, chineseMonths, validateDateRange, validateTimeRange, isValidDateExists, getLastDayOfMonth, smartCorrectDate, smartCorrectYear, quickValidateDate, handleShortcuts, parseRelativeDate, parseExtendedRelativeDate, parseNaturalLanguage, getLocaleKey, parseEnglishDate, getLocale, detectDateFormat, type ParseResult, type DetailedParseResult, type ParseOptions, parseDate, parseDate, parseDate, getPredictionInfo, tryRelaxedParsing, smartParseDate, parseDate, tryRelaxedParsing, smartParseDate, getPredictionInfo, type ParseOptions, type ParseResult, type DetailedParseResult, getEnhancedPrediction, type PredictionResult, validateDateRange, validateTimeRange, isValidDateExists, smartCorrectDate, smartCorrectYear, quickValidateDate, getLastDayOfMonth, getLocale, detectDateFormat, parseMonthName, parseEnglishDate, parseRelativeDate, parseExtendedRelativeDate, parseNaturalLanguage, getLocaleKey, handleShortcuts, extractDigits, convertTwoDigitYear, isValidMonthDay, canBeMonthDay, isReasonableYear, type NumericParseResult, parseYYMMDD, parseYYYYMMDD, parse3Digits, yearUtils, quarterUtils, getQuarterMonths, createQuarter, getCurrentQuarter, getYearQuarters, isQuarterEqual, formatQuarter, getQuarterDateRange, dateToTimeString, timeStringToDate, normalizeTimeValue, smartParseTimeValue, tryRelaxedTimeParsing, createTimeValue, timeToDate, dateToTime, formatTimeValue, formatHourValue, formatMinuteValue, generateHourOptions, generateMinuteOptions, isTimeEqual, findClosestValidTime, generateTimeOptions, createTimeToday, defaultLocaleMap, naturalLanguageMap, relativeDatePatterns, commonDateFormats, commonTimeFormats, parserConfig, parseCache, useDateInput, useTimeInput, type BaseYearProps, type YearItem, type YearLayoutProps, type YearNavigationProps, type BaseQuarterProps, type Quarter, type QuarterItem, type QuarterLayoutProps, type QuarterNavigationProps, type BaseCalendarProps, type CalendarValue, type CalendarState, type CalendarLayoutProps, type BaseDateProps, type DateInputValue, type DateDataFormat, type DateRange, type DateParserOptions, type DateInteractionProps, type BaseTimeProps, type Time, type TimeInputValue, type TimeDataFormat, type TimeParserOptions, type TimeLayout, type TimeInteractionProps, type TimeOptionItem, type SmartInputOptions, type StepProps, type NaturalLanguageMap, type RelativeDatePattern } from "@choice-ui/calendar"

Basic

Default: Shows the basic DateRangeInput usage with standard configuration.
- Demonstrates dual input fields for start and end dates. - Uses ISO date format and English locale as defaults. - Provides a foundation for date range selection implementation.

Size

Size: Demonstrates the large size variant of DateRangeInput.
- Shows the component with increased dimensions for prominent interfaces. - Useful for applications requiring larger touch targets or enhanced visibility.

Variable

Variable: Demonstrates the dark theme variant of DateRangeInput.
- Shows the component styled for dark theme environments. - Useful for applications with dark mode or specialized UI themes.

Range Synchronization

RangeSynchronization: Demonstrates the intelligent range synchronization feature.
- Shows how start date changes automatically adjust the end date to maintain range length. - Displays boundary validation where end dates push start dates when necessary. - Includes comprehensive explanation and test scenarios for understanding the behavior.
3 天
🎯 Range Synchronization
Start Date Change:Automatically adjust the end date to maintain the original range length
End Date Change:If the end date is less than or equal to the start date, the start date is pushed to the end position
Dynamic Range:First adjust the end date to set the desired range length, then any changes to the start date will maintain this length
🧪 Test Steps
1. Adjust the end date to 5 days later → the range becomes 5 days
2. Modify the start date → the end date is automatically adjusted to maintain a 5-day distance
3. Set the end date to be earlier than the start date → the start date is pushed to the end position

With Preset Range

WithPresetRange: Demonstrates DateRangeInput with pre-filled date values.
- Shows the component with initial start and end dates already set. - Displays a 7-day range as an example of preset configurations. - Useful for forms or filters that need default date ranges.

Internationalization

Internationalization: Demonstrates comprehensive multi-language support.
- Shows DateRangeInput working with Chinese, English, Japanese, and Korean locales. - Displays locale-specific date formats and placeholder text. - Demonstrates proper range calculation display in multiple languages.

中文 (zh-CN)

7 天
范围显示:7 天

English (en-US)

7 days
Range display: 7 days

日本語 (ja)

7日
範囲表示:7日

한국어 (ko)

7일
범위 표시:7일

Different Formats

DifferentFormats: Demonstrates various date format options and their visual representation.
- Shows ISO format, American format, Chinese format, and European format. - Displays how different formats affect the display and input experience. - Useful for understanding format flexibility and regional preferences.

ISO Format (yyyy-MM-dd)

3 days

American Format (MM/dd/yyyy)

3 days

Chinese Format (yyyy年MM月dd日)

3 天

European Format (dd.MM.yyyy)

3 days

Common Scenarios

CommonScenarios: Demonstrates real-world usage scenarios for DateRangeInput.
- Shows holiday planning, data analysis periods, and event scheduling examples. - Displays practical applications with appropriate date ranges and contexts. - Useful for understanding when and how to implement date range selection.

🏖️ Holiday Planning

7 天
💡 Planning a week-long holiday, displaying the total number of days

📊 Data Analysis Period

30 days
💡 Data analysis period for the past 30 days

🎫 Event Time

2日
💡 3-day event period, Japanese environment

Edge Cases

EdgeCases: Demonstrates how DateRangeInput handles boundary and edge cases.
- Shows same time point handling, reverse time ranges, and cross-year ranges. - Displays proper validation and calculation behavior in unusual scenarios. - Useful for understanding component robustness and error handling.

Same Time Point

1 day
💡 Display as 1 day at the same time point

Reverse Time Range

5 days
💡 Display the absolute difference in reverse range

Cross-year Range

11 天
💡 Calculating the cross-year date range

Disabled States

DisabledStates: Demonstrates various disabled state configurations.
- Shows individual input field disabling (start only, end only, or both). - Displays how disabled states affect user interaction and visual appearance. - Useful for implementing conditional form controls and readOnly scenarios.

Start Date Disabled

7 days

End Date Disabled

7 days

All Disabled

7 days

Read Only

ReadOnly: Demonstrates the DateRangeInput component in readOnly mode.
- Prevents value changes while allowing focus and selection - Maintains normal visual appearance (unlike disabled) - Useful for displaying non-editable date range information
Current Start:
1/24/2026
Current End:
1/31/2026
Change Count:
0
7 days
7 days
💡 Try changing the readonly date range input - the values should not change and the change count should remain at 0. Only the normal input will change the values.

API reference

MonthCalendarTypeDefault
className
string
|
undefined
-
currentMonth
Date
|
undefined
-
dateComparisonMode
undefined
|
"exact-time"
|
"date-only"
-
defaultValue
CalendarValue
|
undefined
-
disabledDates
Date[]
|
undefined
-
fixedGrid
boolean
|
undefined
-
highlightDates
Date[]
|
undefined
-
highlightToday
boolean
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxDate
Date
|
undefined
-
minDate
Date
|
undefined
-
onChange
((value: CalendarValue) => void)
|
undefined
-
onMonthChange
((month: Date) => void)
|
undefined
-
readOnly
boolean
|
undefined
-
selectionMode
undefined
|
"single"
|
"multiple"
|
"range"
-
showOutsideDays
boolean
|
undefined
-
showWeekNumbers
boolean
|
undefined
-
timeZone
string
|
undefined
-
value
CalendarValue
|
undefined
-
weekStartsOn
undefined
|
0
|
1
|
2
|
3
|
4
|
5
|
6
-
weekdayNames
string[]
|
undefined
-
direction
undefined
|
"horizontal"
|
"vertical"
-
variant
undefined
|
"default"
|
"dark"
-
DateInputValueTypeDefault
value
Date
|
null
|
undefined
-
onChange
((date: Date
|
null) => void)
|
undefined
-
format
string
|
undefined
-
size
undefined
|
"default"
|
"large"
-
selected
boolean
|
undefined
-
className
string
|
undefined
-
focusSelection
undefined
|
"none"
|
"all"
|
"end"
-
onIsEditingChange
((isEditing: boolean) => void)
|
undefined
-
variant
undefined
|
"default"
|
"light"
|
"dark"
|
"reset"
-
enableCache
boolean
|
undefined
true
enableKeyboardNavigation
boolean
|
undefined
true
enablePrediction
boolean
|
undefined
false
enableProfiling
boolean
|
undefined
false
locale
string
|
Locale
|
undefined
-
maxDate
Date
|
undefined
-
minDate
Date
|
undefined
-
onEnterKeyDown
(() => void)
|
undefined
-
prefixElement
ReactNode -
suffixElement
ReactNode -
DateRangeInputTypeDefault
endDisabled
boolean
|
undefined
-
endPlaceholder
string
|
undefined
-
endSuffixElement
ReactNode -
endValue
Date
|
null
|
undefined
-
format
string
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxDate
Date
|
undefined
-
minDate
Date
|
undefined
-
onEndChange
((date: Date
|
null) => void)
|
undefined
-
onEndFocus
(() => void)
|
undefined
-
onEnterKeyDown
(() => void)
|
undefined
-
onStartChange
((date: Date
|
null) => void)
|
undefined
-
onStartFocus
(() => void)
|
undefined
-
rangePrecision
number
|
undefined
1 - Minimum unit is 1 day
startDisabled
boolean
|
undefined
-
startPlaceholder
string
|
undefined
-
startSuffixElement
ReactNode -
startValue
Date
|
null
|
undefined
-
size
undefined
|
"default"
|
"large"
-
selected
boolean
|
undefined
-
className
string
|
undefined
-
focusSelection
undefined
|
"none"
|
"all"
|
"end"
-
onIsEditingChange
((isEditing: boolean) => void)
|
undefined
-
variant
undefined
|
"default"
|
"light"
|
"dark"
|
"reset"
-
TimeCalendarTypeDefault
className
string
|
undefined
-
hourStep
number
|
undefined
-
minuteStep
number
|
undefined
-
open
boolean
|
undefined
-
onOpenChange
((open: boolean) => void)
|
undefined
-
closeOnSelect
boolean
|
undefined
-
triggerRef
RefObject<HTMLElement>
|
undefined
-
triggerSelector
string
|
undefined
-
defaultValue
Date
|
null
|
undefined
-
disabled
boolean
|
undefined
-
format
string
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxTime
Date
|
undefined
-
minTime
Date
|
undefined
-
onChange
((time: Date
|
null) => void)
|
undefined
-
readOnly
boolean
|
undefined
-
value
Date
|
null
|
undefined
-
metaStep
number
|
undefined
-
shiftStep
number
|
undefined
-
step
number
|
undefined
-
offset
number
|
undefined
-
placement
undefined
|
"top"
|
"right"
|
"bottom"
|
"left"
|
"top-start"
|
"top-end"
|
"right-start"
|
"right-end"
|
"bottom-start"
|
"bottom-end"
|
"left-start"
|
"left-end"
-
matchTriggerWidth
boolean
|
undefined
-
variant
undefined
|
"default"
|
"light"
|
"reset"
-
TimeInputValueTypeDefault
value
Date
|
null
|
undefined
-
onChange
((time: Date
|
null) => void)
|
undefined
-
format
string
|
undefined
-
defaultValue
Date
|
null
|
undefined
-
step
number
|
undefined
-
size
undefined
|
"default"
|
"large"
-
selected
boolean
|
undefined
-
className
string
|
undefined
-
focusSelection
undefined
|
"none"
|
"all"
|
"end"
-
onIsEditingChange
((isEditing: boolean) => void)
|
undefined
-
variant
undefined
|
"default"
|
"light"
|
"dark"
|
"reset"
-
prefixElement
ReactNode -
suffixElement
ReactNode -
locale
string
|
Locale
|
undefined
-
maxTime
Date
|
undefined
-
minTime
Date
|
undefined
-
metaStep
number
|
undefined
-
shiftStep
number
|
undefined
-
enableCache
boolean
|
undefined
-
enableKeyboardNavigation
boolean
|
undefined
-
enableProfiling
boolean
|
undefined
-
onEnterKeyDown
(() => void)
|
undefined
-
TimeRangeInputTypeDefault
endDisabled
boolean
|
undefined
-
endPlaceholder
string
|
undefined
-
endSuffixElement
ReactNode -
endValue
Date
|
null
|
undefined
-
format
string
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxTime
Date
|
undefined
-
minTime
Date
|
undefined
-
onEndChange
((time: Date
|
null) => void)
|
undefined
-
onEndFocus
(() => void)
|
undefined
-
onEnterKeyDown
(() => void)
|
undefined
-
onStartChange
((time: Date
|
null) => void)
|
undefined
-
onStartFocus
(() => void)
|
undefined
-
startDisabled
boolean
|
undefined
-
startPlaceholder
string
|
undefined
-
startSuffixElement
ReactNode -
startValue
Date
|
null
|
undefined
-
size
undefined
|
"default"
|
"large"
-
selected
boolean
|
undefined
-
className
string
|
undefined
-
focusSelection
undefined
|
"none"
|
"all"
|
"end"
-
onIsEditingChange
((isEditing: boolean) => void)
|
undefined
-
variant
undefined
|
"default"
|
"light"
|
"dark"
|
"reset"
-
QuarterCalendarTypeDefault
currentYear
number
|
undefined
-
defaultValue
Quarter
|
undefined
-
disabled
boolean
|
undefined
-
disabledQuarters
{ quarter: number; year: number; }[]
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxYear
number
|
undefined
-
minYear
number
|
undefined
-
onChange
((quarter: Quarter
|
null) => void)
|
undefined
-
readOnly
boolean
|
undefined
-
startYear
number
|
undefined
-
value
Quarter
|
null
|
undefined
-
onNavigate
((direction: "prev"
|
"next", newYear: number) => void)
|
undefined
-
className
string
|
undefined
-
variant
undefined
|
"default"
|
"dark"
-
YearCalendarTypeDefault
currentYear
Date
|
undefined
-
defaultValue
Date
|
undefined
-
disabled
boolean
|
undefined
-
disabledYears
Date[]
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxYear
Date
|
undefined
-
minYear
Date
|
undefined
-
onChange
((year: Date
|
null) => void)
|
undefined
-
readOnly
boolean
|
undefined
-
startYear
Date
|
undefined
-
value
Date
|
null
|
undefined
-
yearCount
number
|
undefined
-
onNavigate
((direction: "prev"
|
"next", newStartYear: Date) => void)
|
undefined
-
className
string
|
undefined
-
variant
undefined
|
"default"
|
"dark"
-
inferSelectionModeTypeDefault
end
Date -
start
Date -
inferMonthFromValueTypeDefault
end
Date -
start
Date -
formatQuarterTypeDefault
label
string -
months
string[] -
quarter
1
|
2
|
3
|
4
-
year
number -
getQuarterDateRangeTypeDefault
label
string -
months
string[] -
quarter
1
|
2
|
3
|
4
-
year
number -
timeToDateTypeDefault
hour
number -
minute
number -
useDateInputTypeDefault
onPressEnd
(((event: PressEvent) => void) & ((e: PointerEvent) => void))
|
undefined
-
onPressStart
(((event: PressEvent) => void) & ((e: PointerEvent) => void))
|
undefined
-
readOnly
boolean
|
undefined
-
ref
Ref<HTMLInputElement>
|
undefined
-
defaultValue
Date
|
null
|
undefined
-
disabled
boolean
|
undefined
-
format
string
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxDate
Date
|
undefined
-
minDate
Date
|
undefined
-
onChange
((date: Date
|
null) => void)
|
undefined
-
value
Date
|
null
|
undefined
-
metaStep
number
|
undefined
-
shiftStep
number
|
undefined
-
step
number
|
undefined
-
enableCache
boolean
|
undefined
-
enableKeyboardNavigation
boolean
|
undefined
-
enablePrediction
boolean
|
undefined
-
enableProfiling
boolean
|
undefined
-
onEnterKeyDown
(() => void)
|
undefined
-
useTimeInputTypeDefault
onPressEnd
(((event: PressEvent) => void) & ((e: PointerEvent) => void))
|
undefined
-
onPressStart
(((event: PressEvent) => void) & ((e: PointerEvent) => void))
|
undefined
-
readOnly
boolean
|
undefined
-
ref
Ref<HTMLInputElement>
|
undefined
-
defaultValue
Date
|
null
|
undefined
-
disabled
boolean
|
undefined
-
format
string
|
undefined
-
locale
string
|
Locale
|
undefined
-
maxTime
Date
|
undefined
-
minTime
Date
|
undefined
-
onChange
((time: Date
|
null) => void)
|
undefined
-
value
Date
|
null
|
undefined
-
metaStep
number
|
undefined
-
shiftStep
number
|
undefined
-
step
number
|
undefined
-
enableCache
boolean
|
undefined
-
enableKeyboardNavigation
boolean
|
undefined
-
enableProfiling
boolean
|
undefined
-
onEnterKeyDown
(() => void)
|
undefined
-