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

react-jalali-calendar

v0.1.5

Published

Persian (Jalali) calendar utilities and React components

Downloads

701

Readme

react-jalali-calendar

Persian (Jalali / Shamsi) calendar components and date utilities for React.
Built on jalaali-js with no UI framework dependency.

npm license

فارسی


Table of contents


Installation

npm install react-jalali-calendar
# or
pnpm add react-jalali-calendar
# or
yarn add react-jalali-calendar

Peer dependencies (must already be in your project):

npm install react react-dom   # 18 or 19

Quick start

import { useState } from "react";
import { JalaliCalendar, JalaliDatePicker } from "react-jalali-calendar";
import "react-jalali-calendar/styles.css";

export function BookingForm() {
  const [date, setDate] = useState("");           // "YYYY-MM-DD" string
  const [selected, setSelected] = useState<Date | null>(null);

  return (
    <div>
      {/* Inline calendar */}
      <JalaliCalendar
        selectedDate={selected}
        onSelectDate={setSelected}
        latinDigits={false}
      />

      {/* Popup date picker */}
      <JalaliDatePicker value={date} onChange={setDate} />
    </div>
  );
}

Import styles.css once in your app entry point (e.g. main.tsx or layout.tsx).


Components

JalaliCalendar

An inline month grid. The component manages its own navigation state internally; you only control which day is selected.

import { JalaliCalendar } from "react-jalali-calendar";

<JalaliCalendar
  selectedDate={selected}
  onSelectDate={(date) => setSelected(date)}
/>

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | selectedDate | Date \| null | required | The currently selected date. Pass null for no selection. | | onSelectDate | (date: Date) => void | required | Called with the Date object when the user clicks a day. | | isDateDisabled | (date: Date) => boolean | — | Return true to make a day unclickable. | | latinDigits | boolean | false | Show digits as 0-9 instead of ۰-۹. | | initialMonth | { jy: number; jm: number } | current month | Jalali year/month shown on first render. | | prevMonthLabel | string | "ماه قبل" | aria-label for the previous-month button. | | nextMonthLabel | string | "ماه بعد" | aria-label for the next-month button. | | className | string | — | Extra CSS class added to the root <div>. |

Examples

// Disable all days in the past
<JalaliCalendar
  selectedDate={selected}
  onSelectDate={setSelected}
  isDateDisabled={(date) => date < new Date()}
/>

// Open on a specific month (Farvardin 1403)
<JalaliCalendar
  selectedDate={null}
  onSelectDate={setSelected}
  initialMonth={{ jy: 1403, jm: 1 }}
/>

// Latin digits + custom class
<JalaliCalendar
  selectedDate={selected}
  onSelectDate={setSelected}
  latinDigits
  className="my-calendar"
/>

JalaliDatePicker

A button that opens a popover containing JalaliCalendar. Closes on outside click or Escape. The selected date is stored as a "YYYY-MM-DD" string (Gregorian local date key), which is easy to send to a server or store in a form.

import { JalaliDatePicker } from "react-jalali-calendar";

const [date, setDate] = useState(""); // e.g. "2024-03-20"

<JalaliDatePicker value={date} onChange={setDate} />

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | value | string | required | A YYYY-MM-DD Gregorian date key, or "" for no selection. | | onChange | (value: string) => void | required | Called with the new YYYY-MM-DD string when a day is picked. | | placeholder | string | "انتخاب تاریخ" | Text shown on the trigger button when no date is selected. | | latinDigits | boolean | false | Display the selected date label with Latin digits. | | isDateDisabled | (date: Date) => boolean | — | Passed through to the inner JalaliCalendar. | | className | string | — | Extra class on the picker root element. | | calendarClassName | string | — | Extra class on the inner JalaliCalendar. |

Examples

// Disable weekends (Friday = index 5 in JS Date)
<JalaliDatePicker
  value={date}
  onChange={setDate}
  isDateDisabled={(d) => d.getDay() === 5}
  latinDigits
/>

// With a custom placeholder
<JalaliDatePicker
  value={date}
  onChange={setDate}
  placeholder="تاریخ تولد را انتخاب کنید"
/>

Headless hook

Use useJalaliCalendar to build a completely custom calendar UI while letting the library handle month navigation and grid generation.

