npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@etpl/nepali-datepicker

v1.0.8

Published

Full-featured Nepali date picker for React — Bikram Sambat (BS) & Gregorian (AD) dual calendar, range selection, masked input, presets, dark mode, TypeScript support.

Readme

@etpl/nepali-datepicker — Complete Documentation

A full-featured Nepali (Bikram Sambat) date picker for React with dual BS/AD calendar system, Nepali/English locale, multiple picker modes, range selection, presets, and deep customisation.


Table of Contents

  1. Installation
  2. Quick Start
  3. All Props — Full Reference
  4. Picker Modes (mode prop)
  5. Variants — dropdown vs inline
  6. Calendar Systems — BS and AD
  7. Language / Locale
  8. Selection Types
  9. Typeable Input (Dropdown)
  10. Quick Presets
  11. Date Constraints
  12. DualDateValue — Return Type
  13. Theming — CSS Custom Properties
  14. Dark Mode
  15. classNames Override
  16. Custom Rendering
  17. Core Utilities (exported functions)
  18. TypeScript Types Reference
  19. All CSS Class Names
  20. Usage Examples — Every Variant

1. Installation

npm install @etpl/nepali-datepicker
# or
yarn add @etpl/nepali-datepicker

Import the component and its stylesheet:

import { NepaliDatePicker } from '@etpl/nepali-datepicker';
import '@etpl/nepali-datepicker/styles';   // or import the CSS from src/styles/index.css

2. Quick Start

import { NepaliDatePicker } from '@etpl/nepali-datepicker';
import '@etpl/nepali-datepicker/styles';

function App() {
  return (
    <NepaliDatePicker
      onChange={(val) => {
        console.log(val?.formatted.bs);  // "2081/04/15"
        console.log(val?.formatted.ad);  // "2024-07-30"
      }}
    />
  );
}

3. All Props — Full Reference

| Prop | Type | Default | Description | |------|------|---------|-------------| | variant | 'dropdown' \| 'inline' | 'dropdown' | Display variant | | mode | PickerMode | 'date' | What the picker selects (see §4) | | calendarSystem | 'BS' \| 'AD' | 'BS' | Primary calendar system | | defaultCalendarSystem | 'BS' \| 'AD' | 'BS' | Uncontrolled initial calendar system | | onCalendarSystemChange | (s: CalendarSystem) => void | — | Fires when user switches BS/AD | | showCalendarSystemToggle | boolean | true | Show BS/AD toggle in header | | language | 'ne' \| 'en' | 'ne' | UI language / numeral style | | defaultLanguage | 'ne' \| 'en' | 'ne' | Uncontrolled initial language | | onLanguageChange | (l: Language) => void | — | Fires when user switches language | | showLanguageToggle | boolean | false | Show ne/en toggle in header | | value | DualDateValue \| null | — | Controlled selected value | | defaultValue | DualDateValue \| null | — | Uncontrolled initial value | | onChange | (v: DualDateValue \| null) => void | — | Fires on date/year/month selection | | selectionType | 'single' \| 'range' \| 'multiple' | 'single' | How dates are selected | | startValue | DualDateValue \| null | — | Controlled range start | | endValue | DualDateValue \| null | — | Controlled range end | | onRangeChange | (start, end) => void | — | Fires on range selection | | showSecondaryDate | boolean | true | Show secondary (corner) date in day cells | | renderSecondaryDate | (cell: DualDayCell) => ReactNode | — | Custom secondary date render | | placeholder | string | locale default | Input placeholder text | | format | string | 'YYYY/MM/DD' | Date format string for input display | | showTodayButton | boolean | true | Show "Today" button in footer | | showClearButton | boolean | true | Show "Clear" button in footer | | showWeekNumbers | boolean | false | Show week number column | | showPresets | boolean | false | Show quick preset buttons panel | | presets | DatePreset[] | built-in | Custom preset items | | minDate | NepDate | — | Minimum selectable BS date | | maxDate | NepDate | — | Maximum selectable BS date | | disabledDates | NepDate[] | [] | Specific dates to disable | | disableWeekend | boolean | false | Disable Saturday (and Sunday) | | disabledDays | number[] | [] | Disable weekdays by index (0=Sun…6=Sat) | | disabledFn | (dual: DualDateValue) => boolean | — | Programmatic disable function | | theme | 'light' \| 'dark' \| 'system' | 'light' | Color theme | | classNames | Partial<CalendarClassNames> | — | CSS class overrides per element | | styles | Partial<Record<keyof CalendarClassNames, CSSProperties>> | — | Inline style overrides | | autoClose | boolean | true | Close dropdown after selection (dropdown only) | | position | 'auto' \| 'top' \| 'bottom' \| 'left' \| 'right' | 'auto' | Dropdown popover position | | zIndex | number | 9999 | Popover z-index | | disabled | boolean | false | Disable the picker entirely | | readOnly | boolean | false | Make input non-editable (click to open still works) | | id | string | — | HTML id for the input element | | name | string | — | HTML name for the input element | | ariaLabel | string | — | ARIA label for input | | onOpen | () => void | — | Fires when dropdown opens | | onClose | () => void | — | Fires when dropdown closes | | onMonthChange | (year, month, system) => void | — | Fires on month navigation | | onYearChange | (year, system) => void | — | Fires on year navigation | | renderDay | (cell: DualDayCell) => ReactNode | — | Fully custom day cell render | | renderHeader | (year, month, system) => ReactNode | — | Custom calendar header | | renderFooter | () => ReactNode | — | Custom calendar footer |


