Litopis GitHub

@litopis/dom and @litopis/core

API reference

Public APIs for @litopis/core and @litopis/dom.

DateValue

Litopis represents a calendar date without a time or time zone. Months and days are one-based; supported years are 1 through 9999.

ts
interface DateValue {
  readonly day: number;
  readonly month: number;
  readonly year: number;
}

DateValue is the default public value. Use valueAs: "date" when the application works with native Date instances.

A valid value has year: 1…9999, month: 1…12 and a day valid for that month; for example { year: 2026, month: 7, day: 29 }.

ts
interface DateRange {
  readonly start: DateValue | null;
  readonly end: DateValue | null;
}

Value output

The calendar keeps date-only values internally. The controller can expose the same selection in the form that fits the consuming code.

ts
const picker = createDatePicker(root, {
  format: "dd.mm.yyyy",
  valueAs: "date",
});

picker.getValue();          // Date | null
picker.getInputValue();     // "29.02.2024"
picker.getISOValue();       // "2024-02-29"

getInputValue() is the exact value shown in the field, including the range separator. getISOValue() is always an ISO value for forms and storage. With valueAs: "date", selected, range, setDate() and setRange() also accept local Date instances. Litopis reads their local year, month and day and returns local-noon Date instances so a calendar day is not shifted at a daylight-saving transition.

selection and valueAs determine the return type together. Pass literals directly, or preserve them with satisfies when options are stored first.

ts
import {
  createDatePicker,
  type DatePickerOptions,
  type DatePickerRange,
  type DateValue,
} from "@litopis/dom";

const dateValuePicker = createDatePicker(root);
const dateValue: DateValue | null = dateValuePicker.getValue();

const nativeDatePicker = createDatePicker(root, { valueAs: "date" });
const nativeDate: Date | null = nativeDatePicker.getValue();

const rangeOptions = {
  selection: "range",
  valueAs: "date",
} satisfies DatePickerOptions<"date", "range">;

const rangePicker = createDatePicker(root, rangeOptions);
const range: DatePickerRange<"date"> = rangePicker.getValue();
Options getValue()
Default DateValue | null
valueAs: "date" Date | null
selection: "range" { start: DateValue | null; end: DateValue | null }
selection: "range", valueAs: "date" { start: Date | null; end: Date | null }

Period boundaries

Month and year selections represent complete periods in values sent to an application or a form. Field text remains at the selected precision.

Granularity Single value / range start Range end Field text
"day" The selected day The selected day Configured date format
"month" First day of the month Last day of the month; February 2024 ends on 2024-02-29 YYYY-MM or MM.YYYY
"year" January 1 December 31 YYYY

For example, selecting February through March 2024 yields 2024-02-01/2024-03-31 from getISOValue(), while a field with format: "dd.mm.yyyy" displays 02.2024 – 03.2024.

createDatePicker

Mounts a date field and calendar into an existing element.

ts
function createDatePicker(
  root: HTMLElement,
  options?: DatePickerOptions,
): DatePickerController;

DatePickerOptions

Literal unions below are the complete set of accepted variants. Text options accept user-facing text; locale accepts a supported BCP 47 tag such as "uk-UA".

