انتخابگر تاریخ (DatePicker)
کامپوننت انتخاب بازه تاریخ با پشتیبانی از تقویم شمسی و میلادی
معرفی
کامپوننت Date Picker برای انتخاب بازه تاریخ (از تاریخ شروع تا تاریخ پایان) استفاده میشود. این کامپوننت از تقویم شمسی (جلالی) و میلادی پشتیبانی میکند و به طور کامل RTL است.
چه زمانی استفاده نکنیم:
- برای هر بازهٔ زمانی (از … تا) — از
DateRangePickerبا بازههای آمادهاش استفاده کنید. حالت بازهٔ DatePicker (mode="range"، که هنوز پیشفرض است) منسوخ است و قاعدهٔ ESLintparto/date-range-controlآن را گزارش میکند؛mode="single"بنویسید - وقتی فقط ماه یا سال لازم دارید — از
Selectاستفاده کنید
زمین بازی
با تغییر تنظیمات زیر، پیشنمایش زنده را مشاهده کنید.
استفاده پایه
import { DatePicker } from '@partodata/ui'
import { useState } from 'react'
import { DateRange } from 'react-day-picker'
export default function MyComponent() {
const [dateRange, setDateRange] = useState<DateRange | undefined>()
return <DatePicker value={dateRange} onChange={setDateRange} placeholder="انتخاب بازه تاریخ" />
}تقویم شمسی (پیشفرض)
از نسخهٔ 4.0 تقویم پیشفرض شمسی است، مگر اینکه locale برابر en یا ar باشد (پیش از آن پیشفرض همیشه میلادی بود). برای تقویم میلادی usePersianCalendar={false} بدهید؛ مقدار صریح usePersianCalendar همیشه بر locale مقدم است. DateTimePicker و Calendar هنوز بهطور پیشفرض میلادیاند.
// تقویم شمسی (پیشفرض)
;<DatePicker value={dateRange} onChange={setDateRange} placeholder="انتخاب بازه تاریخ" />
// تقویم میلادی
;<DatePicker value={dateRange} onChange={setDateRange} usePersianCalendar={false} />برچسب دکمه همان برچسب DateRangePicker است: «25 - 30 دی 1402» برای بازه و «25 دی 1402» برای یک روز. ارقام با حروف لاتین در DOM نوشته میشوند و فونت آنها را با قابلیت ss01 فارسی نشان میدهد، تا کپی، جستوجو و صفحهخوان درست کار کنند. تا 3٫x برچسب شمسی به شکل «1402/10/25» و با کد ارقام فارسی نوشته میشد.
اندازه و عرض
دکمهٔ باز کننده روی همان نردبان اندازهٔ کنترلها (xs تا xl) قرار دارد؛ پیشفرض md (38 پیکسل) است، اندازهٔ فیلد فرم، و در نوار ابزار، FilterBar و سرِ کارتها و سربرگها ردیف آن را sm (30 پیکسل) میکند. بهطور پیشفرض دکمه تمام عرض ظرفش را با حداقل 220 پیکسل پر میکند؛ در نوار ابزار و ردیف فیلتر با autoWidth عرض آن به اندازهٔ متنش میشود:
<DatePicker size="xs" autoWidth value={dateRange} onChange={setDateRange} />انتخاب یک تاریخ (بدون بازه)
برای انتخاب فقط یک تاریخ (نه بازه تاریخی)، باید mode را 'single' قرار دهید:
const [date, setDate] = useState<DateRange | undefined>()
;<DatePicker
value={date}
onChange={setDate}
placeholder="انتخاب تاریخ"
usePersianCalendar={true}
mode="single"
numberOfMonths={1}
/>نکته: برای دریافت تاریخ انتخاب شده از date?.from استفاده کنید.
// دریافت تاریخ انتخاب شده
const selectedDate = date?.from
console.log(selectedDate) // Date object یا undefinedتعداد ماهها
میتوانید تعداد ماههای نمایش داده شده را تغییر دهید:
<DatePicker value={dateRange} onChange={setDateRange} numberOfMonths={1} />بازههای پیشفرض (Presets)
با فعال کردن showPresets، دکمههای بازههای پیشفرض نمایش داده میشود:
تقویم شمسی با Presets
<DatePicker value={dateRange} onChange={setDateRange} showPresets={true} usePersianCalendar={true} />تقویم میلادی با Presets
<DatePicker value={dateRange} onChange={setDateRange} showPresets={true} usePersianCalendar={false} />بازههای پیشفرض همان بازههای آمادهٔ DateRangePicker است (DEFAULT_DATE_RANGE_PRESETS):
- 7 روز اخیر / Last 7 days
- 14 روز اخیر / Last 14 days
- ماه گذشته (30 روز) / Last 30 days
- 3 ماه گذشته / Last 3 months
- 6 ماه گذشته / Last 6 months
- 1 سال اخیر / Last year
زبان این برچسبها از locale تعیین میشود (نه از usePersianCalendar) — یعنی <DatePicker locale="fa" usePersianCalendar={false} showPresets />
روی تقویم میلادی هم برچسبهای فارسی نشان میدهد، و locale="ar" برچسبهای عربی میدهد. locale را روی خود
DatePicker تکرار نکنید: اگر تنظیم نشود، زبان صفحه است (locale قاب محصول یا قالب صفحه، که یک بار روی قاب داده
میشود). فقط بیرون از قاب و قالب از تقویم تشخیص داده میشود («fa» برای تقویم شمسی که پیشفرض است، «en» با
usePersianCalendar={false}).
جایگزین کردن بازههای پیشفرض
برای دورههای اختصاصی بهجای شش گزینهی پیشفرض، آرایهی خودتان را به presets بدهید:
import { subDays } from 'date-fns'
const today = new Date()
;<DatePicker
showPresets
presets={[
{ label: 'سه روز اخیر', range: { from: subDays(today, 2), to: today } },
{ label: 'امسال', range: { from: new Date(today.getFullYear(), 0, 1), to: today } },
]}
/>محدودیت تاریخ
میتوانید حداقل و حداکثر تاریخ قابل انتخاب را مشخص کنید:
<DatePicker value={dateRange} onChange={setDateRange} minDate={new Date(2024, 0, 1)} maxDate={new Date(2024, 11, 31)} />روزهای خارج از این بازه غیرفعال میشوند (قابل کلیک نیستند و onChange را صدا نمیزنند) و حرکت بین ماهها هم به همین بازه محدود میشود — همان مکانیزم disabled/startMonth/endMonth که DateRangePicker استفاده میکند.
غیرفعال کردن
<DatePicker value={dateRange} onChange={setDateRange} disabled={true} />راهنمای استفاده
بکنید
- از DatePicker برای انتخاب یک تاریخ مشخص یا بازه تاریخی در فرمها استفاده کنید - تقویم شمسی پیشفرض است؛ فقط برای
محصول میلادی
usePersianCalendar={false}بدهید - ازshowPresetsبرای بازههای رایج (7 روز اخیر، ماه گذشته) استفاده کنید تا انتخاب سریعتر شود - در ردیف فیلترsizeرا با کنترلهای کناری یکی کنید وautoWidthبدهید
نکنید
- وقتی فقط نیاز به انتخاب دورههای از پیش تعریفشده دارید (مانند 7 روز، 30 روز) از DatePicker استفاده نکنید — از
PeriodSelectorاستفاده کنید - بدون تنظیمplaceholderمناسب از DatePicker استفاده نکنید - فراموش نکنید که مقادیرDateهمیشه میلادی هستند، حتی وقتی تقویم شمسی فعال است
Props
نکات مهم
نوع DateRange
نوع DateRange از کتابخانه react-day-picker میآید:
import { DateRange } from 'react-day-picker'
type DateRange = {
from: Date | undefined
to: Date | undefined
}تقویم شمسی
هنگام استفاده از usePersianCalendar={true}:
- ✅ نمایش ماههای شمسی (فروردین، اردیبهشت، ...)
- ✅ نمایش اعداد فارسی (1، 2، 3، ...)
- ✅ نمایش روزهای هفته به فارسی (ش، ی، د، ...)
- ✅ سال شمسی در عنوان
- ⚠️ مقادیر
Dateهمچنان میلادی هستند (فقط نمایش شمسی است)
انتخاب یک تاریخ
برای انتخاب یک تاریخ به جای بازه تاریخی:
- مقدار
modeرا'single'قرار دهید (ضروری) - توصیه میشود
numberOfMonthsرا1قرار دهید - از
value?.fromبرای دسترسی به تاریخ انتخاب شده استفاده کنید - در حالت
single، دکمههای preset نمایش داده نمیشوند
مثالهای کاربردی
فیلتر گزارش
const [reportRange, setReportRange] = useState<DateRange>()
;<DatePicker value={reportRange} onChange={setReportRange} placeholder="بازه گزارش" usePersianCalendar={true} />رزرو هتل
const [checkInOut, setCheckInOut] = useState<DateRange>()
;<DatePicker value={checkInOut} onChange={setCheckInOut} placeholder="تاریخ ورود و خروج" numberOfMonths={2} />با فرم
در یک فیلد فرم، DatePicker داخل FormRow است و به field در react-hook-form همانطور
وصل میشود که جدول «کنترل هر نوع فیلد» میگوید: یک تاریخ با mode="single" (مقدار فیلد یک Date است)، و یک
بازه با حالت پیشفرض (مقدار فیلد { from, to } است).
import { useForm } from 'react-hook-form'
import { DatePicker } from '@partodata/ui'
import { Form, FormField } from '@partodata/ui/form'
import { FormRow } from '@partodata/ui/templates'
type ReportValues = {
start: Date | undefined
period: { from: Date | undefined; to?: Date } | undefined
}
function ReportForm() {
const form = useForm<ReportValues>()
return (
<Form {...form}>
<FormField
control={form.control}
name="start"
rules={{ required: 'تاریخ شروع را انتخاب کنید' }}
render={({ field, fieldState }) => (
<FormRow label="تاریخ شروع" required error={fieldState.error?.message}>
<DatePicker
mode="single"
value={field.value ? { from: field.value } : undefined}
onChange={(range) => field.onChange(range?.from)}
/>
</FormRow>
)}
/>
<FormField
control={form.control}
name="period"
render={({ field }) => (
<FormRow label="بازهٔ گزارش">
<DatePicker value={field.value} onChange={field.onChange} />
</FormRow>
)}
/>
</Form>
)
}رابطه با کامپوننتهای دیگر
- Calendar: کامپوننت داخلی که برای نمایش تقویم استفاده میشود
- Popover: برای نمایش تقویم در یک پاپاور
- Button: برای دکمه باز کردن تقویم
- DateRangePicker: کامپوننت مشابه با امکانات بیشتر
دسترسیپذیری
- دکمه trigger یک
<button>استاندارد است؛ با Enter/Space باز میشود و popover تقویم فوکس را بهصورت Radix Popover trap میکند. - در تقویم: کلیدهای جهت (← → ↑ ↓) برای جابهجایی روز،
Page Up/Page Downبرای ماه، وHome/Endبرای ابتدا/انتهای هفته کار میکنند. Enterتاریخ زیر فوکس را انتخاب میکند؛ درmode="range"پس از انتخاب از/تا popover خودکار بسته میشود.Escapepopover را بدون اعمال تغییر میبندد و فوکس به دکمه trigger برمیگردد.- preset buttons (وقتی
showPresets={true}است) عناصر button استاندارد با focus ring هستند — با Tab قابل دسترس و با Enter قابل فعالسازی. - روزهای انتخابشده
aria-selected="true"و روزهای غیرفعال (خارج از minDate/maxDate)aria-disabled="true"هستند — screen reader وضعیت را اعلام میکند. - در حالت
usePersianCalendar={true}، نام ماه/روز و اعداد به فارسی اعلام میشوند ولی مقدارDateهمچنان میلادی باقی میماند — بنابراین value معنادار است.
کامپوننتهای مرتبط
- DateRangePicker — اگر نیاز به انتخاب بازه تاریخی با label و امکانات بیشتر دارید، از DateRangePicker استفاده کنید
- PeriodSelector — اگر کاربر فقط از بین دورههای از پیش تعریفشده انتخاب میکند (7 روز، 30 روز)، PeriodSelector سادهتر است
- Calendar — اگر نیاز به نمایش تقویم بدون input field و popover دارید، از Calendar مستقیماً استفاده کنید