4. Picker Modes (mode prop)

| Mode | Opens On | Selection | formatted.bs returns | |------|----------|-----------|------------------------| | 'date' (default) | Day grid | Full date | "2081/04/15" | | 'month' | Month grid only | Month name | "04" (2-digit month index) | | 'year' | Year/decade grid only | Year | "2081" | | 'yearMonth' | Year grid → Month grid | Year + month | "2081/04" | | 'monthDay' | Month grid → Day grid | Month + day | full BS date | | 'week' | Day grid | ISO week | full BS date | | 'quarter' | — | Quarter | — | | 'halfYear' | — | H1/H2 | — |

Mode examples

// Year only — returns formatted.bs = "2081"
<NepaliDatePicker
  mode="year"
  onChange={(val) => console.log(val?.formatted.bs)} // "2081"
/>

// Month only — returns formatted.bs = "04"
<NepaliDatePicker
  mode="month"
  onChange={(val) => console.log(val?.formatted.bs)} // "04"
/>

// Year + Month — returns formatted.bs = "2081/04"
<NepaliDatePicker
  mode="yearMonth"
  onChange={(val) => console.log(val?.formatted.bs)} // "2081/04"
/>

// Full date (default)
<NepaliDatePicker
  mode="date"
  onChange={(val) => console.log(val?.formatted.bs)} // "2081/04/15"
/>

Note: In all modes, val.bs still contains the full { year, month, day } object — the formatted.bs string is adjusted to reflect only what was selected.


5. Variants — dropdown vs inline

variant="dropdown" (default)

  • Renders a text input field
  • Calendar opens as a floating popover when the input is clicked/focused
  • Input is typeable — type a date and the calendar navigates to it automatically (500ms debounce)
  • Supported type formats: YYYY/MM/DD, YYYY-MM-DD, YYYY.MM.DD, YYYY MM DD, YYYY/MM
  • Nepali digits (०–९) are also accepted
  • A green ✓ / red ✕ indicator shows parse validity while typing
  • Closes on: date selected + autoClose=true, Escape key, click outside
<NepaliDatePicker variant="dropdown" />

variant="inline"

  • Always-visible calendar panel, no trigger input
  • Fills its container width
  • Ideal for booking pages, dashboards, date range UIs
<NepaliDatePicker variant="inline" />

6. Calendar Systems — BS and AD

Bikram Sambat (BS) — default

<NepaliDatePicker calendarSystem="BS" />
  • Primary day number: BS day (large, center)
  • Secondary corner: AD day (small, bottom-right)
  • Header navigates BS months/years

Gregorian (AD)

<NepaliDatePicker calendarSystem="AD" language="en" />
  • Primary day number: AD day
  • Secondary corner: BS day
  • Header navigates AD months/years

Toggle in UI

<NepaliDatePicker
  showCalendarSystemToggle  // shows BS / AD pill in header
/>

Controlled system

const [sys, setSys] = useState<CalendarSystem>('BS');

