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 🙏

© 2025 – Pkg Stats / Ryan Hefner

persian-datepicker-element

v1.1.18

Published

A modern Jalali (Shamsi) Date Picker web component with shadcn-like styling

Readme

Persian Date Picker Element

A modern, customizable Persian (Jalali) date picker web component with framework integrations.

Features

  • 🎨 Fully customizable with CSS variables
  • 🌙 Dark mode support
  • 📱 Mobile-friendly with touch gestures
  • 🎯 Framework integrations (React, Vue, Angular)
  • 📅 Holiday support with multiple event types (Iran, Afghanistan, Ancient Iran, International)
  • 🔄 RTL support
  • 🎨 Multiple theme options
  • 📦 Zero dependencies
  • 🎯 TypeScript support
  • 📊 Range selection mode
  • 🚫 Disabled dates support
  • 🎨 Customizable UI elements visibility

Installation

Web Component

npm install persian-datepicker-element
# or
yarn add persian-datepicker-element
# or
pnpm add persian-datepicker-element

Framework Integrations

React

npm install react-persian-datepicker-element persian-datepicker-element
# or
yarn add react-persian-datepicker-element persian-datepicker-element
# or
pnpm add react-persian-datepicker-element persian-datepicker-element

Vue

npm install vue-persian-datepicker-element persian-datepicker-element
# or
yarn add vue-persian-datepicker-element persian-datepicker-element
# or
pnpm add vue-persian-datepicker-element persian-datepicker-element

Angular

npm install ngx-persian-datepicker-element persian-datepicker-element
# or
yarn add ngx-persian-datepicker-element persian-datepicker-element
# or
pnpm add ngx-persian-datepicker-element persian-datepicker-element

Usage

Web Component

<!-- Import the component -->
<script type="module" src="node_modules/persian-datepicker-element/dist/persian-datepicker-element.min.js"></script>

<!-- Use the component -->
<persian-datepicker-element
  placeholder="انتخاب تاریخ"
  format="YYYY/MM/DD"
  show-holidays
  rtl
></persian-datepicker-element>

React

import { PersianDatepicker } from 'react-persian-datepicker-element';

function App() {
  const handleChange = (event) => {
    console.log('تاریخ انتخاب شده:', event.detail);
  };

  return (
      <PersianDatepicker
        placeholder="انتخاب تاریخ"
        format="YYYY/MM/DD"
        showEvents
        rtl
        onChange={handleChange}
      />
  );
}

Vue

<template>
    <PersianDatepicker
      placeholder="انتخاب تاریخ"
      format="YYYY/MM/DD"
      :show-holidays="true"
      :rtl="true"
      @change="handleChange"
    />
</template>

<script setup>
import { PersianDatepicker } from 'vue-persian-datepicker-element';

const handleChange = (event) => {
  console.log('تاریخ انتخاب شده:', event.detail);
};
</script>

Angular

