timepicker-ui
4.6.0GitHub
timepicker-ui
API Reference / Options

Options API Reference

Every option of @pglejzer/datepicker-ui, the companion of timepicker-ui, grouped by area.

Option groups

Pass options in five groups: calendar, ui, labels, behavior and callbacks. Every option is optional. For what each group does in practice, see the guides.
index.ts
import DatepickerUI from "@pglejzer/datepicker-ui";
import "@pglejzer/datepicker-ui/index.css";
new DatepickerUI("#date", {
calendar: { mode: "range", minDate: "today" },
ui: { theme: "m3-green", displayMode: "docked" },
labels: { confirm: "Done" },
behavior: { closeOnSelect: true, id: "trip-dates" },
callbacks: {
onConfirm: ({ value }) => console.log(value),
},
}).create();

Invalid options

#

A value of the wrong type or an unknown choice falls back to the default. The picker also emits an error event with code invalid-option and the option path in option, for example ui.theme.

index.ts
import DatepickerUI from "@pglejzer/datepicker-ui";
const picker = new DatepickerUI("#date", {
ui: { theme: "neon" },
});
picker.on("error", ({ code, option, message }) => {
if (code === "invalid-option") {
console.warn(option, message);
}
});
picker.create();

Calendar options

#

Which days exist, what the user selects and how the weeks are laid out:

OptionTypeDefaultDescription
mode"single" | "range" | "multiple""single"What the user selects.
range.minLengthnumberundefinedShortest range in days, a positive integer.
range.maxLengthnumberundefinedLongest range in days. Ignored, with an error, when below minLength.
range.presetsRangePreset[][]Range shortcuts. See the RangePreset shape below.
multiple.maxnumberundefinedMost dates in a multiple selection, a positive integer.
monthsnumber1Months side by side, a positive integer. Docked and inline only.
pageBy"month" | "view""view"Whether the arrows move one month or as many as are shown.
precision"day" | "month" | "year""day"What one pick selects. Single mode only.
localestringpage localeBCP 47 tag. Falls back to <html lang>, then navigator.language, then en-US. An invalid tag emits invalid-option.
weekStart"auto" | "sunday" | "monday" | "saturday""auto"First day of the week. "auto" follows the locale.
minDateDate | string | "today"undefinedEarliest selectable day. Strings are ISO YYYY-MM-DD.
maxDateDate | string | "today"undefinedLatest selectable day.
disabledDates(Date | string)[][]Days that cannot be selected.
enabledDates(Date | string)[]undefinedWhen set, only these days can be selected.
disabledWeekdaysnumber[][]Weekdays that cannot be selected. 0 is Sunday and 6 is Saturday.
isDateDisabled(date: Date) => booleanundefinedReturn true for a day that cannot be selected.
decorateDate(date: Date) => DateDecoration | undefinedundefinedReturn extra presentation for a day.
renderDate(date: Date) => string | Node | nullundefinedReturn content shown under the day number. A string is always text, never HTML, and it is added to the accessible name of the day.
validate(value: PickerValue | null) => string | nullundefinedReturn a message to mark the field invalid, or null or undefined when it is fine. It never blocks a pick or a commit.

isDateDisabled and decorateDate may throw. The error is rethrown asynchronously and the day counts as enabled and undecorated. renderDate and validate follow the same rule: the day gets no content, and the value counts as valid.

UI options

#

Presentation and display behaviour:

