@zephinax/react-datepicker-calendar

React Datepicker Calendar

Full documentation for the DatePicker and Calendar components that live in src/.

This project exposes a lightweight date picker with two entry points:

  • DatePicker: bundled input plus calendar popper.
  • Calendar: bare calendar grid for embedding in layouts.

Both components share the same selection logic and props. A "day" value is an object shaped as { year: number, month: number, day: number }. Range selection expects { from: Day | null, to: Day | null }, and multi-date selection uses Day[].

Explore the docs

Installation and setup

Install the package in your app and import the styles once:

npm i @zephinax/react-datepicker-calendar
# or
yarn add @zephinax/react-datepicker-calendar
import DatePicker, { Calendar, utils } from '@zephinax/react-datepicker-calendar';

The components require React 16.8+ (hooks) and inherit your project's font-family.

Working with values

// Single date
const [selectedDay, setSelectedDay] = useState<Day | null>(null);

// Range
const [selectedRange, setSelectedRange] = useState<{ from: Day | null; to: Day | null }>({
  from: null,
  to: null,
});

// Multi-date
const [selectedDays, setSelectedDays] = useState<Day[]>([]);

The value type you pass determines the selection mode (single, range, or multi). The picker enforces that shape and throws for malformed values.

Quick start examples

// Input + popper
<DatePicker
  value={selectedDay}
  onChange={setSelectedDay}
  inputPlaceholder="Select a day"
  shouldHighlightWeekends
/>;

// Inline calendar for ranges
<Calendar
  value={selectedRange}
  onChange={setSelectedRange}
  minimumDate={utils('en').getToday()}
  shouldHighlightWeekends
/>;

// Multi-date selection with disabled days
<Calendar
  value={selectedDays}
  onChange={setSelectedDays}
  disabledDays={[
    { year: 2025, month: 5, day: 12 },
    { year: 2025, month: 5, day: 25 },
  ]}
  onDisabledDayError={day => console.warn('Disabled:', day)}
/>;

DatePicker automatically closes after a single selection or after completing a range.

Shared calendar props (DatePicker & Calendar)

PropTypeDescriptionDefault
valueDay | Day[] | { from: Day | null; to: Day | null }Current selection; shape controls mode.null
onChange(value) => voidFired with the updated value.required
disabledDaysDay[]Exact days that cannot be picked.[]
onDisabledDayError(day) => voidCalled when the user attempts to select a disabled day or a range covering one.noop
minimumDate / maximumDateDayClamp selectable days and year/month selectors.null
shouldHighlightWeekendsbooleanAdds the weekend style to weekend cells based on locale.false
colorPrimary / colorPrimaryLightstringOverride accent colors via CSS variables.#d24670 / #edadc0
slideAnimationDurationstringDuration (e.g. 0.4s) used for header and grid transitions.0.4s
selectorStartingYear / selectorEndingYearnumberOptional year range. Defaults to today.year - 100 through today.year + 50.0 (auto)
locale'en' | 'fa' | Custom locale objectControls months, weekdays, numbering, labels, layout direction, and weekend days.'en'
calendarClassNamestringExtra class on the root calendar container.''
calendarTodayClassNamestringClass applied to "today" when not selected.undefined
calendarSelectedDayClassNamestringClass for selected single/multi dates.undefined
calendarRangeStartClassName / calendarRangeEndClassName / calendarRangeBetweenClassNamestringClasses for range edges and in-between days.undefined
customDaysClassName{ year: number; month: number; day: number; className: string }[]Add per-day class names (e.g., holidays).[]
renderFooter() => ReactNodeRender content inside the calendar footer.() => null

DatePicker-only props

PropTypeDescriptionDefault
inputPlaceholderstringPlaceholder text; falls back to locale default.''
inputClassNamestringExtra class for the input element.''
inputNamestringName attribute on the input.''
formatInputText() => stringProvide custom rendered input text. If returns a truthy string it overrides the built-in formatter.() => {}
renderInput({ ref }) => ReactNodeFully replace the input; forward ref to preserve focus/blur behavior.() => null
wrapperClassNamestringExtra class on the outer DatePicker wrapper.''
calendarClassNamestringExtra class applied to the calendar inside the popper.''
calendarPopperPosition'auto' | 'top'Force the popper to open above the input or let it flip automatically.'auto'
renderFooter() => ReactNodeFooter inside the popper's calendar (same as Calendar).() => null

Styling hooks

  • CSS variables: --cl-color-primary, --cl-color-primary-light, --animation-duration.
  • Class hooks: calendarTodayClassName, calendarSelectedDayClassName, range classes, and customDaysClassName let you target specific cells without overriding the whole stylesheet.
  • Wrapper classes: wrapperClassName (input wrapper) and calendarClassName (calendar root) help integrate with your design system.

Locale support and customization

Built-in locales: English (en, left-to-right, Sunday-first, weekends Sunday/Saturday) and Persian (fa, right-to-left, Monday-first, Jalali calendar, Persian digits). Pass a locale object to add another language. The object should mirror the built-in shape:

{
  months: string[];
  weekDays: { name: string; short: string; isWeekend?: boolean }[];
  weekStartingIndex: number;
  getToday: ({ year, month, day }) => Day;
  toNativeDate: (day: Day) => Date;
  getMonthLength: (day: Day) => number;
  transformDigit: (digit: string | number) => string;
  nextMonth: string;
  previousMonth: string;
  openMonthSelector: string;
  closeMonthSelector: string;
  openYearSelector: string;
  closeYearSelector: string;
  from: string;
  to: string;
  defaultPlaceholder: string;
  digitSeparator: string;
  yearLetterSkip: number;
  isRtl: boolean;
}

Utility helpers

utils(locale) exposes date helpers that respect the locale:

  • getToday() returns today's date in the current calendar.
  • getMonthName(month) / getMonthNumber(name).
  • getMonthLength({ year, month }).
  • getMonthFirstWeekday(date) with locale-specific week start.
  • isBeforeDate(day1, day2) and checkDayInDayRange({ day, from, to }).
  • getLanguageDigits(value) to format digits per locale.

Use these helpers for guards (e.g., minimumDate={utils('en').getToday()}) so your constraints match the calendar's rules.

Accessibility and keyboard behavior

  • Arrow keys move focus across days; Tab cycles through interactive elements. Enter activates a focused day.
  • Month/year selectors expose focusable buttons and respect min/max limits.
  • The popper closes when focus leaves the DatePicker or when a single/range selection completes.

Error handling

When a user attempts to pick a disabled day or a range that crosses one, onDisabledDayError receives that day so you can show a message or toast without mutating state.

You're ready to embed the picker, style it, and extend locales as needed—all using the components in src/.

On this page