Skip to content

Options ​

All options are passed as the second argument to new Datepicker(el, options).

Core ​

OptionTypeDefaultDescription
formatstring'YYYY-MM-DD'Date format string. Tokens: YYYY MM DD HH mm ss.
localestring | LocaleConfig'sk'Locale identifier or full locale config object.
valuestring | Date—Initial selected date.
defaultValuestring | Date—Alias for value (used when value is uncontrolled).
mode'single' | 'range' | 'multiple''single'Selection mode.
theme'light' | 'dark' | 'auto''auto'Color theme.

Constraints ​

OptionTypeDefaultDescription
minDatestring | Date—Earliest selectable date. Cells before this date are visually disabled and not clickable.
maxDatestring | Date—Latest selectable date. Cells after this date are visually disabled and not clickable.
minDateTitlestringlocale defaultTooltip shown on cells that fall before minDate. Overrides the locale string.
maxDateTitlestringlocale defaultTooltip shown on cells that fall after maxDate. Overrides the locale string.
disabledDatesDate[] | ((d: Date) => boolean | Promise<boolean>)—Specific dates or predicate to disable.
disabledWeekdaysnumber[][]Weekday indices to disable (0=Sun … 6=Sat).
maxRangeDaysnumber0Max span of a range selection (0 = unlimited).
minRangeDaysnumber0Min span of a range selection.
maxSelectionsnumber0Max number of multiple selections (0 = unlimited).

Display ​

OptionTypeDefaultDescription
position'auto' | 'top' | 'bottom' | 'left' | 'right''auto'Dropdown placement.
zIndexnumber1000z-index of the dropdown.
animation'fade' | 'slide' | 'none''fade'Open/close animation.
inlinebooleanfalseRender calendar inline (always visible).
numberOfMonthsnumber1Number of months visible side-by-side.
fixedHeightbooleanfalseAlways render 6 rows (prevents layout shift).
showWeekNumbersbooleanfalseShow ISO week number column.
weekNumberSystem'iso' | 'us''iso'Week numbering system.
weekStart0-6locale defaultFirst day of week (0=Sun, 1=Mon …).
weekdayFormat'short' | 'narrow' | 'long''short'Weekday header format.
showTodayButtonbooleanfalseShow "Today" footer button.
showClearButtonbooleanfalseShow "Clear" footer button.
showConfirmButtonbooleanfalseShow "OK" confirm button (defers selection).
showCancelButtonbooleanfalseShow "Cancel" button.
showToggleIconbooleantrueShow calendar icon in input (via CSS).
showHeaderbooleantrueShow month/year navigation header.
highlightedDatesDate[]—Dates to mark with vdp-cell--highlighted class.

Behaviour ​

OptionTypeDefaultDescription
openOnFocusbooleantrueOpen dropdown on input focus.
closeOnSelectbooleantrueClose after date selection.
allowManualInputbooleantrueAllow typing in the input field.
readonlyInputbooleanfalseMake input read-only.
autofillbooleantrueParse + format raw input on blur.
strictModebooleanfalseFire vdp:invalid on blur if text can't be parsed.
emptyOkbooleantrueAllow empty value.
keepFocusbooleanfalseReturn focus to the input after close (only when the calendar held focus). See Keyboard & focus.
initialView'days' | 'months' | 'years''days'Which view to open on.
containerHTMLElementdocument.bodyPortal target for the dropdown.

Callbacks ​

Every callback below is read at the moment its event fires, so all of them can be added, swapped or removed on a live instance with setOptions() — passing undefined unregisters one.

OptionSignatureDescription
onOpen({ month, from, to }: OpenRange) => void | Promise<void>Called once when calendar opens. month = 1st of displayed month; from/to = full visible grid range. Awaited before onCellRender.
onMonthChange({ month, from, to }: OpenRange) => void | Promise<void>Called on every month navigation (not on initial open). Same shape as onOpen. Awaited before onCellRender.
onClose(reason: CloseReason) => voidCalled when calendar closes.
onChange(value: string, event: DatepickerChangeEvent) => boolean | void | Promise<boolean | void>Called when selected date changes. Return false (or Promise<false>) to keep the calendar open — useful for async validation that fails after the value is set.
onInput(raw: string) => voidCalled on every keystroke in the input.
onInvalid(error: DatepickerError) => voidCalled when an invalid value is rejected.
onViewChange(view: CalendarView) => voidCalled when the calendar view changes.
onYearChange(year: number) => voidCalled when the displayed year changes.
onCellRender(ctx: CellRenderContext) => CellRenderResult | Promise<CellRenderResult>Called per visible day cell for async customisation.
onBeforeOpen() => boolean | Promise<boolean>Return false to cancel opening.
onBeforeChange(next: Date, prev: Date | null) => boolean | Promise<boolean>Return false to cancel selection.
onBeforeMonthChange(next: Date, prev: Date) => boolean | Promise<boolean>Return false to cancel navigation.
validate(date: Date) => boolean | string | Promise<boolean | string>Custom validation; return false or error string to reject.

Keeping the calendar open from onChange ​

Return false (or a Promise resolving to false) from onChange to prevent the calendar from closing after a date is selected. This is useful when you run async validation after the value is committed and need to give the user a chance to correct their choice.

js
new Datepicker('#dp', {
  format: 'YYYY-MM-DD',
  onChange: async (value, event) => {
    const isValid = await myServerValidate(event.date);
    if (!isValid) {
      showError('This date is not available');
      return false; // calendar stays open
    }
    // returning nothing (or void) closes the calendar normally
  },
});

Outside-click / Escape protection while onChange is pending

While onChange is awaited (e.g. your handler shows a confirm dialog), the calendar is automatically protected from being closed by an outside click or the Escape key. Any such close attempt is silently blocked until onChange resolves. Only a programmatic dp.close() call will still work.

This means you can safely show a modal or confirm() dialog inside onChange without the calendar disappearing under it:

js
onChange: async (value, event) => {
  try {
    // Calendar stays open while the user decides in the dialog,
    // even if they click outside the calendar.
    await showConfirmDialog('Is this date correct?');
  } catch {
    dp.setValue('');
    return false; // user cancelled — keep calendar open
  }
},

Note: The value is already applied to the input before onChange is called. If validation fails and you want to also clear the value, call dp.setValue('') inside the handler before returning false.

Difference from onBeforeChange: onBeforeChange runs before the value is set and prevents the commit entirely. onChange runs after the value is set and can only prevent the calendar from closing — the value change itself has already happened.

Appearance ​

OptionTypeDescription
classNamesPartial<ClassNames>Override any default class name. See Theming.
prevButtonContentstringHTML string for the previous-month button (default: built-in SVG arrow). Accepts a Unicode character, plain text, or an SVG string.
nextButtonContentstringHTML string for the next-month button (default: built-in SVG arrow). Accepts a Unicode character, plain text, or an SVG string.

Custom navigation arrows ​

Pass any HTML string — a Unicode character, text, or an inline SVG — to replace the default arrow icons:

js
// Unicode characters
new Datepicker('#dp', {
  prevButtonContent: '‹',
  nextButtonContent: '›',
});

// Double angle quotes
new Datepicker('#dp', {
  prevButtonContent: '«',
  nextButtonContent: '»',
});

// Inline SVG
new Datepicker('#dp', {
  prevButtonContent: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>',
  nextButtonContent: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>',
});

Released under the MIT License.