OptionTypeDefaultDescription
displayMode"auto" | "docked" | "modal""auto"Which surface opens. "auto" uses the modal below 600 px wide or 480 px tall and the docked popover otherwise.
inline.enabledbooleanfalseRender the calendar permanently instead of opening it.
inline.containerstring | HTMLElementundefinedSelector or element for the inline picker.
formatstring"auto"Date text format: "auto" or a pattern of d, dd, M, MM, yy, yyyy with one separator of /, ., - or a space.
themeThemeName"basic"Theme name.
colorScheme"auto" | "light" | "dark""auto"Light or dark. "auto" detects it when the picker opens.
fullscreenboolean | numbertrueWidth below which a modal range picker goes full screen. true means 600 px, a number is a width in pixels, false means never.
toggleButtonstring | HTMLElementundefinedExtra element that opens the picker, such as a calendar icon button.
weekNumbersbooleanfalseShow ISO week numbers before each row.
outsideDaysboolean | { selectable?: boolean }falseShow days of neighbouring months. true keeps them selectable, { selectable: false } makes them inert.
fixedWeeksbooleanfalseAlways show six rows.
startView"day" | "month" | "year""day"Panel shown first. Ignored in range mode and for month or year precision.
endInputstring | HTMLElementundefinedSecond page input for a range. Read on create() and used in range mode only. A value that is not an <input> emits invalid-option.
yearRange.beforenumber100Years offered before the current year.
yearRange.afternumber20Years offered after the current year.
todayButtonbooleanfalseShow the Today button in the footer.
clearButtonboolean | { clearInput?: boolean }falseShow the Clear button. true also clears and commits the input.
clearButton.clearInputbooleantrueWith false, Clear only empties the selection in the picker. Nothing is committed and the picker stays open.
footerbooleanundefinedShow the footer. Unset means shown, except inline. true or false forces it.
animationbooleantruePlay motion. With prefers-reduced-motion: reduce only short fades remain.
allowPageScrollbooleanfalseKeep the page scrollable while the modal is open.
cssClassstring""Extra class names for the picker surface, separated by spaces.
appendTostring | HTMLElementundefinedWhere the modal dialog is appended. Defaults to the host.
swipebooleantrueDrag, wheel and swipe between months.
viewSwitchbooleantrueShow the button that switches between the calendar and the input view.
initialView"calendar" | "input""calendar"View shown on open, where the input view is supported.
maskbooleanfalseFormat typed digits to the date format while typing. Single mode and the two range fields, day precision only.

The input view exists for single pickers in a modal and for every range picker. Multiple pickers have no input view. The theme names are basic, m3-green, crane, crane-straight, m2, glassmorphic, pastel, ai, cyberpunk and blueprint.

Labels options

#

Every visible and assistive text is a label. Month and weekday names come from Intl, not from labels.

OptionDefaultUsed for
title"Select date"Modal header supporting text
monthTitle"Select month"Header supporting text with calendar.precision: "month"
yearTitle"Select year"Header supporting text with calendar.precision: "year"
noDate"No date selected"Modal headline while nothing is selected
confirm"OK"Confirm button
cancel"Cancel"Cancel button
today"Today"Today button
clear"Clear"Clear button
openCalendar"Choose date"Accessible name of the toggle button
previousMonth"Previous month"Previous month button
nextMonth"Next month"Next month button
previousYear"Previous year"Previous year button
nextYear"Next year"Next year button
chooseMonth"Choose month"Month menu button and list
chooseYear"Choose year"Year menu button and list
weekNumber"Week"Week number column header
invalidDate"Enter a valid date"Message for typed text that is not a date
unavailableDate"This date is not available"Message for a typed date that is disabled
rangeTitle"Select dates"Header supporting text in range mode
rangeStart"Start"Headline placeholder for a missing range start
rangeEnd"End"Headline placeholder for a missing range end
multipleSelected"{count} selected"Headline in multiple mode. A PluralLabel.
save"Save"Save button of the full-screen range picker
close"Close"Close button of the full-screen range picker
switchToInput"Switch to text input"Name of the button that shows the input view
switchToCalendar"Switch to calendar"Name of the button that shows the calendar view
dateField"Date"Text field label in single mode
startDateField"Start date"Start text field label in range mode
endDateField"End date"End text field label in range mode
invalidRange"End date must be on or after the start date"Message for a range that is reversed or too long or short
presets"Presets"Accessible name of the range presets group
beforeMinDate"Enter a date on or after {date}"Message for a typed date before minDate. {date} is the limit in the display format.
afterMaxDate"Enter a date on or before {date}"Message for a typed date after maxDate. {date} is the limit in the display format.

