پرش به مطلب اصلی

DateRangePicker

کامپوننت DateRangePicker برای انتخاب یک بازه‌ی تاریخ بر پایه‌ی تقویم شمسی (جلالی) استفاده می‌شود؛ مثل فیلتر بازه‌ی زمانی در گزارش‌ها یا تعیین تاریخ ورود و خروج. پنل آن دو ماه کنار هم نمایش می‌دهد و بازه‌ی در حال انتخاب را به‌صورت زنده highlight می‌کند.

Import​

import { DateRangePicker } from "fara-ui";

اگر هنوز FaraUI را نصب و راه‌اندازی نکرده‌ای، ابتدا صفحه‌ی شروع به کار را ببین.

Basic Usage​

import { useState } from "react";
import { DateRangePicker } from "fara-ui";

export function ReportRangePicker() {
const [range, setRange] = useState(null);

return (
<div>
<DateRangePicker
value={range}
onChange={setRange}
placeholder="بازه‌ی گزارش را انتخاب کنید"
/>
{range && (
<p>
از {range.start.year}/{range.start.month}/{range.start.day}
{" تا "}
{range.end.year}/{range.end.month}/{range.end.day}
</p>
)}
</div>
);
}

برای مقدار اولیه‌ی غیرکنترل‌شده از defaultValue استفاده کن:

<DateRangePicker
defaultValue={{
start: { year: 1404, month: 1, day: 1 },
end: { year: 1404, month: 1, day: 7 },
}}
onChange={(nextRange) => console.log(nextRange)}
/>

Playground​

<DateRangePicker
value={range}
onChange={setRange}
placeholder="انتخاب بازه‌ی تاریخ"
/>

Range Selection​

  1. کلیک اول، تاریخ شروع بازه را انتخاب می‌کند.
  2. با حرکت ماوس روی روزها، بازه‌ی در حال انتخاب به‌صورت زنده پیش‌نمایش می‌شود.
  3. کلیک دوم، تاریخ پایان را مشخص می‌کند. اگر تاریخ پایان قبل از شروع انتخاب شود، به‌صورت خودکار جابه‌جا می‌شوند تا ترتیب درست بماند.

مقادیر پنل فقط با کلیک روی «تأیید» در onChange ثبت می‌شوند؛ بستن پنل (کلیک بیرون یا Escape) بدون تأیید، مقدار قبلی را حفظ می‌کند. اگر فقط تاریخ شروع انتخاب و تأیید شود، بازه‌ی تک‌روزه (start == end) ثبت می‌شود.

Range Value​

مقدار ورودی/خروجی کامپوننت یک شیء با تاریخ‌های شمسی است و به‌صورت پیش‌فرض معادل میلادی آن هم برگردانده می‌شود:

interface DateRangeValue {
start: JalaliDate; // { year, month, day } شمسی
end: JalaliDate;
startGregorian?: Date; // با includeGregorian (پیش‌فرض true)
endGregorian?: Date;
}

اگر فقط معادل میلادی را نیاز داری، includeGregorian را روشن بگذار و از startGregorian/endGregorian استفاده کن؛ برای به‌روزرسانی state لازم نیست خودت تبدیل انجام بدهی.

Restricting the Selectable Range​

  • minDate / maxDate — حد پایین و بالای بازه‌ی قابل انتخاب؛ هر دو یا هر کدام به‌صورت Date میلادی یا JalaliDate شمسی. روزهای خارج از محدوده غیرفعال می‌شوند و پیمایش ماه هم محدود می‌شود.
  • disabledDates — تابعی که یک Date میلادی می‌گیرد و اگر true برگرداند، آن روز غیرفعال می‌شود؛ مثلاً تعطیلات.
<DateRangePicker
minDate={new Date("2025-03-21")}
disabledDates={(date) => date.getDay() === 5} // جمعه‌ها
/>

بازه‌ی سال قابل‌پیمایش از ۱۳۰۰ تا ۱۵۰۰ (شمسی) محدود شده است.

مثال کامل برای فیلتر گزارش:

function SalesReportFilter() {
const [range, setRange] = useState(null);

function loadReport() {
if (!range?.startGregorian || !range.endGregorian) return;

const params = new URLSearchParams({
from: range.startGregorian.toISOString(),
to: range.endGregorian.toISOString(),
});

console.log(`/api/reports/sales?${params}`);
}

return (
<div>
<DateRangePicker
value={range}
onChange={setRange}
minDate={new Date("2025-03-21")}
disabledDates={(date) => date.getDay() === 5}
/>
<button type="button" disabled={!range} onClick={loadReport}>
دریافت گزارش
</button>
</div>
);
}

Controlled vs Uncontrolled​

DateRangePicker هر دو حالت را پشتیبانی می‌کند: با value کنترل‌شده و با defaultValue غیرکنترل‌شده.

Accessibility​

  • دکمه‌های پیمایش ماه (قبلی/بعدی) دارای aria-label مناسب هستند.
  • پنل با کلیک بیرون از کامپوننت یا کلید Escape بسته می‌شود.

Data Attributes and Customize CSS​

DateRangePicker hookهای پایدار زیر را در DOM تولید می‌کند:

Attributeکاربرد
data-fara-date-range-pickerریشه‌ی کامپوننت
data-fara-date-range-picker-inputفیلد نمایش بازه
data-fara-date-range-picker-panelپنل انتخاب؛ در Portal قرار می‌گیرد
data-fara-date-range-picker-day-cellسلول هر روز
data-fara-date-range-picker-month-columnستون هر ماه
data-fara-date-range-picker-footer-buttonدکمه‌های پایین پنل

سلول‌های روز stateهایی مثل data-selected, data-in-range و data-today دارند:

[data-fara-date-range-picker-day-cell][data-in-range] {
background: #ede9fe;
}

[data-fara-date-range-picker-day-cell][data-selected] {
background: #7c3aed;
color: white;
}

className روی wrapper اصلی و inputClassName روی input اعمال می‌شود:

<DateRangePicker
className="booking-range"
inputClassName="booking-range-input"
value={range}
onChange={setRange}
/>
.booking-range {
width: 320px;
}

.booking-range-input {
border-radius: 12px;
}

پنل با Portal داخل document.body رندر می‌شود؛ برای استایل پنل از hook مربوط به data-fara-date-range-picker-panel استفاده کن.

SSR Note​

DateRangePicker با SSR و Next.js سازگار است و در زمان رندر سرور خروجی پنل تولید نمی‌کند. پنل پس از hydration در مرورگر فعال می‌شود و نیازی به dynamic(..., { ssr: false }) نیست.

Props​

PropTypeDefaultDescription
valueDateRangeValue | null-بازه‌ی انتخاب‌شده (controlled)
defaultValueDateRangeValue | nullnullبازه‌ی اولیه (uncontrolled)
onChange(value: DateRangeValue) => void-با کلیک روی «تأیید» صدا زده می‌شود
minDateDate | JalaliDate-حد پایین بازه‌ی قابل انتخاب
maxDateDate | JalaliDate-حد بالای بازه‌ی قابل انتخاب
disabledDates(date: Date) => boolean-غیرفعال‌کردن روزهای خاص
includeGregorianbooleantrueافزودن معادل میلادی به مقدار خروجی
placeholderstring"انتخاب بازه‌ی تاریخ"متن راهنما وقتی بازه‌ای انتخاب نشده
disabledbooleanfalseغیرفعال کردن کل کامپوننت
classNamestring-کلاس CSS اضافی برای سفارشی‌سازی
inputClassNamestring-کلاس CSS اضافی مخصوص فیلد ورودی نمایش بازه