1. Using the NgModule (Traditional Angular)

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgxPersianDatepickerModule } from 'ngx-persian-datepicker-element';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    NgxPersianDatepickerModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <ngx-persian-datepicker-element
      placeholder="انتخاب تاریخ"
      format="YYYY/MM/DD"
      [showEvents]="true"
      [rtl]="true"
      (dateChange)="onDateChange($event)"
    ></ngx-persian-datepicker-element>
  `
})
export class AppComponent {
  onDateChange(event: any) {
    console.log('تاریخ شمسی:', event.jalali); // [year, month, day]
    console.log('تاریخ میلادی:', event.gregorian);
    console.log('آیا تعطیل است:', event.isHoliday);
    console.log('رویدادها:', event.events);
  }
}

2. As a Standalone Component (Angular 17+)

// app.component.ts
import { Component } from '@angular/core';
import { NgxPersianDatepickerComponent } from 'ngx-persian-datepicker-element';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [NgxPersianDatepickerComponent],
  template: `
    <ngx-persian-datepicker-element
      placeholder="تاریخ را انتخاب کنید"
      format="YYYY/MM/DD"
      [showEvents]="true"
      (dateChange)="onDateChange($event)"
    ></ngx-persian-datepicker-element>
  `
})
export class AppComponent {
  onDateChange(event: any) {
    console.log('تاریخ شمسی:', event.jalali); // [سال, ماه, روز]
    console.log('تاریخ میلادی:', event.gregorian);
    console.log('آیا تعطیل است:', event.isHoliday);
    console.log('رویدادها:', event.events);
  }
}

3. With Reactive Forms

// app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { NgxPersianDatepickerComponent } from 'ngx-persian-datepicker-element';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [NgxPersianDatepickerComponent, ReactiveFormsModule],
  template: `
    <form [formGroup]="dateForm">
      <ngx-persian-datepicker-element 
        formControlName="date"
        placeholder="تاریخ را انتخاب کنید"
        format="YYYY/MM/DD">
      </ngx-persian-datepicker-element>
    </form>
  `
})
export class AppComponent {
  dateForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.dateForm = this.fb.group({
      date: [1403, 6, 15] // Initial value: [year, month, day]
    });
  }
}

Props & Attributes

| Prop/Attribute | Type | Default | Description | |---------------|------|---------|-------------| | value | string | [number, number, number] | - | The selected date value | | placeholder | string | - | Placeholder text | | format | string | "YYYY/MM/DD" | Date format string | | show-holidays | boolean | false | Show holiday indicators | | holiday-types | string | "Iran,Afghanistan,AncientIran,International" | Comma-separated list of holiday types to display. Use "all" to show all available holiday types | | rtl | boolean | false | Right-to-left layout | | min-date | [number, number, number] | - | Minimum selectable date | | max-date | [number, number, number] | - | Maximum selectable date | | disabled-dates | string | - | The name of a function that determines if a date should be disabled | | disabled | boolean | false | Disable the datepicker | | dark-mode | boolean | false | Enable dark mode | | range-mode | boolean | false | Enable date range selection mode | | show-month-selector | boolean | true | Show month selector dropdown | | show-year-selector | boolean | true | Show year selector dropdown | | show-prev-button | boolean | true | Show previous month button | | show-next-button | boolean | true | Show next month button | | show-today-button | boolean | true | Show today button | | show-tomorrow-button | boolean | true | Show tomorrow button | | today-button-text | string | "امروز" | Custom text for today button | | tomorrow-button-text | string | "فردا" | Custom text for tomorrow button | | today-button-class | string | "" | Additional CSS classes for today button | | tomorrow-button-class | string | "" | Additional CSS classes for tomorrow button |

Events

| Event | Detail Type | Description | |-------|-------------|-------------| | change | { jalali: [number, number, number], gregorian: [number, number, number], isHoliday: boolean, events: Array, formattedDate: string, isoString: string } | Fired when a date is selected | | change | { range: { start: [number, number, number], end: [number, number, number], startISOString: string, endISOString: string, startGregorian: [number, number, number], endGregorian: [number, number, number] }, isRange: true } | Fired when a date range is selected (in range mode) |

Examples for accessing ISO strings

For single date selection:

datepicker.addEventListener('change', (event) => {
  // ISO string for the selected date
  console.log('Selected date ISO string:', event.detail.isoString);
  
  // Access ISO strings from events (like holidays)
  if (event.detail.events.length > 0) {
    event.detail.events.forEach(eventItem => {
      console.log(`Event: ${eventItem.title}, ISO date: ${eventItem.isoString}`);
    });
  }
});

For range selection:

rangePicker.addEventListener('change', (event) => {
  if (event.detail.isRange) {
    // ISO strings for range start and end
    console.log('Range start ISO:', event.detail.range.startISOString);
    console.log('Range end ISO:', event.detail.range.endISOString);
  }
});

Methods

| Method | Parameters | Return Type | Description | |--------|------------|-------------|-------------| | setValue | (year: number, month: number, day: number) | void | Sets the datepicker value | | getValue | () | [number, number, number] | null | Gets the current selected date as a tuple | | open | () | void | Opens the datepicker calendar | | close | () | void | Closes the datepicker calendar | | setMinDate | (year: number, month: number, day: number) | void | Sets the minimum allowed date | | setMaxDate | (year: number, month: number, day: number) | void | Sets the maximum allowed date | | setDisabledDatesFn | (fn: (year: number, month: number, day: number) => boolean) | void | Sets a function to determine disabled dates | | setRange | (start: [number, number, number], end: [number, number, number]) | void | Sets a date range (in range mode) | | getRange | () | { start: [number, number, number] | null, end: [number, number, number] | null } | Gets the current selected range | | clear | () | void | Clears the selected date or range | | seteventTypes | (types: string | string[]) | void | Sets the holiday types to display | | geteventTypes | () | string[] | Gets the current holiday types | | isShowingAllTypes | () | boolean | Checks if all holiday types are being shown | | isSelectedDateHoliday | () | boolean | Checks if the currently selected date is a holiday | | getSelectedDateEvents | () | any[] | Gets events for the currently selected date |

Advanced Usage

Date Range Selection

To enable date range selection mode:

<persian-datepicker-element range-mode></persian-datepicker-element>

In React:

<PersianDatepicker rangeMode />

In Vue:

<PersianDatepicker :range-mode="true" />

In Angular:

<ngx-persian-datepicker-element [rangeMode]="true"></ngx-persian-datepicker-element>

Customizing UI Elements

You can control the visibility of various UI elements:

<persian-datepicker-element
  show-month-selector="false"
  show-year-selector="true"
  show-prev-button="true"
  show-next-button="true"
  show-today-button="false"
  show-tomorrow-button="true"
></persian-datepicker-element>

Custom Button Text and Styling

<persian-datepicker-element
  today-button-text="Go to Today"
  tomorrow-button-text="Next Day"
  today-button-class="primary rounded"
  tomorrow-button-class="secondary rounded"
></persian-datepicker-element>

Dark Mode

<persian-datepicker-element dark-mode></persian-datepicker-element>

Disabled Dates

There are three ways to specify which dates should be disabled:

1. Global Function

Define a function in the global scope and reference it by name:

<script>
  function isWeekend(year, month, day) {
    const date = new Date(year, month - 1, day);
    const dayOfWeek = date.getDay();
    return dayOfWeek === 5 || dayOfWeek === 6; // Disable Friday and Saturday (Persian weekend)
  }
</script>

<persian-datepicker-element disabled-dates="isWeekend"></persian-datepicker-element>

2. Element Method

Define a method directly on the element after retrieving it:

<persian-datepicker-element id="my-picker"></persian-datepicker-element>

<script>
  const picker = document.getElementById('my-picker');
  
  // Add a method to the element
  picker.isHoliday = function(year, month, day) {
    // Custom logic to determine holidays
    return day === 13; // Disable 13th of each month as an example
  };
  
  // Reference the method by name
  picker.setAttribute('disabled-dates', 'isHoliday');
</script>

3. Direct Function Assignment (Recommended for Framework Users)

For React, Vue, or other framework users, you can pass a function directly:

// React example
import { PersianDatepicker } from 'react-persian-datepicker-element';

function App() {
  // Define the function locally
  const isEvenDay = (year, month, day) => {
    return day % 2 === 0; // Disable even days
  };

  return (
    <PersianDatepicker 
      placeholder="Select date" 
      disabledDates={isEvenDay}
    />
  );
}

You can also use the setDisabledDatesFn method directly:

const picker = document.getElementById('my-picker');
picker.setDisabledDatesFn((year, month, day) => {
  return day % 2 === 0; // Disable even days
});

Framework-Specific Features

React

  • Full TypeScript support
  • Ref forwarding for imperative methods
  • React event handling
  • Controlled and uncontrolled modes
  • Custom hooks for date manipulation

Vue

  • Vue 3 Composition API support
  • TypeScript support
  • Vue event handling
  • v-model support
  • Custom directives for date formatting

Angular

  • Angular Ivy and Angular Signals support
  • TypeScript support
  • Angular event binding
  • Reactive Forms and Template-driven Forms integration
  • Customization using CSS variables and direct inputs
  • Zero configuration required
  • Both module-based and standalone component support

Mobile Support

The component includes built-in support for mobile devices:

  • Touch swipe gestures for month navigation
  • Mobile-optimized tooltips
  • Responsive design
  • Touch-friendly UI elements

Browser Support

  • Chrome 67+
  • Firefox 63+
  • Safari 10.1+
  • Edge 79+

Troubleshooting

Common Issues

  1. Component not rendering: Make sure you've imported the component correctly and that the script is loaded before using the component.

  2. Events not firing: Check that you're using the correct event name and that the event handler is properly attached.

  3. Styling issues: Verify that your CSS variables are correctly defined and that there are no conflicting styles.

  4. Date format issues: Ensure that the format string is valid and that the date is in the correct format.

  5. Holidays not showing: Check that the show-holidays attribute is set to true and that the holiday-types attribute includes the desired holiday types.

Debugging

For debugging purposes, you can enable verbose logging:

const picker = document.getElementById('my-picker');
picker.setAttribute('debug', 'true');

This will log additional information to the console, which can help identify issues.

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.