@hamedf/svelte-persian-datepicker
Version:
A comprehensive Svelte 5 Persian/Jalali DateTime picker component with multi-calendar support (Jalali, Gregorian, Hijri), multiple selection modes (single, range, multiple), and extensive customization options
443 lines (345 loc) โข 14.3 kB
Markdown
# Persian DatePicker Component (Svelte 5)
**๐ [Live Demo](https://hamedf62.github.io/svelte-persian-datepicker/) ๐**
A highly customizable and feature-rich date picker component built with Svelte 5, supporting Persian (Jalali), Gregorian, and Arabic calendars. This component is inspired by and converted from [Alireza's Vue3 Persian DatePicker](https://github.com/alireza-ab/vue3-persian-datepicker).
## โจ Features
### ๐
Selection Modes
- **Single Date**: Select one date
- **Date Range**: Select from one date to another
- **Multiple Dates**: Select multiple individual dates (click to toggle)
- **Time Only**: Select time without date
- **DateTime**: Select both date and time
- **DateTime Range**: Select from one datetime to another datetime
### ๐ Localization & Calendar Support
- **Persian (Jalali)**: Full support for Persian calendar
- **Gregorian**: Standard international calendar
- **Arabic**: Arabic calendar support
- **RTL/LTR**: Automatic direction support based on locale
### ๐จ Customization
- **Colors**: Multiple color themes (blue, red, pink, orange, green, purple, gray)
- **Formats**: Customizable display formats, input formats
- **Styles**: Full CSS customization support
- **Icons**: Custom icon support
- **Shortcuts**: Predefined shortcuts for quick selections
### ๐ก User Experience
- **Clearable Input**: Option to clear selected dates
- **Auto Submit**: Automatic submission on selection
- **Keyboard Navigation**: Full keyboard support
- **Modal Mode**: Can be displayed as modal
- **Dual Input**: Separate inputs for range selection
- **Validation**: Built-in date validation and disable rules
- **Smart Range Selection**:
- **Cross-Month Preview**: See your selected range highlight even when navigating between months.
- **Dynamic Disabling**: Automatically disables dates before the start date during range selection.
- **Easy Reset**: Clicking a new date when a range is already selected resets and starts a new selection.
- **Reactive Model**: Seamlessly syncs with parent state changes, supporting asynchronous data loading.
## ๐ Installation
```bash
npm install @hamedf/svelte-persian-datepicker
# or
pnpm install @hamedf/svelte-persian-datepicker
# or
yarn add @hamedf/svelte-persian-datepicker
```
## ๐ Basic Usage
```svelte
<script>
import DatePicker from '@hamedf/svelte-persian-datepicker';
let selectedDate = $state(''); // Svelte 5 rune
function handleSubmit(date) {
console.log('Selected date:', date);
}
</script>
<DatePicker
bind:model={selectedDate}
mode="single"
type="date"
submit={handleSubmit}
color="blue"
clearable={true}
/>
```
> **Note**: For more advanced examples including range selection, async loading, and disabling dates, check out the [demo route](src/routes/default-value/+page.svelte) in the repository.
## ๐ฏ Usage Examples
### Single Date Selection
```svelte
<DatePicker
bind:model={singleDate}
mode="single"
type="date"
submit={handleSingleDate}
color="blue"
/>
```
### Date Range Selection
```svelte
<DatePicker
bind:model={dateRange}
mode="range"
type="date"
submit={handleDateRange}
color="green"
/>
```
### Disable Previous Dates (Select from Today)
```svelte
<DatePicker
bind:model={selectedDate}
from={new Date()}
color="orange"
label="Select future date"
/>
```
## ๐ค GitHub Copilot Integration
This package includes a specialized instruction file for GitHub Copilot. When you use this package in your project, Copilot will automatically understand the Svelte 5 runes, the Gregorian model requirement, and the various selection modes.
You can find the detailed instructions in [.github/copilot-instructions.md](.github/copilot-instructions.md).
### Multiple Date Selection
```svelte
<DatePicker
bind:model={multipleDates}
mode="multiple"
type="date"
submit={handleMultipleDates}
color="purple"
auto_submit={false}
/>
```
### Time Selection
```svelte
<DatePicker
bind:model={selectedTime}
mode="single"
type="time"
input_format="HH:mm"
submit={handleTime}
color="orange"
/>
```
### DateTime Selection
```svelte
<DatePicker
bind:model={selectedDateTime}
mode="single"
type="datetime"
input_format="YYYY-MM-DD HH:mm"
submit={handleDateTime}
color="red"
/>
```
### DateTime Range Selection
```svelte
<DatePicker
bind:model={dateTimeRange}
mode="range"
type="datetime"
input_format="YYYY-MM-DD HH:mm"
submit={handleDateTimeRange}
color="pink"
/>
```
## โ๏ธ Props
| Prop | Type | Default | Description |
| ---------------- | ------------------------------------------------------------------------ | ----------- | -------------------------- |
| `model` | `string \| string[] \| PersianDate \| PersianDate[]` | `undefined` | The selected value(s) (Bindable) |
| `mode` | `'single' \| 'range' \| 'multiple'` | `'single'` | Selection mode |
| `type` | `'date' \| 'time' \| 'datetime'` | `'date'` | Type of picker |
| `format` | `string` | `undefined` | Output format (Gregorian) |
| `input_format` | `string` | `undefined` | Input parsing format |
| `display_format` | `string` | `undefined` | UI display format |
| `color` | `'blue' \| 'red' \| 'pink' \| 'orange' \| 'green' \| 'purple' \| 'gray'` | `undefined` | Color theme |
| `locale` | `string` | `'fa'` | Locale (fa, en, ar) |
| `clearable` | `boolean` | `true` | Show clear button |
| `auto_submit` | `boolean` | `true` | Auto submit on selection |
| `modal` | `boolean` | `false` | Display as modal |
| `dual_input` | `boolean` | `false` | Separate inputs for range |
| `shortcut` | `boolean \| object` | `false` | Enable shortcuts |
| `column` | `number \| object` | `1` | Number of calendar columns |
| `from` | `Date \| string` | `1921-03-22`| Minimum selectable date |
| `to` | `Date \| string` | `2051-03-21`| Maximum selectable date |
| `disable` | `string[] \| function \| RegExp` | `undefined` | Custom disable rules |
## ๐จ Events
| Event | Parameters | Description |
| -------- | ------------------------------------ | ---------------------------- |
| `submit` | `date: PersianDate \| PersianDate[]` | Fired when date is submitted |
| `select` | `date: PersianDate` | Fired when date is selected |
| `clear` | `none` | Fired when picker is cleared |
| `open` | `none` | Fired when picker opens |
| `close` | `none` | Fired when picker closes |
## ๐จ Styling
The component supports full CSS customization. You can override the default styles by targeting the component classes:
```css
/* Custom styling for multiple selection */
:global(.pdp-multiple .pdp-day.selected) {
background-color: #8b5cf6 !important;
color: white !important;
border-radius: 4px;
font-weight: 600;
}
/* Custom range styling */
:global(.pdp-range .pdp-day.start-range) {
background-color: your-color;
}
```
## ๐ง Development
### Prerequisites
- Node.js 18+
- pnpm
### Setup
```bash
# Clone the repository
git clone https://github.com/hamedf62/svelte-persian-datepicker
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Run tests
pnpm test
# Build for production
pnpm build
```
## ๐ Project Structure
```
src/
โโโ lib/
โ โโโ DatePicker.svelte # Main component
โ โโโ components/ # Sub-components
โ โ โโโ PDPArrow.svelte
โ โ โโโ PDPIcon.svelte
โ โ โโโ PDPAlt.svelte
โ โโโ modules/
โ โ โโโ core.ts # Core logic
โ โ โโโ types.ts # TypeScript types
โ โโโ assets/sass/ # Styles
โโโ routes/
โโโ +page.svelte # Demo page
```
## ๐งช Testing
The component includes comprehensive tests using Cypress:
```bash
# Run component tests
pnpm test:component
# Run e2e tests
pnpm test:e2e
# Open Cypress UI
pnpm cypress:open
```
## ๐ Documentation
For detailed documentation and API reference, visit [Alireza's Documentation](https://alireza-ab.ir/datepicker) as this component maintains compatibility with the original Vue3 version.
## ๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## ๐ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## ๐ Acknowledgments
- [Alireza-ab](https://github.com/alireza-ab) for the original Vue3 Persian DatePicker
- Persian calendar calculations and localization support
- Svelte community for the amazing framework
## ๐ Features Comparison
| Feature | Single | Range | Multiple | Time | DateTime | DateTime Range |
| --------------------- | ------ | ----- | -------- | ---- | -------- | -------------- |
| Select one date | โ
| โ | โ | โ | โ
| โ |
| Select date range | โ | โ
| โ | โ | โ | โ
|
| Select multiple dates | โ | โ | โ
| โ | โ | โ |
| Time selection | โ | โ | โ | โ
| โ
| โ
|
| Persian calendar | โ
| โ
| โ
| โ
| โ
| โ
|
| Keyboard navigation | โ
| โ
| โ
| โ
| โ
| โ
|
| Custom validation | โ
| โ
| โ
| โ
| โ
| โ
|
## ๐ค AI/LLM Integration Guide
This component has been optimized for AI coding assistants and LLMs. Here's how to work with it effectively:
### ๐ Quick Reference for AI Agents
```javascript
// COMPONENT SIGNATURE FOR AI REFERENCE
/**
* @component PersianDatePicker
* @description A comprehensive Svelte 5 Persian/Jalali DateTime picker
* @props {Object} Props - See interface below for all available props
* @bindable model - The selected date(s) value
* @example
* // Single date selection
* <DatePicker bind:model={selectedDate} />
*
* // Range selection
* <DatePicker mode="range" bind:model={dateRange} />
*
* // Multiple dates
* <DatePicker mode="multiple" bind:model={multipleDates} />
*
* // With custom validation
* <DatePicker
* bind:model={date}
* from="1400/01/01"
* to="1405/12/29"
* disable={['1403/01/01', '1403/05/15']}
* />
*/
```
### ๐ฏ Common AI Prompts & Solutions
#### For Setting Up Basic Date Selection:
```typescript
// AI: "Create a basic Persian date picker"
let selectedDate: string;
<DatePicker
bind:model={selectedDate}
locale="fa"
type="date"
mode="single"
/>
```
#### For Range Selection:
```typescript
// AI: "Create a date range picker for Persian calendar"
let dateRange: string[];
<DatePicker
bind:model={dateRange}
mode="range"
locale="fa"
dual_input={true}
/>
```
#### For Time Selection:
```typescript
// AI: "Add time picker functionality"
let selectedTime: string;
<DatePicker
bind:model={selectedTime}
type="time"
from="08:00"
to="20:00"
/>
```
#### For Multi-Calendar Support:
```typescript
// AI: "Support both Persian and Gregorian calendars"
let date: string;
<DatePicker
bind:model={date}
locale="fa,en"
input_calendar="auto"
/>
```
### ๐ง Props Reference for AI
**Essential Props for Common Use Cases:**
- `bind:model` - The selected date value(s) - **ALWAYS BINDABLE & REACTIVE**
- `mode` - Selection type: "single" | "range" | "multiple"
- `type` - Picker type: "date" | "time" | "datetime"
- `locale` - Language/calendar: "fa" | "en" | "ar" | "fa,en"
- `from`/`to` - Date boundaries (supports `Date` objects or strings)
- `disable` - Disabled dates/times (array, function, or regex)
**Styling & UI Props:**
- `color` - Theme: "blue" | "red" | "pink" | "orange" | "green" | "purple" | "gray"
- `dual_input` - Separate inputs for range mode
- `modal` - Show as modal overlay
- `clearable` - Show clear button
**Advanced Props:**
- `format` - Model data format (always Gregorian)
- `input_format` - Input parsing format
- `display_format` - UI display format
- `input_calendar` - Calendar for input: "auto" | "jalali" | "gregorian"
### ๐ก AI Best Practices
1. **Always use `bind:model`** for data binding. The component will automatically sync if the parent updates the value.
2. **Range Selection**: The component handles the flow (Start -> End). If a range is already selected, the next click resets it.
3. **Date Boundaries**: Use `from={new Date()}` to disable all previous dates easily.
4. **Model Format**: Remember that the `model` always uses Gregorian format (`YYYY-MM-DD`) for consistency, regardless of the displayed calendar.
5. **Async Data**: You can initialize the `model` with an empty string and update it later (e.g., after a fetch); the component will react accordingly.
3. **Use `from`/`to` props** for date boundaries
4. **Use `disable` prop** for validation rules
5. **Set `locale` appropriately** for language/calendar
6. **Consider `dual_input`** for better range UX