multipleSelected is a PluralLabel: a string, or an object keyed by Intl.PluralRules categories. {count} is replaced by the number of dates.

index.ts
new DatepickerUI("#date", {
calendar: { mode: "multiple" },
labels: {
multipleSelected: { one: "{count} date", other: "{count} dates" },
},
}).create();

Behavior options

#

Interaction rules:

OptionTypeDefaultDescription
closeOnSelectbooleanfalseCommit and close as soon as a day is picked. Not used in multiple mode.
closeOnCancelbooleantrueClose the picker when the Cancel button is pressed.
commitOnChangebooleanfalseCommit every change to the input without the confirm button.
ignoreOutsideClickbooleanfalseKeep the picker open when the user clicks outside of it.
returnFocusbooleantrueMove focus back to the input when the picker closes.
idstringundefinedInstance id for DatepickerUI.getById().

Callbacks options

#

Each callback receives the payload of its event. The payload types and when each event fires are on the Events page.

OptionTypeDefaultDescription
onOpen(data: OpenEventData) => voidundefinedCalled on the open event.
onClose(data: CloseEventData) => voidundefinedCalled on the close event.
onCancel(data: CancelEventData) => voidundefinedCalled on the cancel event.
onConfirm(data: ConfirmEventData) => voidundefinedCalled on the confirm event.
onUpdate(data: UpdateEventData) => voidundefinedCalled on the update event.
onError(data: ErrorEventData) => voidundefinedCalled on the error event.
onSelectDay(data: SelectDayEventData) => voidundefinedCalled on the select:day event.
onSelectMonth(data: SelectMonthEventData) => voidundefinedCalled on the select:month event.
onSelectYear(data: SelectYearEventData) => voidundefinedCalled on the select:year event.
onNavigate(data: NavigateEventData) => voidundefinedCalled on the navigate event.
onRangeStart(data: RangeStartEventData) => voidundefinedCalled on the range:start event.
onRangeEnd(data: RangeEndEventData) => voidundefinedCalled on the range:end event.

Shapes used by the options

#

DateDecoration is what calendar.decorateDate returns. RangePreset and RangePresetValue describe calendar.range.presets.

OptionTypeDefaultDescription
DateDecoration.classNamestringundefinedClass name added to the day cell.
DateDecoration.badgebooleanundefinedShow a small dot on the day.
DateDecoration.labelstringundefinedText appended to the accessible name of the day.
RangePreset.labelstringrequiredText of the preset button.
RangePreset.valueRangePresetValue | (() => RangePresetValue)requiredThe range, or a function that returns it. The function runs each time the picker refreshes, so relative presets stay current.
RangePresetValue.startDate | stringrequiredFirst day of the range.
RangePresetValue.endDate | stringrequiredLast day of the range, on or after start.
index.ts
new DatepickerUI("#date", {
calendar: {
decorateDate: (date) =>
date.getDate() === 1
? { className: "first-of-month", badge: true, label: "First of the month" }
: undefined,
},
}).create();
index.ts
const day = 24 * 60 * 60 * 1000;
new DatepickerUI("#range", {
calendar: {
mode: "range",
range: {
presets: [
{
label: "Last 7 days",
value: () => ({
start: new Date(Date.now() - 6 * day),
end: new Date(),
}),
},
{ label: "Q4 2026", value: { start: "2026-10-01", end: "2026-12-31" } },
],
},
},
}).create();

A preset click completes the range as if the user had picked both ends. It emits range:end, not select:day, and follows behavior.closeOnSelect and behavior.commitOnChange. A preset is disabled when its value is invalid or the length limits refuse the range.

Esc