import { useJalaliCalendar } from "react-jalali-calendar";
import { PERSIAN_MONTHS, PERSIAN_WEEKDAYS_SHORT, localDateKey } from "react-jalali-calendar/core";

function MyCalendar({ selectedDate, onSelectDate }) {
  const { jy, jm, grid, today, todayKey, prevMonth, nextMonth, goToMonth, goToToday } =
    useJalaliCalendar({ initialMonth: { jy: 1403, jm: 6 } });

  return (
    <div dir="rtl">
      <div>
        <button onClick={prevMonth}>قبل</button>
        <strong>{PERSIAN_MONTHS[jm - 1]} {jy}</strong>
        <button onClick={nextMonth}>بعد</button>
        <button onClick={goToToday}>امروز</button>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "repeat(7, 1fr)" }}>
        {PERSIAN_WEEKDAYS_SHORT.map((d) => (
          <span key={d}>{d}</span>
        ))}

        {grid.map((date, i) => {
          if (!date) return <span key={i} />;
          const key = localDateKey(date);
          return (
            <button
              key={key}
              onClick={() => onSelectDate(date)}
              style={{ fontWeight: key === todayKey ? "bold" : undefined }}
            >
              {date.getDate()}
            </button>
          );
        })}
      </div>
    </div>
  );
}

Return value

| Property | Type | Description | |----------|------|-------------| | jy | number | Currently displayed Jalali year. | | jm | number | Currently displayed Jalali month (1-12). | | grid | (Date \| null)[] | Flat array of day cells. null entries are leading empty cells before the 1st of the month. | | today | JalaliDateParts | Today's { jy, jm, jd }. | | todayKey | string | Today as "YYYY-MM-DD", useful for highlighting. | | prevMonth | () => void | Navigate one month back. | | nextMonth | () => void | Navigate one month forward. | | goToMonth | (jy, jm) => void | Jump to any Jalali year/month directly. | | goToToday | () => void | Jump back to the current month. |

Options

useJalaliCalendar({
  initialMonth: { jy: 1403, jm: 1 }, // optional, defaults to current month
})

Core utilities

Import pure date helpers from the /core sub-path. This entry point has no React dependency and can be used in Node.js, server components, or non-React projects.

import {
  toJalali,
  fromJalali,
  formatJalali,
  formatTime,
  getJalaliMonthGrid,
  getJalaliWeekDates,
  addJalaliMonths,
  monthDateRange,
  localDateKey,
  isoDateOnly,
  toLatinDigits,
  toPersianDigits,
  PERSIAN_MONTHS,
  PERSIAN_WEEKDAYS,
  PERSIAN_WEEKDAYS_SHORT,
} from "react-jalali-calendar/core";

Conversion

toJalali(date: Date): JalaliDateParts

Convert a Date object to Jalali parts.

toJalali(new Date("2024-03-20"));
// => { jy: 1403, jm: 1, jd: 1 }

fromJalali(parts: JalaliDateParts): Date

Convert Jalali { jy, jm, jd } back to a Gregorian Date.

fromJalali({ jy: 1403, jm: 1, jd: 1 });
// => Date("2024-03-20")

Formatting

formatJalali(date, options?): string

Human-readable Jalali date string.

formatJalali(new Date("2024-03-20"));
// => "۱ فروردین ۱۴۰۳"

formatJalali(new Date("2024-03-20"), { includeWeekday: true });
// => "چهارشنبه، ۱ فروردین ۱۴۰۳"

formatJalali(new Date("2024-03-20"), { latinDigits: true });
// => "1 فروردین 1403"

| Option | Type | Default | Description | |--------|------|---------|-------------| | includeWeekday | boolean | false | Prepend the Persian weekday name. | | latinDigits | boolean | false | Use 0-9 instead of ۰-۹. |

formatTime(date: Date, latinDigits?: boolean): string

Format hours and minutes as HH:MM.

formatTime(new Date(), true);   // "09:45"
formatTime(new Date(), false);  // "۰۹:۴۵"

toPersianDigits(value: string): string

Replace 0-9 with ۰-۹ anywhere in a string.

toPersianDigits("1403/01/01"); // "۱۴۰۳/۰۱/۰۱"

toLatinDigits(value: string): string

