Documentation

Complete API reference and usage guide for bos-nepali-date — a React component for selecting Bikram Sambat (Nepali) dates with a pluggable conversion engine. API design follows Ant Design DatePicker conventions.

CSS must be imported separately — the npm package does not auto-inject styles. Add one of the following to your app:

// Option 1 (recommended)
import 'bos-nepali-date/style';

// Option 2
import 'bos-nepali-date/index.css';

For the UMD build (docs site), include the CSS file directly:

Getting started

$ npm install bos-nepali-date
import { useState } from "react"
import { NepaliDatePicker, defaultAdapter } from "bos-nepali-date"

function Demo() {
  const [value, setValue] = useState(null)
  return (
    <NepaliDatePicker
      value={value}
      onChange={setValue}
      adapter={defaultAdapter}
    />
  )
} 
Loading live example...
// Renders:

Basic usage

The onChange callback receives a BsDate object or null (when cleared).

// BsDate shape
{
  year: number, // e.g. 2080
  month: number, // 1–12 (Baishak–Chaitra)
  day: number // 1–32
}
// Range picker usage
import { NepaliDateRangePicker } from "bos-nepali-date"

function RangeDemo() {
  const [range, setRange] = useState([null, null])
  return (
    <NepaliDateRangePicker
      value={range}
      onChange={setRange}
      adapter={defaultAdapter}
    />
  )
} 
Loading live example...
⏎ Live Select start and end dates — the range highlights inline. Open full demo →

Common props

These props are shared by both NepaliDatePicker and NepaliDateRangePicker.

Basic

PropTypeDefaultDescription
value BsDate | null / [BsDate|null, BsDate|null] Controlled value. Single picker: BsDate | null. Range picker: tuple [start, end]. Use undefined (omit) for uncontrolled mode.
defaultValue BsDate | null / [BsDate|null, BsDate|null] null Default value for uncontrolled mode. Only used when value is not provided. Single: BsDate | null. Range: tuple [start, end].
onChange (date: BsDate|null) => void / ([BsDate|null, BsDate|null]) => void Callback when selection changes. Single: receives date or null. Range: receives [start, end] tuple.
adapter BsAdapter defaultAdapter Conversion engine for BS↔AD arithmetic. Ships with defaultAdapter (includes full BS year data for 2000–2099) and MemoryBsAdapter (custom year tables).
placeholder string "YYYY-MM-DD (BS)" Placeholder text for the input field(s).
disabled boolean false Disable the entire picker. No interaction, input is grayed out.

Date control

PropTypeDefaultDescription
minDate BsDate Earliest selectable date. Dates before this are disabled. Combines with other disable rules.
maxDate BsDate Latest selectable date. Dates after this are disabled. Combines with other disable rules.
disabledDate (date: BsDate) => boolean Callback to dynamically disable individual dates. Called per calendar cell. Return true to prevent selection.

Display

PropTypeDefaultDescription
variant 'outlined' | 'filled' | 'borderless' | 'underlined' 'outlined' Visual style of the picker input. outlined has border, filled has background fill, borderless has no border, underlined shows only a bottom border.
size 'small' | 'middle' | 'large' 'middle' Adjusts input height, font size, and popover sizing.
status 'error' | 'warning' Applies validation state colors to the input border and background.
placement 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight' 'bottomLeft' Popover placement relative to the trigger input. Automatically flips to opposite side when insufficient space.
allowClear boolean false Show a × clear button inside the input when a value is selected.
inputReadOnly boolean false Set the input to read-only. Calendar selection via popover still works.
autoFocus boolean false Auto-focus the trigger input on mount.

Localization

PropTypeDefaultDescription
menu MenuOptions {} Localization and display options. See Menu options for details.

Customization

