Calendar
A calendar renders a series of pages showing the days, weeks, and months of a particular year. A single date can be selected within a calendar.
| Install | yarn add @diallink-corp/convergo-react-calendar |
|---|---|
| Version | 4.1.2 |
| Usage | import {Calendar} from '@diallink-corp/convergo-react-calendar' |
Uncontrolled Value
By default, the Calendar component handles its value uncontrolled. In the uncontrolled variant you can
pass in a defaultValue to set the default date.
<Calendar defaultValue={new CalendarDate(2021, 12, 14)} />
<Calendar defaultValue={new CalendarDate(2021, 12, 14)} />
<Calendar
defaultValue={new CalendarDate(
2021,
12,
14
)}
/>
Controlled Value
You can also handle the value of the component in a controlled manner. To do so, you can pass in a value
prop as well as an onChange handler to modify the value when the user changes the date.
function Example() {
const [date, setDate] = useState(new CalendarDate(1997, 10, 14));
return (
<Calendar value={date} onChange={setDate} />
);
}
function Example() {
const [date, setDate] = useState(
new CalendarDate(1997, 10, 14)
);
return <Calendar value={date} onChange={setDate} />;
}
function Example() {
const [date, setDate] =
useState(
new CalendarDate(
1997,
10,
14
)
);
return (
<Calendar
value={date}
onChange={setDate}
/>
);
}
Calendar and Locale
The calendar component supports most calendar types across the globe as well as all browser locales for accessibility.
function Example() {
const calendars = [
{ key: 'gregory', name: 'Gregorian' },
{ key: 'japanese', name: 'Japanese' },
{ key: 'buddhist', name: 'Buddhist' },
{ key: 'roc', name: 'Taiwan' },
{ key: 'persian', name: 'Persian' },
{ key: 'indian', name: 'Indian' },
{ key: 'islamic-umalqura', name: 'Islamic (Umm al-Qura)' },
{ key: 'islamic-civil', name: 'Islamic Civil' },
{ key: 'islamic-tbla', name: 'Islamic Tabular' },
{ key: 'hebrew', name: 'Hebrew' },
{ key: 'coptic', name: 'Coptic' },
{ key: 'ethiopic', name: 'Ethiopic' },
{ key: 'ethioaa', name: 'Ethiopic (Amete Alem)' }
];
const [calendar, setCalendar] = useState(calendars[0].key);
// https://github.com/unicode-org/cldr/blob/22af90ae3bb04263f651323ce3d9a71747a75ffb/common/supplemental/supplementalData.xml#L4649-L4664
const locales = [
{ label: 'Default', locale: 'en-US', ordering: 'gregory' },
{
label: 'Arabic (Algeria)',
locale: 'ar-DZ',
territories: 'DJ DZ EH ER IQ JO KM LB LY MA MR OM PS SD SY TD TN YE',
ordering: 'gregory islamic islamic-civil islamic-tbla'
},
{
label: 'Arabic (United Arab Emirates)',
locale: 'ar-AE',
territories: 'AE BH KW QA',
ordering: 'gregory islamic-umalqura islamic islamic-civil islamic-tbla'
},
{
label: 'Arabic (Egypt)',
locale: 'AR-EG',
territories: 'EG',
ordering: 'gregory coptic islamic islamic-civil islamic-tbla'
},
{
label: 'Arabic (Saudi Arabia)',
locale: 'ar-SA',
territories: 'SA',
ordering: 'islamic-umalqura gregory islamic islamic-rgsa'
},
{
label: 'Farsi (Afghanistan)',
locale: 'fa-AF',
territories: 'AF IR',
ordering: 'persian gregory islamic islamic-civil islamic-tbla'
},
{
label: 'Amharic (Ethiopia)',
locale: 'am-ET',
territories: 'ET',
ordering: 'gregory ethiopic ethioaa'
},
{
label: 'Hebrew (Israel)',
locale: 'he-IL',
territories: 'IL',
ordering: 'gregory hebrew islamic islamic-civil islamic-tbla'
},
{
label: 'Hindi (India)',
locale: 'hi-IN',
territories: 'IN',
ordering: 'gregory indian'
},
{
label: 'Japanese (Japan)',
locale: 'ja-JP',
territories: 'JP',
ordering: 'gregory japanese'
},
{
label: 'Thai (Thailand)',
locale: 'th-TH',
territories: 'TH',
ordering: 'buddhist gregory'
},
{
label: 'Chinese (Taiwan)',
locale: 'zh-TW',
territories: 'TW',
ordering: 'gregory roc chinese'
}
];
const { locale: defaultLocale } = useLocale();
const [locale, setLocale] = useState(defaultLocale);
const [date, setDate] = useState(new CalendarDate(2021, 12, 8));
const handleLocaleChange = (locale) => {
setLocale(locale);
const fullLocale = locales.find((p) => p.locale === locale);
setCalendar(fullLocale.ordering.split(' ')[0]);
};
return (
<div>
<Select
label="Locale"
items={locales}
selectedKey={locale}
onSelectionChange={handleLocaleChange}
>
{(item) => <Item key={item.locale}>{item.label}</Item>}
</Select>
<Select
label="Calendar"
items={calendars}
selectedKey={calendar}
onSelectionChange={setCalendar}
>
{(item) => <Item key={item.key}>{item.name}</Item>}
</Select>
<ConvergoProvider locale={``}>
<Calendar value={date} onChange={setDate} />
</ConvergoProvider>
</div>
);
}
function Example() {
const calendars = [
{ key: 'gregory', name: 'Gregorian' },
{ key: 'japanese', name: 'Japanese' },
{ key: 'buddhist', name: 'Buddhist' },
{ key: 'roc', name: 'Taiwan' },
{ key: 'persian', name: 'Persian' },
{ key: 'indian', name: 'Indian' },
{
key: 'islamic-umalqura',
name: 'Islamic (Umm al-Qura)'
},
{ key: 'islamic-civil', name: 'Islamic Civil' },
{ key: 'islamic-tbla', name: 'Islamic Tabular' },
{ key: 'hebrew', name: 'Hebrew' },
{ key: 'coptic', name: 'Coptic' },
{ key: 'ethiopic', name: 'Ethiopic' },
{ key: 'ethioaa', name: 'Ethiopic (Amete Alem)' }
];
const [calendar, setCalendar] = useState(
calendars[0].key
);
// https://github.com/unicode-org/cldr/blob/22af90ae3bb04263f651323ce3d9a71747a75ffb/common/supplemental/supplementalData.xml#L4649-L4664
const locales = [
{
label: 'Default',
locale: 'en-US',
ordering: 'gregory'
},
{
label: 'Arabic (Algeria)',
locale: 'ar-DZ',
territories:
'DJ DZ EH ER IQ JO KM LB LY MA MR OM PS SD SY TD TN YE',
ordering: 'gregory islamic islamic-civil islamic-tbla'
},
{
label: 'Arabic (United Arab Emirates)',
locale: 'ar-AE',
territories: 'AE BH KW QA',
ordering:
'gregory islamic-umalqura islamic islamic-civil islamic-tbla'
},
{
label: 'Arabic (Egypt)',
locale: 'AR-EG',
territories: 'EG',
ordering:
'gregory coptic islamic islamic-civil islamic-tbla'
},
{
label: 'Arabic (Saudi Arabia)',
locale: 'ar-SA',
territories: 'SA',
ordering:
'islamic-umalqura gregory islamic islamic-rgsa'
},
{
label: 'Farsi (Afghanistan)',
locale: 'fa-AF',
territories: 'AF IR',
ordering:
'persian gregory islamic islamic-civil islamic-tbla'
},
{
label: 'Amharic (Ethiopia)',
locale: 'am-ET',
territories: 'ET',
ordering: 'gregory ethiopic ethioaa'
},
{
label: 'Hebrew (Israel)',
locale: 'he-IL',
territories: 'IL',
ordering:
'gregory hebrew islamic islamic-civil islamic-tbla'
},
{
label: 'Hindi (India)',
locale: 'hi-IN',
territories: 'IN',
ordering: 'gregory indian'
},
{
label: 'Japanese (Japan)',
locale: 'ja-JP',
territories: 'JP',
ordering: 'gregory japanese'
},
{
label: 'Thai (Thailand)',
locale: 'th-TH',
territories: 'TH',
ordering: 'buddhist gregory'
},
{
label: 'Chinese (Taiwan)',
locale: 'zh-TW',
territories: 'TW',
ordering: 'gregory roc chinese'
}
];
const { locale: defaultLocale } = useLocale();
const [locale, setLocale] = useState(defaultLocale);
const [date, setDate] = useState(
new CalendarDate(2021, 12, 8)
);
const handleLocaleChange = (locale) => {
setLocale(locale);
const fullLocale = locales.find((p) =>
p.locale === locale
);
setCalendar(fullLocale.ordering.split(' ')[0]);
};
return (
<div>
<Select
label="Locale"
items={locales}
selectedKey={locale}
onSelectionChange={handleLocaleChange}
>
{(item) => (
<Item key={item.locale}>{item.label}</Item>
)}
</Select>
<Select
label="Calendar"
items={calendars}
selectedKey={calendar}
onSelectionChange={setCalendar}
>
{(item) => <Item key={item.key}>{item.name}</Item>}
</Select>
<ConvergoProvider
locale={``}
>
<Calendar value={date} onChange={setDate} />
</ConvergoProvider>
</div>
);
}
function Example() {
const calendars = [
{
key: 'gregory',
name: 'Gregorian'
},
{
key: 'japanese',
name: 'Japanese'
},
{
key: 'buddhist',
name: 'Buddhist'
},
{
key: 'roc',
name: 'Taiwan'
},
{
key: 'persian',
name: 'Persian'
},
{
key: 'indian',
name: 'Indian'
},
{
key:
'islamic-umalqura',
name:
'Islamic (Umm al-Qura)'
},
{
key:
'islamic-civil',
name:
'Islamic Civil'
},
{
key:
'islamic-tbla',
name:
'Islamic Tabular'
},
{
key: 'hebrew',
name: 'Hebrew'
},
{
key: 'coptic',
name: 'Coptic'
},
{
key: 'ethiopic',
name: 'Ethiopic'
},
{
key: 'ethioaa',
name:
'Ethiopic (Amete Alem)'
}
];
const [
calendar,
setCalendar
] = useState(
calendars[0].key
);
// https://github.com/unicode-org/cldr/blob/22af90ae3bb04263f651323ce3d9a71747a75ffb/common/supplemental/supplementalData.xml#L4649-L4664
const locales = [
{
label: 'Default',
locale: 'en-US',
ordering: 'gregory'
},
{
label:
'Arabic (Algeria)',
locale: 'ar-DZ',
territories:
'DJ DZ EH ER IQ JO KM LB LY MA MR OM PS SD SY TD TN YE',
ordering:
'gregory islamic islamic-civil islamic-tbla'
},
{
label:
'Arabic (United Arab Emirates)',
locale: 'ar-AE',
territories:
'AE BH KW QA',
ordering:
'gregory islamic-umalqura islamic islamic-civil islamic-tbla'
},
{
label:
'Arabic (Egypt)',
locale: 'AR-EG',
territories: 'EG',
ordering:
'gregory coptic islamic islamic-civil islamic-tbla'
},
{
label:
'Arabic (Saudi Arabia)',
locale: 'ar-SA',
territories: 'SA',
ordering:
'islamic-umalqura gregory islamic islamic-rgsa'
},
{
label:
'Farsi (Afghanistan)',
locale: 'fa-AF',
territories:
'AF IR',
ordering:
'persian gregory islamic islamic-civil islamic-tbla'
},
{
label:
'Amharic (Ethiopia)',
locale: 'am-ET',
territories: 'ET',
ordering:
'gregory ethiopic ethioaa'
},
{
label:
'Hebrew (Israel)',
locale: 'he-IL',
territories: 'IL',
ordering:
'gregory hebrew islamic islamic-civil islamic-tbla'
},
{
label:
'Hindi (India)',
locale: 'hi-IN',
territories: 'IN',
ordering:
'gregory indian'
},
{
label:
'Japanese (Japan)',
locale: 'ja-JP',
territories: 'JP',
ordering:
'gregory japanese'
},
{
label:
'Thai (Thailand)',
locale: 'th-TH',
territories: 'TH',
ordering:
'buddhist gregory'
},
{
label:
'Chinese (Taiwan)',
locale: 'zh-TW',
territories: 'TW',
ordering:
'gregory roc chinese'
}
];
const {
locale: defaultLocale
} = useLocale();
const [
locale,
setLocale
] = useState(
defaultLocale
);
const [date, setDate] =
useState(
new CalendarDate(
2021,
12,
8
)
);
const handleLocaleChange =
(locale) => {
setLocale(locale);
const fullLocale =
locales.find(
(p) =>
p.locale ===
locale
);
setCalendar(
fullLocale
.ordering
.split(' ')[0]
);
};
return (
<div>
<Select
label="Locale"
items={locales}
selectedKey={locale}
onSelectionChange={handleLocaleChange}
>
{(item) => (
<Item
key={item
.locale}
>
{item.label}
</Item>
)}
</Select>
<Select
label="Calendar"
items={calendars}
selectedKey={calendar}
onSelectionChange={setCalendar}
>
{(item) => (
<Item
key={item
.key}
>
{item.name}
</Item>
)}
</Select>
<ConvergoProvider
locale={``}
>
<Calendar
value={date}
onChange={setDate}
/>
</ConvergoProvider>
</div>
);
}
Min and Max Value
You can specify a minimum and maximum date that the user can select.
<Calendar
defaultValue={new CalendarDate(2019, 2, 10)}
minValue={new CalendarDate(2019, 2, 5)}
maxValue={new CalendarDate(2019, 2, 15)}
/>
<Calendar
defaultValue={new CalendarDate(2019, 2, 10)}
minValue={new CalendarDate(2019, 2, 5)}
maxValue={new CalendarDate(2019, 2, 15)}
/>
<Calendar
defaultValue={new CalendarDate(
2019,
2,
10
)}
minValue={new CalendarDate(
2019,
2,
5
)}
maxValue={new CalendarDate(
2019,
2,
15
)}
/>
Visible Months
You can define how many months should be visible through the visibleMonths prop.
<Calendar defaultValue={new CalendarDate(2019, 6, 5)} visibleMonths={3} />
<Calendar
defaultValue={new CalendarDate(2019, 6, 5)}
visibleMonths={3}
/>
<Calendar
defaultValue={new CalendarDate(
2019,
6,
5
)}
visibleMonths={3}
/>
Disabled
The Calendar component can be disabled via the isDisabled prop.
<Calendar defaultValue={new CalendarDate(2019, 6, 5)} isDisabled />
<Calendar
defaultValue={new CalendarDate(2019, 6, 5)}
isDisabled
/>
<Calendar
defaultValue={new CalendarDate(
2019,
6,
5
)}
isDisabled
/>
Unavailable Dates
The Calendar component allows to mark certain dates as unavailable.
function Example() {
const now = today(getLocalTimeZone());
const disabledRanges = [
[now, now.add({ days: 5 })],
[now.add({ days: 14 }), now.add({ days: 16 })],
[now.add({ days: 23 }), now.add({ days: 24 })]
];
const { locale } = useLocale();
const isDateUnavailable = (date) =>
isWeekend(date, locale) ||
disabledRanges.some((interval) =>
date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0
);
return (
<Calendar
aria-label="Meeting date"
minValue={today(getLocalTimeZone())}
isDateUnavailable={isDateUnavailable}
/>
);
}
function Example() {
const now = today(getLocalTimeZone());
const disabledRanges = [
[now, now.add({ days: 5 })],
[now.add({ days: 14 }), now.add({ days: 16 })],
[now.add({ days: 23 }), now.add({ days: 24 })]
];
const { locale } = useLocale();
const isDateUnavailable = (date) =>
isWeekend(date, locale) ||
disabledRanges.some((interval) =>
date.compare(interval[0]) >= 0 &&
date.compare(interval[1]) <= 0
);
return (
<Calendar
aria-label="Meeting date"
minValue={today(getLocalTimeZone())}
isDateUnavailable={isDateUnavailable}
/>
);
}
function Example() {
const now = today(
getLocalTimeZone()
);
const disabledRanges =
[
[
now,
now.add({
days: 5
})
],
[
now.add({
days: 14
}),
now.add({
days: 16
})
],
[
now.add({
days: 23
}),
now.add({
days: 24
})
]
];
const { locale } =
useLocale();
const isDateUnavailable =
(date) =>
isWeekend(
date,
locale
) ||
disabledRanges
.some((
interval
) =>
date.compare(
interval[0]
) >= 0 &&
date.compare(
interval[1]
) <= 0
);
return (
<Calendar
aria-label="Meeting date"
minValue={today(
getLocalTimeZone()
)}
isDateUnavailable={isDateUnavailable}
/>
);
}
Read Only
The Calendar component can be marked as read only via the isReadOnly prop.
<Calendar defaultValue={new CalendarDate(2019, 6, 5)} isReadOnly />
<Calendar
defaultValue={new CalendarDate(2019, 6, 5)}
isReadOnly
/>
<Calendar
defaultValue={new CalendarDate(
2019,
6,
5
)}
isReadOnly
/>