<NepaliDatePicker
  calendarSystem={sys}
  onCalendarSystemChange={setSys}
/>

7. Language / Locale

| Value | Months | Day headers | Numbers | Labels | |-------|--------|-------------|---------|--------| | 'ne' | बैशाख, जेष्ठ… | आ, सो, म… | Nepali ०–९ | Nepali | | 'en' | Baisakh, Jestha… | Su, Mo, Tu… | Arabic 0–9 | English |

<NepaliDatePicker language="ne" />  // Nepali (default)
<NepaliDatePicker language="en" />  // English

// Toggle in header
<NepaliDatePicker showLanguageToggle />

// Controlled
const [lang, setLang] = useState<Language>('ne');
<NepaliDatePicker language={lang} onLanguageChange={setLang} />

8. Selection Types

Single (default)

<NepaliDatePicker
  selectionType="single"
  onChange={(val) => console.log(val)}
/>

Range

<NepaliDatePicker
  selectionType="range"
  variant="inline"
  onRangeChange={(start, end) => {
    console.log(start?.formatted.bs, end?.formatted.bs);
  }}
/>

Click first date = range start, click second = range end. Range highlights cells between start and end with hover preview.

Multiple

<NepaliDatePicker selectionType="multiple" />

9. Masked Input (Dropdown)

The dropdown input uses a slot-by-slot masked input driven by the format prop. The mask is shaped exactly like the format string — you type only digits and separators are auto-inserted.

How it works

Format:   YYYY/MM/DD
Mask:     ____/__/__
Type "2": 2___/__/__
Type "0": 20__/__/__
Type "8": 208_/__/__
Type "1": 2081/__/__  ← year complete, cursor jumps to MM slot
Type "0": 2081/0_/__
Type "4": 2081/04/__  ← month complete
Type "1": 2081/04/1_
Type "5": 2081/04/15  ✓  ← onChange fires immediately!

Key behaviour

  • Digits only — only 0–9 keys are accepted (Nepali digits ०–९ are also normalised)
  • onChange fires immediately when the last digit slot is filled and the date is valid — no need to click a day in the calendar
  • Cursor stays at the typed position — does not jump to the end after each keystroke
  • Arrow keys move the caret left/right among digit slots
  • Backspace removes the digit at caret position and shifts later digits left
  • Delete removes the digit at the cursor position
  • Paste extracts digits from the pasted string and fills the mask from the beginning
  • Click-outside closes the popover but keeps the typed value — no revert to previous date
  • For mode="date": after mask completes, the calendar opens so the user can optionally pick a different day
  • For mode="year", mode="month", mode="yearMonth": mask completion closes the picker immediately (no day grid needed)

Supported formats

Any format built from Y, M, D tokens and any separator:

| Format | Mask | Example filled | |--------|------|----------------| | YYYY/MM/DD | ____/__/__ | 2081/04/15 | | DD/MM/YYYY | __/__/____ | 15/04/2081 | | MM/DD/YYYY | __/__/____ | 04/15/2081 | | YYYY-MM-DD | ____-__-__ | 2081-04-15 | | YYYY.MM.DD | ____.__.__ | 2081.04.15 | | YYYY/MM | ____/__ | 2081/04 | | MM/YYYY | __/____ | 04/2081 | | YYYY | ____ | 2081 |

Return value matches format

formatted.bs always uses the format string exactly:

// format="DD/MM/YYYY"
onChange={(val) => {
  console.log(val?.formatted.bs);  // "15/04/2081"
  console.log(val?.formatted.ad);  // "30/07/2024"
}}

// format="YYYY-MM-DD"
onChange={(val) => {
  console.log(val?.formatted.bs);  // "2081-04-15"
  console.log(val?.formatted.ad);  // "2024-07-30"
}}

// format="YYYY/MM" + mode="yearMonth"
onChange={(val) => {
  console.log(val?.formatted.bs);  // "2081/04"
  console.log(val?.formatted.ad);  // "2024/07"
}}

Both formatted.bs and formatted.ad always mirror the same format pattern.

Disable typing (readonly input)

<NepaliDatePicker readOnly />
// Input opens calendar on click but does not accept keyboard input

10. Quick Presets

<NepaliDatePicker showPresets />

Built-in presets (language-aware):