PropTypeDefaultDescription
className string Extra CSS class for the root wrapper element.
classNames PickerClassNames {} Semantic class names for sub-elements. See classNames & styles.
styles PickerStyles {} Semantic inline styles for sub-elements. See classNames & styles.
cellRender (date: BsDate, info: CellRenderInfo) => React.ReactNode Custom render function for date cells. Receives the date and a CellRenderInfo object with status flags.
renderExtraFooter () => React.ReactNode Custom React node rendered at the bottom of the popover, above the Clear/Today footer buttons.
inputPattern string | false \d{4}-\d{2}-\d{2} Native HTML pattern attribute on the input. Set false to remove.
Loading live example...
⏎ Live
Open full demo →

Popover control

PropTypeDefaultDescription
open boolean Controlled popover visibility. When provided, the parent controls open/close state.
onOpenChange (open: boolean) => void Callback when popover opens or closes. Required with open for controlled mode.
getPopupContainer (trigger: HTMLElement) => HTMLElement document.body Custom DOM container for the popover portal. Useful for containing within a scrollable parent.

Events

PropTypeDefaultDescription
onFocus () => void Called when the trigger input gains focus.
onBlur () => void Called when the trigger input loses focus.
onKeyDown (e: React.KeyboardEvent<HTMLInputElement>) => void Called on keydown on the trigger input.
onPanelChange (date: BsDate) => void Called when the calendar panel navigates to a different month/year via the header controls or arrow buttons.
name string Native name attribute for the input element. Use with form libraries like React Hook Form.

NepaliDatePicker

The single date picker component. Accepts all common props plus the following:

PropTypeDefaultDescription
label string "Select date" Visible label text when showLabel is enabled. Also used as aria-label on the input.
showLabel boolean false Render a visible label above the input. The label uses htmlFor/id association with the input.
disable DisableOptions {} Static disable rules. See Disable options.
inputClassName string Extra CSS class for the <input> element. Alternative to classNames.input.
// Full featured single picker
<NepaliDatePicker
  value={value}
  onChange={setValue}
  adapter={adapter}
  variant="outlined"
  size="middle"
  status="error"
  placement="bottomLeft"
  allowClear
  inputReadOnly
  disabledDate={(d) => d.day === 5}
  menu={{ lang: "en" }}
  classNames={{ popup: "my-popup" }}
  renderExtraFooter={() => <span>Custom footer</span>}
/> 

NepaliDateRangePicker

The range date picker component for selecting start and end dates. Accepts all common props plus the following:

PropTypeDefaultDescription
value [BsDate | null, BsDate | null] Controlled range value as [start, end]. Both can be null.
onChange (dates: [BsDate | null, BsDate | null]) => void Fired when the range changes via selection, input typing, or clear.
label string "Select date range" Visible label text when showLabel is enabled.
showLabel boolean false Render a visible label above the range inputs.
separator string "→" Separator displayed between the start and end inputs.
endPlaceholder string Placeholder for the end input. Falls back to placeholder.
disable DisableOptions {} Static disable rules applied to both dates. See Disable options.
presets Preset[] [] Quick-select preset ranges displayed as buttons above the footer. Each preset: { label: string, value: [BsDate, BsDate] }.
name / nameEnd string Native name attributes for the start and end inputs. name for start, nameEnd for end.
// Range picker with all options
<NepaliDateRangePicker
  value={[start, end]}
  onChange={setRange}
  adapter={fullAdapter}
  minDate={{ year: 2080, month: 1, day: 1 }}
  maxDate={{ year: 2085, month: 12, day: 30 }}
  separator="to"
  size="small"
  variant="filled"
  allowClear
  menu={{ lang: "ne" }}
/>

Range selection behavior

Disable options

Pass a disable object to control which dates cannot be selected. These static rules combine with the disabledDate callback — if any rule marks a date as disabled, it will be unselectable.

PropertyTypeDefaultDescription
disable.todaybooleanfalsePrevent selecting today's date.
disable.dateBsDateDisable a single specific date.
disable.datesBsDate[][]Disable a list of specific dates.
disable.beforeBsDateDisable all dates before this date (exclusive).
disable.afterBsDateDisable all dates after this date (exclusive).
// Disable today + block specific dates + block past dates
<NepaliDatePicker
  disable={{
    today: true,
    dates: [
      { year: 2081, month: 1, day: 1 },
      { year: 2081, month: 1, day: 15 },
    ],
    before: { year: 2081, month: 1, day: 10 },
  }}
  disabledDate={(d) => d.day === 5} // also disable every 5th
