UNPKG

@armin-eslami/persian-calendar

Version:

Big persian calendar component made by react.

278 lines (233 loc) 11.3 kB
# Persian Calendar <div align="center"> <table style="border: none" align="center"> <tr> <td style="padding:10px" align="center"> <img src="docs/preview-1.png" alt="Wheel Preview 1" style="max-height: 250px; aspect-ratio: 1 / 1; object-fit: contain;" /> <div>Year View</div> </td> <td style="padding:10px" align="center"> <img src="docs/preview-2.png" alt="Wheel Preview 2" style="max-height: 250px; aspect-ratio: 1 / 1; object-fit: contain;" /> <div>Month View</div> </td> </tr> </table> </div> Big **Persian Calendar** component built with React, Typescript and Tailwindcss. ## Features - Supports year and month view - Customizable theme - Supports events - Supports custom off dates - Supports controlled vs uncontrolled mode ## Installation ```bash npm install @armin-eslami/persian-calendar ``` ## Example Usage ### 1. Uncontrolled component #### Basic ```ts import PersianCalendar from '@armin-eslami/persian-calendar'; function App() { return ( PersianCalendar year={year} /> ); } ``` #### Advanced ```ts import PersianCalendar, { PersianCalendarTheme, PersianCalendarEvent, Day, } from "@armin-eslami/persian-calendar"; function App() { // Override the default theme const theme: PersianCalendarTheme = { fontFamily: "Vazir", background: "#fff", }; // Set which days of week are off const offDaysOfWeek: number[] = [6]; // 6 is friday // Set off dates of the year const offDates: string[] = [ "1404/01/01", "1404/01/02", "1404/01/03", "1404/01/04", "1404/01/12", "1404/01/13", ... ]; // Set events const events: PersianCalendarEvent[] = [ { title: "بدون عنوان", date: "1404/02/05", color: "#ef4444" }, { title: "بدون عنوان", date: "1404/02/13", color: "#10b981" }, { title: "بدون عنوان", date: "1404/02/20", color: "#d946ef" }, ]; // Gets called when a day is clicked const onDayClick = (day: Day) => { console.log(day); }; return ( <PersianCalendar className="w-full h-full p-4" year="1404" month={2} theme={theme} events={events} offDates={offDates} offDaysOfWeek={offDaysOfWeek} onDayClick={onDayClick} /> ); } export default App; ``` ### 2. Controlled component ```ts import PersianCalendar, { PersianCalendarMode, Day, getCurrentYear getCurrentMonthIndex, } from "@armin-eslami/persian-calendar"; function App() { // Track the active mode const [activeMode, setActiveMode] = useState<PersianCalendarMode>( PersianCalendarMode.YEAR ); // Track the active year const [year, setYear] = useState<string>("1404"); // Track active month const [month, setMonth] = useState<number | undefined>( getCurrentMonthIndex() ); // Gets called when a day is clicked const onDayClick = (day: Day) => { console.log(day); }; const onNext = () => { if (activeMode === PersianCalendarMode.YEAR) { setYear((prev) => String(Number(prev) + 1)); } else { const curretnMonth = month ?? getCurrentMonthIndex(); if (curretnMonth + 1 > 12) { setMonth(() => 1); setYear((prev) => String(Number(prev) + 1)); } else { setMonth((prev) => Number(prev) + 1); } } }; const onPrevious = () => { if (activeMode === PersianCalendarMode.YEAR) { setYear((prev) => String(Number(prev) - 1)); } else { const curretnMonth = month ?? getCurrentMonthIndex(); if (curretnMonth - 1 < 1) { setMonth(() => 12); setYear((prev) => String(Number(prev) - 1)); } else { setMonth((prev) => Number(prev) - 1); } } }; const onToday = () => { setJYear(getCurrentYear()); setMonth(getCurrentMonthIndex()); }; const onModeChange = (mode: PersianCalendarMode) => { setActiveMode(mode); }; return ( <PersianCalendar className="w-full h-full p-4" year={year} month={month} theme={theme} events={events} offDates={offDates} offDaysOfWeek={offDaysOfWeek} onDayClick={onDayClick} mode={activeMode} onModeChange={onModeChange} onNext={onNext} onPrevious={onPrevious} onToday={onToday} /> ); } export default App; ``` ## PersianCalendar Props | Name | Type | Default | Required | Description | | ----------------------- | ------------------------------------- | ------------------------ | -------- | --------------------------------------------------------------------------- | | `year` | `string` | `getCurrentYear()` | Yes | Initial year to render. | | `month` | `number` | `getCurrentMonthIndex()` | No | Initial month index. | | `mode` | `PersianCalendarMode` | `'year'` | No | Display mode of the calendar. | | `theme` | `PersianCalendarTheme` | `defaultTheme` | No | Custom theme object for styling the calendar. | | `className` | `string` | — | No | Custom class names for the root container. | | `events` | `PersianCalendarEvent[]` | `[]` | No | List of event objects to mark on the calendar. | | `offDates` | `string[]` | `[]` | No | List of off-day date strings. The format must be jYYYY/jMM/jDD (1404/02/01) | | `offDaysOfWeek` | `number[]` | `[6]` | No | Array of weekday indices to mark as off days (0 = Saturday, 6 = Friday). | | `monthTitleFormat` | `string` | `"jMMMM"` | No | Format string for month title display. | | `hasNavbar` | `boolean` | `true` | No | Whether to show the navbar header. | | `hasModeSwitch` | `boolean` | `true` | No | Whether to show the mode switch. | | `gridColumnCount` | `1` → `12` | `4` | No | Number of columns used in year view grid. | | `showEventsOnDay` | `boolean` | `false` | No | Whether to show the day events on day iteself or below it on year mode. | | `multiEventsInDayColor` | `string` | `#f43f5e (accent)` | No | The Color to use if a day has more than one event on year mode. | | `onNext` | `() => void` | — | No | Callback when navigating forward. | | `onPrevious` | `() => void` | — | No | Callback when navigating backward. | | `onToday` | `() => void` | — | No | Callback for jumping to current date. | | `onModeChange` | `(mode: PersianCalendarMode) => void` | — | No | Callback when view mode is toggled. | | `onDayClick` | `(day: Day) => void` | — | No | Callback when a day is clicked. | ## PersianCalendarTheme | Property | Type | Default Value | Required | | ------------------------- | ------ | -------------------- | -------- | | `primary` | string | `"#6366f1"` | No | | `secondary` | string | `"#818cf8"` | No | | `accent` | string | `"#f43f5e"` | No | | `background` | string | `"#ffffff"` | No | | `textPrimary` | string | `"#1f2937"` | No | | `textSecondary` | string | `"#6b7280"` | No | | `borderColor` | string | `"#f3f4f6"` | No | | `disabledMonthBackground` | string | `"#e5e7eb"` | No | | `fontSize.header` | string | `"4rem"` | No | | `fontSize.subHeader` | string | `"3rem"` | No | | `fontSize.title` | string | `"1rem"` | No | | `fontSize.body` | string | `"0.875rem"` | No | | `fontSize.footer` | string | `"0.75rem"` | No | | `fontFamily` | string | `"monospace, Arial"` | No | | `colors.monthTitleColor` | string | `"#6366f1"` | No | | `colors.offDayColor` | string | `"#ef4444"` | No | | `colors.hoverColor` | string | `"#6366f1"` | No | ## PersianCalendarEvent | Property | Type | Required | Description | | -------- | ------ | -------- | -------------------------------------- | | `id` | number | No | Optional unique ID of the event. | | `title` | string | No | Optional title of the event. | | `date` | string | Yes | Date of the event (e.g. "1404/02/05"). | | `color` | string | No | Optional hex color for the event dot. | ## Day | Property | Type | Required | Description | | ---------- | ---------------------- | -------- | ---------------------------------------------- | | `id` | string | Yes | Unique identifier, usually the formatted date. | | `title` | string | Yes | Display title for the day (e.g. "۱", "۲"). | | `active` | boolean | No | Whether this day is today. | | `enabled` | boolean | No | Whether this day is selectable. | | `isOffDay` | boolean | No | Whether this day is an off day. | | `event` | PersianCalendarEvent[] | No | Array of events assigned to this day. | | `month` | number | No | The month number this day belongs to. | ## PersianCalendarMode ```ts enum PersianCalendarMode { YEAR = "1", MONTH = "2", } ``` ## License The MIT License (MIT). Please see [License File](LICENSE.md) for more information.