✨(react) extend Calendar functionalities with range selection
Extend the functionality of the DatePicker component to include support for a range calendar. This enhancement allows users to select a date range spanning multiple calendar cells, enabling more flexible date selection.
This commit is contained in:
committed by
aleb_the_flash
parent
219d08c82e
commit
3631367e14
@@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo, useRef } from "react";
|
import React, { forwardRef, Ref, useMemo, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
CalendarDate,
|
CalendarDate,
|
||||||
createCalendar,
|
createCalendar,
|
||||||
@@ -11,15 +11,24 @@ import {
|
|||||||
useDateFormatter,
|
useDateFormatter,
|
||||||
useLocale,
|
useLocale,
|
||||||
} from "@react-aria/i18n";
|
} from "@react-aria/i18n";
|
||||||
import { useCalendarState } from "@react-stately/calendar";
|
import {
|
||||||
import { useCalendar } from "@react-aria/calendar";
|
CalendarState,
|
||||||
|
RangeCalendarState,
|
||||||
|
useCalendarState,
|
||||||
|
useRangeCalendarState,
|
||||||
|
} from "@react-stately/calendar";
|
||||||
|
import {
|
||||||
|
CalendarAria,
|
||||||
|
useCalendar,
|
||||||
|
useRangeCalendar,
|
||||||
|
} from "@react-aria/calendar";
|
||||||
import {
|
import {
|
||||||
useSelect,
|
useSelect,
|
||||||
UseSelectReturnValue,
|
UseSelectReturnValue,
|
||||||
UseSelectStateChange,
|
UseSelectStateChange,
|
||||||
} from "downshift";
|
} from "downshift";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { CalendarProps } from "react-aria";
|
import { CalendarProps, RangeCalendarProps } from "react-aria";
|
||||||
import { range } from ":/utils";
|
import { range } from ":/utils";
|
||||||
import { Button } from ":/components/Button";
|
import { Button } from ":/components/Button";
|
||||||
import { CalendarGrid } from ":/components/Forms/DatePicker/CalendarGrid";
|
import { CalendarGrid } from ":/components/Forms/DatePicker/CalendarGrid";
|
||||||
@@ -75,29 +84,25 @@ const DropdownValues = ({ options, downShift }: DropdownValuesProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
interface CalendarSubProps extends CalendarProps<DateValue> {
|
interface CalendarAuxProps extends CalendarAria {
|
||||||
minYear?: number;
|
minYear?: number;
|
||||||
maxYear?: number;
|
maxYear?: number;
|
||||||
|
state: RangeCalendarState | CalendarState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Calendar = ({
|
const CalendarAux = forwardRef(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
state,
|
||||||
minYear = 1900, // in gregorian calendar.
|
minYear = 1900, // in gregorian calendar.
|
||||||
maxYear = 2050, // in gregorian calendar.
|
maxYear = 2050, // in gregorian calendar.
|
||||||
...props
|
prevButtonProps,
|
||||||
}: CalendarSubProps) => {
|
nextButtonProps,
|
||||||
const { locale } = useLocale();
|
calendarProps,
|
||||||
|
}: CalendarAuxProps,
|
||||||
|
ref: Ref<HTMLDivElement>
|
||||||
|
) => {
|
||||||
const { t } = useCunningham();
|
const { t } = useCunningham();
|
||||||
const ref = useRef(null);
|
|
||||||
|
|
||||||
const state = useCalendarState({
|
|
||||||
...props,
|
|
||||||
locale,
|
|
||||||
createCalendar,
|
|
||||||
});
|
|
||||||
const { calendarProps, prevButtonProps, nextButtonProps } = useCalendar(
|
|
||||||
props,
|
|
||||||
state
|
|
||||||
);
|
|
||||||
|
|
||||||
const useTimeZoneFormatter = (formatOptions: DateFormatterOptions) => {
|
const useTimeZoneFormatter = (formatOptions: DateFormatterOptions) => {
|
||||||
return useDateFormatter({
|
return useDateFormatter({
|
||||||
@@ -261,7 +266,8 @@ export const Calendar = ({
|
|||||||
onClick={() => state.focusPreviousSection(true)}
|
onClick={() => state.focusPreviousSection(true)}
|
||||||
disabled={
|
disabled={
|
||||||
!!state.minValue &&
|
!!state.minValue &&
|
||||||
state.minValue.year > state.focusedDate.add({ years: -1 }).year
|
state.minValue.year >
|
||||||
|
state.focusedDate.add({ years: -1 }).year
|
||||||
}
|
}
|
||||||
aria-label={t(
|
aria-label={t(
|
||||||
"components.forms.date_picker.previous_year_button_aria_label"
|
"components.forms.date_picker.previous_year_button_aria_label"
|
||||||
@@ -302,4 +308,29 @@ export const Calendar = ({
|
|||||||
<DropdownValues options={yearItems} downShift={downshiftYear} />
|
<DropdownValues options={yearItems} downShift={downshiftYear} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Calendar = (props: CalendarProps<DateValue>) => {
|
||||||
|
const { locale } = useLocale();
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const state = useCalendarState({
|
||||||
|
...props,
|
||||||
|
locale,
|
||||||
|
createCalendar,
|
||||||
|
});
|
||||||
|
const calendarProps = useCalendar(props, state);
|
||||||
|
return <CalendarAux {...calendarProps} state={state} ref={ref} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CalendarRange = (props: RangeCalendarProps<DateValue>) => {
|
||||||
|
const { locale } = useLocale();
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const state = useRangeCalendarState({
|
||||||
|
...props,
|
||||||
|
locale,
|
||||||
|
createCalendar,
|
||||||
|
});
|
||||||
|
const calendarProps = useRangeCalendar(props, state, ref);
|
||||||
|
return <CalendarAux {...calendarProps} state={state} ref={ref} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import {
|
|||||||
today,
|
today,
|
||||||
} from "@internationalized/date";
|
} from "@internationalized/date";
|
||||||
import { useCalendarGrid } from "react-aria";
|
import { useCalendarGrid } from "react-aria";
|
||||||
import { CalendarState } from "@react-stately/calendar";
|
import { CalendarState, RangeCalendarState } from "@react-stately/calendar";
|
||||||
import { CalendarCell } from ":/components/Forms/DatePicker/CalendarCell";
|
import { CalendarCell } from ":/components/Forms/DatePicker/CalendarCell";
|
||||||
import { range } from ":/utils";
|
import { range } from ":/utils";
|
||||||
|
|
||||||
interface CalendarGridProps {
|
interface CalendarGridProps {
|
||||||
state: CalendarState;
|
state: CalendarState | RangeCalendarState;
|
||||||
defaultDaysInWeek?: number;
|
defaultDaysInWeek?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user