| English label | Nepali label | |---------------|--------------| | Today | आज | | Yesterday | हिजो | | Tomorrow | भोली | | Last 7 Days | गत ७ दिन | | Last 14 Days | गत १४ दिन | | Last 30 Days | गत ३० दिन | | This Month | यो महिना | | This Year | यो वर्ष |

Custom presets

import { makeDualDateValue, getNepaliToday } from '@etpl/nepali-datepicker';

<NepaliDatePicker
  showPresets
  presets={[
    {
      label: 'Dashain',
      getValue: () => makeDualDateValue({ year: 2081, month: 7, day: 10 }),
    },
    {
      label: 'New Year',
      getValue: () => makeDualDateValue({ year: 2082, month: 1, day: 1 }),
    },
  ]}
/>

11. Date Constraints

Min / Max date

<NepaliDatePicker
  minDate={{ year: 2081, month: 1, day: 1 }}
  maxDate={{ year: 2081, month: 12, day: 30 }}
/>

Disable specific dates

<NepaliDatePicker
  disabledDates={[
    { year: 2081, month: 4, day: 10 },
    { year: 2081, month: 4, day: 11 },
  ]}
/>

Disable weekends

<NepaliDatePicker disableWeekend />

Disable specific weekdays

// Disable Mondays (1) and Fridays (5)
<NepaliDatePicker disabledDays={[1, 5]} />
// 0=Sun, 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat

12. DualDateValue — Return Type

Every onChange always emits a DualDateValue containing both BS and AD dates:

interface DualDateValue {
  bs: {
    year: number;   // e.g. 2081
    month: number;  // 1–12
    day: number;    // 1–32
  };
  ad: Date;         // JavaScript Date object (Gregorian)
  formatted: {
    bs: string;     // "2081/04/15" (or mode-adjusted: "2081", "04", "2081/04")
    ad: string;     // "2024-07-30"
  };
}

Accessing values

onChange={(val) => {
  if (!val) return; // null = cleared

  // BS date parts
  const { year, month, day } = val.bs;

  // AD JavaScript Date
  const adDate = val.ad;
  const adYear = adDate.getFullYear();

  // Formatted strings
  console.log(val.formatted.bs);  // "2081/04/15"
  console.log(val.formatted.ad);  // "2024-07-30"
}}

Mode-adjusted formatted.bs

| Mode | formatted.bs | |------|----------------| | date | "2081/04/15" | | year | "2081" | | month | "04" | | yearMonth | "2081/04" |

The full val.bs object always has year, month, day regardless of mode.


13. Theming — CSS Custom Properties

All visual tokens are exposed as CSS custom properties on :root. Override any of them in your own CSS:

:root {
  /* ── Brand / Primary ──────────────────────────────── */
  --ndc-primary:              hsl(174, 52%, 38%);   /* teal-green */
  --ndc-primary-hover:        hsl(174, 52%, 28%);
  --ndc-primary-light:        hsl(174, 50%, 94%);   /* light tint for hover bg */

  /* ── Surfaces ─────────────────────────────────────── */
  --ndc-surface:              hsl(0, 0%, 100%);      /* calendar background */
  --ndc-surface-hover:        hsl(174, 20%, 96%);   /* day cell hover bg */

  /* ── Borders ──────────────────────────────────────── */
  --ndc-border:               hsl(210, 16%, 90%);

  /* ── Text ─────────────────────────────────────────── */
  --ndc-text:                 hsl(215, 28%, 17%);   /* primary text */
  --ndc-text-muted:           hsl(215, 12%, 52%);   /* weekday headers, muted */
  --ndc-text-secondary:       hsl(215, 10%, 70%);   /* secondary corner date */

  /* ── Today indicator (dot + accent text) ─────────── */
  --ndc-today-bg:             transparent;
  --ndc-today-text:           hsl(174, 52%, 32%);   /* today number color */
  --ndc-today-dot:            hsl(174, 52%, 42%);   /* dot under today number */

  /* ── Selected day ─────────────────────────────────── */
  --ndc-selected-bg:          hsl(174, 52%, 38%);
  --ndc-selected-text:        hsl(0, 0%, 100%);

  /* ── Range selection ──────────────────────────────── */
  --ndc-range-bg:             hsl(174, 45%, 90%);
  --ndc-range-text:           hsl(174, 52%, 25%);

  /* ── Weekend day ──────────────────────────────────── */
  --ndc-weekend:              hsl(355, 60%, 58%);   /* soft rose */

  /* ── Disabled days ────────────────────────────────── */
  --ndc-disabled:             hsl(215, 10%, 78%);
  --ndc-disabled-bg:          hsl(215, 10%, 97%);

  /* ── Header ───────────────────────────────────────── */
  --ndc-header-bg:            hsl(215, 28%, 20%);   /* dark slate */
  --ndc-header-text:          hsl(0, 0%, 97%);

  /* ── Toggle pills ─────────────────────────────────── */
  --ndc-toggle-bg:            hsl(210, 18%, 94%);

  /* ── Border radius ────────────────────────────────── */
  --ndc-radius:               12px;                 /* calendar corners */
  --ndc-radius-sm:            7px;                  /* day cell corners */

  /* ── Shadow ───────────────────────────────────────── */
  --ndc-shadow:               0 8px 32px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.04);

  /* ── Cell sizes ───────────────────────────────────── */
  --ndc-cell-size:            2.6rem;               /* dropdown day cell */
  --ndc-cell-size-inline:     3.4rem;               /* inline day cell */

  /* ── Typography ───────────────────────────────────── */
  --ndc-primary-day-size:     0.9rem;               /* main day number */
  --ndc-secondary-day-size:   0.52rem;              /* corner date number */
  --ndc-font:                 "Inter", "Segoe UI", system-ui, sans-serif;
}