Replace ۰-۹ with 0-9 anywhere in a string.

toLatinDigits("۱۴۰۳"); // "1403"

Date keys

localDateKey(date: Date): string

Returns a "YYYY-MM-DD" string using local time (no UTC shift). This is the format used by JalaliDatePicker.

localDateKey(new Date("2024-03-20")); // "2024-03-20"

isoDateOnly(date: Date): string

Returns a "YYYY-MM-DD" string using UTC (date.toISOString().slice(0, 10)).

Grid helpers

getJalaliMonthGrid(jy: number, jm: number): (Date | null)[]

Returns a flat array of cells for a full month grid (Saturday-anchored). Leading cells before the 1st are null.

const cells = getJalaliMonthGrid(1403, 1);
// cells[0] might be null (padding), then Date objects for each day

getJalaliWeekDates(jy: number, jm: number, jd: number): Date[]

Returns the 7 Date objects for the Jalali week (Saturday to Friday) containing the given date.

getJalaliWeekDates(1403, 1, 10); // [Date(Sat), ..., Date(Fri)]

addJalaliMonths(jy: number, jm: number, delta: number): JalaliDateParts

Add or subtract months, handling year rollovers correctly.

addJalaliMonths(1403, 12, 1);  // => { jy: 1404, jm: 1, jd: 1 }
addJalaliMonths(1403, 1, -1);  // => { jy: 1402, jm: 12, jd: 1 }

monthDateRange(jy: number, jm: number): { from: Date; to: Date }

Returns the first and last Date of a Jalali month (last date is set to 23:59:59.999). Useful for API range queries.

const { from, to } = monthDateRange(1403, 1);
// from: 2024-03-20 00:00:00
// to:   2024-04-19 23:59:59.999

Constants

PERSIAN_MONTHS[0]         // "فروردین"  (index 0 = month 1)
PERSIAN_WEEKDAYS[0]       // "شنبه"     (index 0 = Saturday)
PERSIAN_WEEKDAYS_SHORT[0] // "ش"

Theming

The components use CSS custom properties scoped under the .rjc and .rjc-picker class names. Override any variable to match your design system.

/* globals.css or any stylesheet loaded after styles.css */
:root {
  --rjc-primary:     #7c3aed;
  --rjc-primary-fg:  #ffffff;
  --rjc-radius:      0.75rem;
  --rjc-font:        "Vazirmatn", sans-serif;
}

Or scope overrides to a specific instance:

.booking-calendar {
  --rjc-primary: #0ea5e9;
  --rjc-cell-size: 2.5rem;
}
<JalaliCalendar className="booking-calendar" ... />

All available variables

| Variable | Controls | |----------|----------| | --rjc-bg | Calendar background | | --rjc-fg | Text color | | --rjc-muted | Weekday header text | | --rjc-border | Border color | | --rjc-primary | Selected day background | | --rjc-primary-fg | Selected day text | | --rjc-hover | Day hover background | | --rjc-today-ring | Ring color on today's cell | | --rjc-disabled | Disabled day text color | | --rjc-radius | Border radius of cells and container | | --rjc-cell-size | Width/height of each day cell | | --rjc-cell-gap | Gap between cells in the grid | | --rjc-font | Font family |


TypeScript types

All public types are exported from the main entry point:

import type {
  JalaliDateParts,
  JalaliCalendarProps,
  JalaliDatePickerProps,
  UseJalaliCalendarOptions,
} from "react-jalali-calendar";

JalaliDateParts

type JalaliDateParts = {
  jy: number; // Jalali year
  jm: number; // Jalali month (1-12)
  jd: number; // Jalali day (1-29/30/31)
};

Week convention

This library treats Saturday as day 0 and Friday as day 6, which matches the Iranian week. The grid returned by getJalaliMonthGrid and useJalaliCalendar is aligned to this convention -- the first column is always Saturday.

| Index | Day | |-------|-----| | 0 | شنبه (Saturday) | | 1 | یکشنبه (Sunday) | | 2 | دوشنبه (Monday) | | 3 | سه‌شنبه (Tuesday) | | 4 | چهارشنبه (Wednesday) | | 5 | پنجشنبه (Thursday) | | 6 | جمعه (Friday) |


License

MIT - TronIsHere