Option Type Default Description
mode "inline" | "popover" "inline" "inline" stays in document flow; "popover" opens from the field.
selection "single" | "range" "single" "single" chooses one period; "range" chooses start then end.
granularity "day" | "month" | "year" "day" Chooses days, months or years. Period output uses real calendar boundaries; field text remains at the selected precision.
range { start: DateValue | Date | null; end: DateValue | Date | null } { start: null, end: null } Initial range for selection: "range"; a partial range may have only start. Endpoints are ordered chronologically.
layout "single" | "split" "split" for range "single" uses one start – end field; "split" uses From and To fields. It applies only to ranges.
panels 1 | 2 | "auto" "auto" for range 1 shows one month; 2 shows adjacent months; "auto" uses two when the container is at least 640px wide.
closeOnSelect boolean true true closes a popover after selection; false leaves it open. Inline calendars stay open.
clearButton boolean false true adds a Clear footer action; false omits it.
clearLabel string "Clear" Any visible text for Clear; for example "Reset dates".
firstDayOfWeek 0 | 1 | 2 | 3 | 4 | 5 | 6 Locale-derived Overrides locale: 0 Sunday through 6 Saturday; for example 1 starts weeks on Monday.
format "yyyy-mm-dd" | "dd.mm.yyyy" | "mm/dd/yyyy" "yyyy-mm-dd" Visible mask and parsing: "yyyy-mm-dd" → 2026-07-29; "dd.mm.yyyy" → 29.07.2026; "mm/dd/yyyy" → 07/29/2026.
label string | { start: string; end: string }; for example "Travel date" "Date"; "Start" / "End" for split Visible label and accessible name. A range object labels split fields; for example { start: "Departure", end: "Return" }.
locale Supported BCP 47 tag; for example "uk-UA" Browser locale Omit it for the browser language. "uk-UA" localizes labels; invalid tags fall back to "en-US".
min DateValue Inclusive earliest selectable date; for example { year: 2026, month: 7, day: 1 }.
max DateValue Inclusive latest selectable date; for example { year: 2026, month: 7, day: 31 }.
onValueChange (value: DateValue | Date | null) => void Called after a single value changes. Its value follows valueAs; use it to synchronize application state.
valueAs "date-value" | "date" "date-value" Chooses the representation returned by selection APIs and change callbacks: a DateValue object or a local native Date.
selected DateValue | Date | null null Initial single value. Use null for none; use range for range mode.
onRangeChange (range) => void Called after either endpoint changes. The endpoint type follows valueAs; the completed end is expanded to the final day of a selected month or year.
name string | { start: string; end: string }; for example "period" Native FormData name. A split range derived from "stay" submits stay[start] and stay[end]; pass an object only when the endpoints need different names. A one-field range serializes full ISO boundaries, for example 2024-02-01/2024-03-31.
outsideDays boolean true true shows subdued adjacent-month dates; false leaves their cells empty.
season boolean false true adds a localized season beside the caption; false omits it.
todayButton boolean false true adds a Today footer action; false omits it.
size "compact" | "comfortable" "compact" "compact" uses 40px controls; "comfortable" uses at least 44px controls.
today DateValue Local current date Overrides the local current date; for example { year: 2026, month: 7, day: 29 } for deterministic tests.
todayLabel string "Today" Any visible text for Today; for example "Jump to today".

DatePickerController

Method Result Description
open() void Opens a popover calendar.
close() void Closes a popover calendar and restores its closed state.
toggle() void Toggles popover visibility.
getValue() DateValue | Date | null, or { start, end } for range Returns the selected value. Its shape follows selection; its endpoint type follows valueAs.
getInputValue() string Returns the formatted field text; a range uses start – end.
getISOValue() string Returns ISO YYYY-MM-DD, a complete range as start/end with complete period boundaries, or an empty string.
setDate(value) void Sets or clears selection and updates the input.
setRange(range) void Sets or clears range endpoints and synchronizes the fields and native form values.
setVisibleMonth(value) void Changes the month currently displayed.
setOptions(options) void Replaces options without remounting; selection is preserved unless supplied.
goToToday() void Focuses and reveals today within configured bounds.
destroy() void Removes listeners, generated DOM and Litopis state attributes.

createDateField

Mounts only the masked text field. It is useful when the application provides its own calendar surface or needs typed date entry without a picker.

ts
const field = createDateField(root, {
  format: "dd.mm.yyyy",
  label: "Invoice date",
  min: { day: 1, month: 1, year: 2026 },
});

field.getDate();
field.getISOValue();
field.isValid();
field.setDate({ day: 16, month: 7, year: 2026 });
field.destroy();

DateFieldOptions

Option Accepted value Default Effect
format "yyyy-mm-dd" | "dd.mm.yyyy" | "mm/dd/yyyy" "yyyy-mm-dd" Input mask and parser; for example "dd.mm.yyyy" accepts 29.07.2026.
label Visible text; for example "Invoice date" "Date" Visible label and accessible name.
min DateValue Inclusive lower bound; dates before it are invalid.
max DateValue Inclusive upper bound; dates after it are invalid.
value DateValue | null null Initial value; null starts with an empty field.

Core exports

@litopis/core has no DOM dependency and can be used for custom renderers, server-side validation and deterministic calendar calculations.

Date math

addDays, addMonths, addYears, startOfMonth, endOfMonth, getDaysInMonth

Comparison and validation

compareDates, clampDate, isSameDate, isValidDateValue, isDateDisabled

Formatting

formatDate, toIsoDate, toLocalDate, getToday

Calendar state

createCalendarState, createCalendarGrid, moveFocus, focusDate, selectDate, selectFocusedDate