Example: Change to indigo theme

:root {
  --ndc-primary:         hsl(245, 70%, 55%);
  --ndc-primary-hover:   hsl(245, 70%, 45%);
  --ndc-primary-light:   hsl(245, 70%, 95%);
  --ndc-today-text:      hsl(245, 70%, 45%);
  --ndc-today-dot:       hsl(245, 70%, 55%);
  --ndc-selected-bg:     hsl(245, 70%, 55%);
  --ndc-header-bg:       hsl(245, 70%, 55%);
  --ndc-range-bg:        hsl(245, 70%, 93%);
}

Example: Change cell size for compact layout

:root {
  --ndc-cell-size: 2rem;
  --ndc-primary-day-size: 0.78rem;
  --ndc-secondary-day-size: 0.45rem;
}

14. Dark Mode

Automatic via theme prop

<NepaliDatePicker theme="dark" />
<NepaliDatePicker theme="light" />
<NepaliDatePicker theme="system" />  // follows prefers-color-scheme

Manual via data-ndc-theme attribute

<!-- Wrap your app or the picker in a container with: -->
<div data-ndc-theme="dark">
  <!-- picker here -->
</div>

Dark mode CSS tokens (auto-applied)

[data-ndc-theme="dark"] {
  --ndc-primary:         hsl(174, 55%, 50%);
  --ndc-surface:         hsl(220, 26%, 10%);
  --ndc-border:          hsl(220, 18%, 20%);
  --ndc-text:            hsl(210, 18%, 90%);
  --ndc-header-bg:       hsl(220, 26%, 14%);
  /* ... all tokens are defined for dark mode */
}

15. classNames Override

Every element has a named slot you can inject custom classes into (works with Tailwind CSS):

<NepaliDatePicker
  classNames={{
    container:             "relative",
    input:                 "border-2 border-teal-400 rounded-xl px-4 py-2",
    inputWrapper:          "relative",
    calendar:              "rounded-3xl shadow-2xl",
    header:                "bg-gradient-to-r from-teal-600 to-emerald-600 text-white",
    headerTitle:           "font-bold text-lg",
    headerNav:             "hover:bg-white/20 rounded-lg",
    calendarSystemToggle:  "text-xs px-2 py-1 rounded-full",
    languageToggle:        "text-xs px-2 py-1 rounded-full",
    weekdayRow:            "",
    weekdayCell:           "text-teal-500 font-semibold",
    grid:                  "",
    dayCell:               "rounded-xl hover:bg-teal-50 transition-colors",
    dayPrimary:            "font-semibold",
    daySecondary:          "text-gray-300",
    selectedDay:           "bg-teal-600 text-white shadow-lg",
    todayDay:              "text-teal-600 font-bold",
    rangeDay:              "bg-teal-100",
    rangeStart:            "rounded-l-xl bg-teal-600",
    rangeEnd:              "rounded-r-xl bg-teal-600",
    disabledDay:           "opacity-30 cursor-not-allowed",
    weekendDay:            "text-rose-500",
    outsideMonthDay:       "opacity-20",
    monthCell:             "rounded-lg hover:bg-teal-50",
    yearCell:              "rounded-lg hover:bg-teal-50",
    presetPanel:           "border-t border-gray-100",
    presetItem:            "rounded-full text-xs",
    footer:                "border-t border-gray-100",
    todayButton:           "text-teal-600 font-medium",
    clearButton:           "text-gray-400",
  }}