/> 
Combines with disabledDate: Both the static disable object and the disabledDate callback are evaluated independently. A date is disabled if any rule applies. Use minDate/maxDate for simple ranged clamping instead of disable.before/disable.after.

The menu prop controls localization, calendar layout, and visibility of navigation controls.

PropertyTypeDefaultDescription
menu.lang'en' | 'ne''en'Localize month/day labels and digits to English or Nepali (नेपाली).
menu.showMonthbooleantrueShow/hide the month selector dropdown in the popover header.
menu.showYearbooleantrueShow/hide the year selector dropdown in the popover header.
menu.firstDayOfWeek0 | 10Start the week on Sunday (0) or Monday (1).
menu.yearRange{ min?: number; max?: number }adapter rangeOverride the year dropdown range. Takes priority over adapter.range. Example: { min: 2075, max: 2090 }.
// Nepali locale with Monday start, hide year selector
<NepaliDatePicker
  menu={{
    lang: "ne",
    firstDayOfWeek: 1,
    showMonth: true,
    showYear: false,
  }}
/> 

Localization behavior

OptionLabelsDigitsValue format
menu.lang="en" (default)English month/day names0–92081-01-15
menu.lang="ne"नेपाली month/day names०-९२०८१-०१-१५ (display) / 2081-01-15 (value)

The input accepts Nepali digits (०-९) and normalizes them to ASCII automatically. The onChange value always returns ASCII BS dates.

classNames & styles

Both pickers accept classNames and styles props for granular styling of sub-elements. These follow the same pattern as Ant Design's classNames/styles API.

PickerClassNames

KeyTarget elementDescription
input<input> elementAdditional class for the text input.
popup.np-popover dialogAdditional class for the popover wrapper.
header.np-popover__headerAdditional class for the month/year header.
grid.np-cal-gridAdditional class for the calendar grid.
cell.np-cal-cell buttonsAdditional class for each day cell button.
footer.np-footerAdditional class for the footer (Clear/Today).

PickerStyles

KeyTarget elementDescription
input<input> elementInline styles for the text input.
popup.np-popover dialogInline styles for the popover wrapper.
header.np-popover__headerInline styles for the month/year header.
grid.np-cal-gridInline styles for the calendar grid.
footer.np-footerInline styles for the footer (Clear/Today).
<NepaliDatePicker
  classNames={{
    popup: "my-custom-popup",
    cell: "my-custom-cell",
    footer: "dark-mode-footer",
  }}
  styles={{
    popup: { borderRadius: "16px" },
    header: { background: "#fef3c7" },
  }}
/>

Styling

The picker's base styles are auto-imported from the CSS bundle. Override these CSS variables to theme the component.

CSS Variables

VariableDefaultDescription
--np-fontinherits hostFont family for all picker controls.
--np-popover-min-width280pxMinimum calendar popover width.
--np-popover-max-width320pxMaximum calendar popover width.
--np-color-error#ef4444Border/bg color for status="error".
--np-color-warning#f59e0bBorder/bg color for status="warning".
--np-underline-color--np-primaryUnderline border/shadow color for variant="underlined" on focus.
--np-underline-border--np-borderBottom border color for variant="underlined" when idle.
--np-filled-bg#f8f9faBackground color for variant="filled".
--np-sm-height24pxInput height for size="small".
--np-md-height32pxInput height for size="middle" (default).
--np-lg-height40pxInput height for size="large".
/* Custom theme override */
.np-picker {
  --np-font: "Noto Sans Devanagari", sans-serif;
  --np-popover-min-width: 300px;
  --np-color-error: #dc2626;
  --np-color-warning: #d97706;
}

Adapter