/>

16. Custom Rendering

Custom day cell

<NepaliDatePicker
  renderDay={(cell) => (
    <div className="relative flex items-center justify-center w-full h-full">
      <span className={cell.isToday ? "text-red-500 font-bold" : ""}>
        {cell.bsDay}
      </span>
      {cell.isWeekend && <div className="absolute bottom-1 w-1 h-1 bg-red-400 rounded-full" />}
    </div>
  )}
/>

Custom secondary corner date

<NepaliDatePicker
  showSecondaryDate
  renderSecondaryDate={(cell) => (
    <span style={{ fontSize: '0.45rem', color: 'purple' }}>
      {cell.adDay}
    </span>
  )}
/>

Custom header

<NepaliDatePicker
  renderHeader={(year, month, system) => (
    <div className="flex items-center justify-between p-3 bg-rose-600 text-white">
      <span>{system} · {month}/{year}</span>
    </div>
  )}
/>

Custom footer

<NepaliDatePicker
  renderFooter={() => (
    <div className="p-2 text-center text-xs text-gray-400">
      Select a date above
    </div>
  )}
/>

17. Core Utilities (exported functions)

All core functions are exported and can be used independently:

import {
  getNepaliDate,
  getEnglishDate,
  getNepaliToday,
  getBaar,
  getTotalDays,
  compareBs,
  bsEquals,
  bsIsBetween,
  makeDualDateValue,
  makeDualDateValueFromAd,
  toNepaliDigits,
  fromNepaliDigits,
  nepDateToString,
  nepDateFromString,
  toLongBsDateString,
  toLongAdDateString,
} from '@etpl/nepali-datepicker';

| Function | Signature | Description | |----------|-----------|-------------| | getNepaliDate | (adDate: Date) => NepDate | Convert JS Date → BS date | | getEnglishDate | (bs: NepDate) => Date | Convert BS date → JS Date | | getNepaliToday | () => NepDate | Get today's BS date | | getBaar | (year, month) => number | Get day-of-week for BS month start (1=Sun…7=Sat) | | getTotalDays | (year, month) => number | Days in a BS month (29–32) | | compareBs | (a, b) => -1 \| 0 \| 1 | Compare two BS dates | | bsEquals | (a, b) => boolean | Check if two BS dates are equal | | bsIsBetween | (date, start, end) => boolean | Check if date is in range | | makeDualDateValue | (bs: NepDate) => DualDateValue | Build a DualDateValue from BS | | makeDualDateValueFromAd | (ad: Date) => DualDateValue | Build a DualDateValue from AD | | toNepaliDigits | (n: number \| string) => string | 15१५ | | fromNepaliDigits | (s: string) => string | "१५""15" | | nepDateToString | (date, format?) => string | Format BS date string | | nepDateFromString | (str: string) => NepDate \| null | Parse BS date string | | toLongBsDateString | (date, lang) => string | "२०८१ साल बैशाख १५ गते" | | toLongAdDateString | (date, lang) => string | "July 30, 2024" |

Examples

import { getNepaliDate, toNepaliDigits, makeDualDateValue } from '@etpl/nepali-datepicker';

// Today in BS
const today = getNepaliDate(new Date());
console.log(today); // { year: 2081, month: 4, day: 15 }

// Nepali digits
console.log(toNepaliDigits(2081)); // "२०८१"

// Build dual value
const dual = makeDualDateValue({ year: 2081, month: 4, day: 15 });
console.log(dual.formatted.bs); // "2081/04/15"
console.log(dual.formatted.ad); // "2024-07-30"

18. TypeScript Types Reference

// Calendar system
type CalendarSystem = 'BS' | 'AD';

// UI language
type Language = 'ne' | 'en';

// Picker display variant
type PickerVariant = 'dropdown' | 'inline';

// Picker mode
type PickerMode =
  | 'date'       // full date
  | 'month'      // month only
  | 'year'       // year only
  | 'yearMonth'  // year + month
  | 'monthDay'   // month + day
  | 'week'
  | 'quarter'
  | 'halfYear';

// Selection behaviour
type SelectionType = 'single' | 'range' | 'multiple';

// BS date object
interface NepDate {
  year: number;
  month: number;
  day: number;
}

// What onChange emits — always has BOTH BS and AD
interface DualDateValue {
  bs: NepDate;
  ad: Date;
  formatted: {
    bs: string;  // mode-adjusted
    ad: string;
  };
}

// Single day cell in the grid
interface DualDayCell {
  bsDay: number;   bsMonth: number;   bsYear: number;
  adDay: number;   adMonth: number;   adYear: number;
  isCurrentMonth: boolean;
  isToday: boolean;
  isSelected: boolean;
  isInRange: boolean;
  isRangeStart: boolean;
  isRangeEnd: boolean;
  isDisabled: boolean;
  isWeekend: boolean;
  weekdayIndex: number; // 0=Sun … 6=Sat
}

// Custom preset item
interface DatePreset {
  label: string;
  getValue: () => DualDateValue | [DualDateValue, DualDateValue] | null;
}

// classNames map — all customisable slots
interface CalendarClassNames {
  container: string;
  input: string;
  inputWrapper: string;
  calendar: string;
  header: string;
  headerTitle: string;
  headerNav: string;
  calendarSystemToggle: string;
  languageToggle: string;
  weekdayRow: string;
  weekdayCell: string;
  grid: string;
  dayCell: string;
  dayPrimary: string;
  daySecondary: string;
  selectedDay: string;
  todayDay: string;
  rangeDay: string;
  rangeStart: string;
  rangeEnd: string;
  disabledDay: string;
  weekendDay: string;
  outsideMonthDay: string;
  monthCell: string;
  yearCell: string;
  presetPanel: string;
  presetItem: string;
  footer: string;
  todayButton: string;
  clearButton: string;
}

19. All CSS Class Names

These are the generated class names on rendered HTML elements. You can target them directly in your stylesheet:

| Class | Element | |-------|---------| | .ndc-calendar | Root calendar wrapper | | .ndc-inline | Added when variant="inline" | | .ndc-header | Header bar | | .ndc-header-center | Middle section of header | | .ndc-header-title | Month/year title button | | .ndc-header-toggles | Toggle pills wrapper | | .ndc-nav-btn | Prev/next navigation buttons | | .ndc-toggle-pill | BS/AD or ne/en pill container | | .ndc-toggle-option | Individual option within pill | | .ndc-toggle-option.active | Currently active option | | .ndc-weekday-row | Row of weekday abbreviations | | .ndc-weekday-cell | Single weekday abbreviation cell | | .ndc-grid | Day/month/year grid container | | .ndc-day-cell | Individual day cell | | .ndc-day-cell.today | Today's cell | | .ndc-day-cell.selected | Selected day cell | | .ndc-day-cell.in-range | Day within a range | | .ndc-day-cell.range-start | Range start day | | .ndc-day-cell.range-end | Range end day | | .ndc-day-cell.weekend | Weekend day | | .ndc-day-cell.disabled | Disabled day | | .ndc-day-cell.outside | Day from prev/next month | | .ndc-day-primary | Primary (large) day number | | .ndc-day-secondary | Secondary corner date | | .ndc-month-grid | Month picker grid | | .ndc-month-cell | Single month button | | .ndc-month-cell.active | Selected month | | .ndc-year-grid | Year picker grid | | .ndc-year-cell | Single year button | | .ndc-year-cell.active | Selected year | | .ndc-year-cell.current | Current year (today) | | .ndc-footer | Footer bar | | .ndc-footer-btn | Footer button base | | .ndc-footer-btn.today | Today button | | .ndc-footer-btn.clear | Clear button | | .ndc-selected-display | Inline: selected date display strip | | .ndc-dropdown-wrapper | Dropdown: outer wrapper | | .ndc-input-wrapper | Dropdown: input container | | .ndc-input | Dropdown: text input | | .ndc-input--valid | Input with valid typed date | | .ndc-input--invalid | Input with invalid typed text | | .ndc-input-icon | Calendar icon in input | | .ndc-input-status | ✓ / ✕ validation indicator | | .ndc-input-status--valid | Green ✓ indicator | | .ndc-input-status--invalid | Red ✕ indicator | | .ndc-popover | Dropdown: floating panel | | .ndc-popover.pos-top | Popover opens upward | | .ndc-presets | Presets panel container | | .ndc-preset-btn | Individual preset button | | .ndc-preset-item | Alternative preset item style |