The adapter is the conversion engine that translates between Bikram Sambat (BS) and Gregorian (AD) dates. The library ships with two built-in adapters.

defaultAdapter

Pre-configured with demo data for BS years 2080–2081. Suitable for evaluation and development. Not recommended for productiontoAD() and toBS() throw for dates outside this range.

MemoryBsAdapter

Create a custom adapter with your own complete year table for production use.

import { MemoryBsAdapter } from "bos-nepali-date"

const adapter = new MemoryBsAdapter({
  anchorBs: { year: 2000, month: 1, day: 1 },
  anchorAdIso: "1943-04-14",
  yearTable: {
    2080: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31],
    2081: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30],
  },
})
Full data included: The published NPM package ships with complete BS year data for 2000–2099 (100 years) in defaultAdapter. No need to provide your own table unless you need years beyond this range. For custom tables, use MemoryBsAdapter or implement the BsAdapter interface.

BsAdapter interface

Implement this interface to provide your own conversion logic, e.g., from an API or database.

// BsAdapter interface
{
  toAD: (date: BsDate) => AdDateIso
  toBS: (date: AdDateIso) => BsDate
  addDays: (date: BsDate, days: number) => BsDate
  diffDays: (date1: BsDate, date2: BsDate) => number
  today: () => BsDate
  range?: { min?: BsDate; max?: BsDate }
}
// Custom adapter example (e.g., API-backed)
const apiAdapter: BsAdapter = {
  toAD: (date) => { /* POST /convert-to-ad */ },
  toBS: (iso) => { /* POST /convert-to-bs */ },
  addDays: (date, days) => { /* POST /add-days */ },
  diffDays: (a, b) => { /* POST /diff */ },
  today: () => { /* GET /today-bs */ },
  range: { min: { year: 2000, month: 1, day: 1 }, max: { year: 2090, month: 12, day: 30 } },
}

TypeScript

All components and types are fully typed. Key exports:

// Core types
type BsDate = { year: number; month: number; day: number }
type AdDateIso = string // "YYYY-MM-DD"
interface BsAdapter { toAD; toBS; addDays; diffDays; today; range? }

// Picker prop types
type PickerSize = 'small' | 'middle' | 'large'
type PickerStatus = 'error' | 'warning'
type PickerVariant = 'outlined' | 'filled' | 'borderless' | 'underlined'
type PickerPlacement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight'

// Options types
DisableOptions
MenuOptions
CellRenderInfo
NepaliDateRangePickerProps
// Import types:
import {
  type BsDate, type BsAdapter, type AdDateIso,
  type DisableOptions, type MenuOptions,
  type PickerSize, type PickerStatus,
  type PickerVariant, type PickerPlacement,
  type CellRenderInfo, type NepaliDateRangePickerProps,
} from "bos-nepali-date"

Accessibility

The picker components follow WAI-ARIA design patterns for accessible date picker widgets.

FeatureImplementation
Calendar semantics role="grid", role="gridcell" with aria-colindex, role="columnheader", role="row" wrappers. Each cell has aria-label with full date context (e.g., "15 Baishak, 2081 BS").
Selected state aria-selected on selected cells. Range picker highlights both start and end.
Disabled state Disabled cells have disabled attribute and are not focusable.
Modal dialog Popover uses role="dialog" with aria-modal="true" and aria-label.
Live region aria-live="polite" region announces month/year changes to screen readers.
Focus management Popover auto-focuses first focusable element on open. Focus returns to trigger input on close. Tab trapping within open popover.
Keyboard Escape closes the popover. Tab navigates between controls within the popover. Click-outside closes automatically.
Label association Visible labels use htmlFor/id association. Inputs have aria-label when no visible label.
Footer buttons Clear and Today buttons have aria-label in both English and Nepali.
Header controls Month/year toggles expose aria-haspopup="listbox" and aria-expanded. Previous/next buttons have aria-label.
Input Numeric mask enforces YYYY-MM-DD format. Accepts and normalizes Nepali digits (०-९) automatically.