20. Usage Examples — Every Variant

A. Basic dropdown

<NepaliDatePicker onChange={(v) => console.log(v?.formatted.bs)} />

B. Inline full calendar

<NepaliDatePicker variant="inline" onChange={(v) => console.log(v)} />

C. Year-only picker

<NepaliDatePicker
  mode="year"
  onChange={(v) => console.log(v?.formatted.bs)} // "2081"
/>

D. Month-only picker

<NepaliDatePicker
  mode="month"
  onChange={(v) => console.log(v?.formatted.bs)} // "04"
/>

E. Year + Month picker

<NepaliDatePicker
  mode="yearMonth"
  onChange={(v) => console.log(v?.formatted.bs)} // "2081/04"
/>

F. Date range (inline)

<NepaliDatePicker
  variant="inline"
  selectionType="range"
  onRangeChange={(start, end) => {
    console.log(start?.formatted.bs, end?.formatted.bs);
  }}
/>

G. AD calendar, English language

<NepaliDatePicker
  calendarSystem="AD"
  language="en"
  onChange={(v) => console.log(v?.formatted.ad)}
/>

H. Controlled value

const [val, setVal] = useState<DualDateValue | null>(null);

<NepaliDatePicker
  value={val}
  onChange={setVal}
/>

I. With presets panel

<NepaliDatePicker
  variant="inline"
  showPresets
  onChange={(v) => console.log(v)}
/>

J. With constraints

<NepaliDatePicker
  minDate={{ year: 2081, month: 1, day: 1 }}
  maxDate={{ year: 2081, month: 12, day: 30 }}
  disableWeekend
/>

K. Dark mode

<NepaliDatePicker theme="dark" />

L. Typeable dropdown with read-only toggle

// Editable (default):
<NepaliDatePicker variant="dropdown" />

// Read-only (click to open, no typing):
<NepaliDatePicker variant="dropdown" readOnly />

M. Fully custom styled with Tailwind

<NepaliDatePicker
  classNames={{
    calendar:    "rounded-3xl shadow-2xl border-0",
    header:      "bg-gradient-to-r from-violet-600 to-indigo-600 text-white rounded-t-3xl px-4 py-3",
    dayCell:     "rounded-xl transition-all hover:scale-105",
    selectedDay: "bg-violet-600 text-white shadow-lg",
    weekendDay:  "text-rose-400",
    footer:      "bg-gray-50 border-t border-gray-100",
  }}
/>

N. React Hook Form integration

import { Controller } from 'react-hook-form';

<Controller
  name="nepaliDate"
  control={control}
  render={({ field }) => (
    <NepaliDatePicker
      value={field.value}
      onChange={field.onChange}
    />
  )}
/>

O. Secondary date (dual-date cells)

// Show corner date (default: true)
<NepaliDatePicker showSecondaryDate />

// Hide corner date for clean look
<NepaliDatePicker showSecondaryDate={false} />

// Custom corner render
<NepaliDatePicker
  showSecondaryDate
  renderSecondaryDate={(cell) => <span>{cell.adDay}</span>}
/>

P. Both toggles visible

<NepaliDatePicker
  showCalendarSystemToggle  // BS / AD in header
  showLanguageToggle        // ne / en in header
/>

Q. Format string

<NepaliDatePicker format="DD-MM-YYYY" />  // shows "15-04-2081"
<NepaliDatePicker format="YYYY/MM/DD" />  // default "2081/04/15"

R. Position control (dropdown)

<NepaliDatePicker position="top" />     // opens above input
<NepaliDatePicker position="bottom" />  // opens below (default)
<NepaliDatePicker position="auto" />    // auto-detects