Skip to content

Commit

Permalink
feat: add ability to add custom classes to each day.
Browse files Browse the repository at this point in the history
This will allow custom functionality such as differentiating what kind of
'invalid' a day might be. e.g. when used as a booking calendar, you might
not be allowed to select a given day to check in because it's sold out,
or it may simply not be a valid check-in day. Differentiating this is
key to user experience.
  • Loading branch information
coling committed Aug 2, 2022
1 parent ee53c38 commit 44be8c6
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/constant/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DefaultTheme } from "styled-components";
import { ElementType, ReactNode } from "react";
import { Dayjs } from "dayjs";

type HeaderIconsPosition = {
right: ReactNode;
Expand Down Expand Up @@ -35,6 +36,7 @@ export interface InitialProps {
numberOfMonths?: number;
initialMonthAndYear?: string;
onRangeDateInScreen?: DatePickerWindowUpdated;
dayClasses?: (day: Dayjs) => string[];
}

type DatePickerWindow = { start: string; end: string };
Expand Down
2 changes: 2 additions & 0 deletions src/datePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const DatePicker = ({
onChange,
initialMonthAndYear,
onRangeDateInScreen,
dayClasses,
}: DatePickerProps) => {
const [selectedDays, setSelectedDays] = useState(selectedDaysProps || []);
const [numberOfMonths, setNumberOfMonths] = useState(numberOfMonthsProps);
Expand Down Expand Up @@ -129,6 +130,7 @@ export const DatePicker = ({
disabledBeforeDate={disabledBeforeDate}
disabledBeforeToday={disabledBeforeToday}
numberOfSelectableDays={numberOfSelectableDays}
dayClasses={dayClasses}
/>
)}
</ThemeProvider>
Expand Down
8 changes: 7 additions & 1 deletion src/datePicker/Day.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Props = {
components?: DatePickerComponents;
onChange: DatePickerOnChange;
setSelectedDays: Dispatch<SetStateAction<string[]>>;
dayClasses?: (day: Dayjs) => string[];
};

export const Day: React.FC<Props> = ({
Expand All @@ -40,6 +41,7 @@ export const Day: React.FC<Props> = ({
numberOfSelectableDays,
disabledBeforeDate,
disabledAfterDate,
dayClasses,
}) => {
if (disabledBeforeToday) {
const today = dayjs().format(FORMAT_DATE);
Expand Down Expand Up @@ -134,6 +136,10 @@ export const Day: React.FC<Props> = ({
};

const DayComponent = components?.days;
let extraDayClasses = "";
if (dayClasses) {
extraDayClasses = dayClasses(day).join(" ");
}
return (
<Wrapper
data-test={day.format(FORMAT_DATE)}
Expand All @@ -147,7 +153,7 @@ export const Day: React.FC<Props> = ({
dayjs()
.calendar(jalali ? "jalali" : "gregory")
.format(FORMAT_DATE) === day.format(FORMAT_DATE),
})}
}, extraDayClasses)}
>
{DayComponent && (
<DayComponent day={day.format(FORMAT_DATE)} jalali={jalali} />
Expand Down
3 changes: 3 additions & 0 deletions src/datePicker/Months.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface Props {
components?: DatePickerComponents;
setSource: Dispatch<SetStateAction<Dayjs>>;
setSelectedDays: Dispatch<SetStateAction<string[]>>;
dayClasses?: (day: Dayjs) => string[];
}

export const Months = ({
Expand All @@ -41,6 +42,7 @@ export const Months = ({
disabled,
onChange,
source: sourceProp,
dayClasses,
}: Props) => {
const renderMonths = () => {
let months = [];
Expand Down Expand Up @@ -90,6 +92,7 @@ export const Months = ({
disabledBeforeDate={disabledBeforeDate}
disabledAfterDate={disabledAfterDate}
numberOfSelectableDays={numberOfSelectableDays}
dayClasses={dayClasses}
/>
))}
</Weeks>
Expand Down
8 changes: 7 additions & 1 deletion src/rangePicker/Day.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface Props {
setSelectedDays: Dispatch<
SetStateAction<RangePickerSelectedDays | undefined>
>;
dayClasses?: (day: Dayjs) => string[];
}

export const Day = ({
Expand All @@ -52,6 +53,7 @@ export const Day = ({
disabledBeforeToday,
disabledBeforeDate,
disabledAfterDate,
dayClasses,
}: Props) => {
if (disabledBeforeToday) {
const today = dayjs().format(FORMAT_DATE);
Expand Down Expand Up @@ -199,6 +201,10 @@ export const Day = ({
};

const DayComponent = components?.days;
let extraDayClasses = "";
if (dayClasses) {
extraDayClasses = dayClasses(day).join(" ");
}
return (
<Wrapper
data-test={day.format(FORMAT_DATE)}
Expand Down Expand Up @@ -228,7 +234,7 @@ export const Day = ({
dayjs()
.calendar(jalali ? "jalali" : "gregory")
.format(FORMAT_DATE) === day.format(FORMAT_DATE),
})}
}, extraDayClasses)}
>
{DayComponent && (
<DayComponent day={day.format(FORMAT_DATE)} jalali={jalali} />
Expand Down
3 changes: 3 additions & 0 deletions src/rangePicker/Months.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface Props {
setSelectedDays: Dispatch<
SetStateAction<RangePickerSelectedDays | undefined>
>;
dayClasses?: (day: Dayjs) => string[];
}

export const Months = ({
Expand All @@ -52,6 +53,7 @@ export const Months = ({
disabled,
onChange,
source: sourceProp,
dayClasses,
}: Props) => {
const renderMonths = () => {
let months = [];
Expand Down Expand Up @@ -103,6 +105,7 @@ export const Months = ({
allowDisabledDaysSpan={allowDisabledDaysSpan}
disabledBeforeDate={disabledBeforeDate}
disabledAfterDate={disabledAfterDate}
dayClasses={dayClasses}
/>
))}
</Weeks>
Expand Down
2 changes: 2 additions & 0 deletions src/rangePicker/RangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const RangePicker = ({
onChange,
initialMonthAndYear,
onRangeDateInScreen,
dayClasses,
}: RangePickerProps) => {
const [selectedDays, setSelectedDays] = useState(selectedDaysProps);
const [hoverDay, setHoverDay] = useState<string>();
Expand Down Expand Up @@ -130,6 +131,7 @@ export const RangePicker = ({
disabledBeforeDate={disabledBeforeDate}
disabledAfterDate={disabledAfterDate}
allowDisabledDaysSpan={allowDisabledDaysSpan}
dayClasses={dayClasses}
/>
)}
</ThemeProvider>
Expand Down
17 changes: 17 additions & 0 deletions src/stories/DatePicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,23 @@ stories.add("Selected Days", () => {
);
});

stories.add("Custom Day Classes", () => {
return (
<>
<style type="text/css">{`
.odd { transform: rotate(-10deg); } .even { transform: rotate(10deg); }
`}</style>
<DatePicker
numberOfMonths={1}
autoResponsive={false}
initialMonthAndYear="2021-08"
onChange={dates => window.console.log(dates)}
dayClasses={day => [parseInt(day.format('D')) % 2 == 1 ? 'odd' : 'even' ]}
/>
</>
);
});

stories.add("Number of Selectable Days", () => {
return (
<DatePicker
Expand Down
17 changes: 17 additions & 0 deletions src/stories/RangePicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,23 @@ stories.add("Allow Disabled Days Span", () => {
);
});

stories.add("Custom Day Classes", () => {
return (
<>
<style type="text/css">{`
.odd { transform: rotate(-10deg); } .even { transform: rotate(10deg); }
`}</style>
<RangePicker
numberOfMonths={1}
autoResponsive={false}
initialMonthAndYear="2021-08"
onChange={dates => window.console.log(dates)}
dayClasses={day => [parseInt(day.format('D')) % 2 == 1 ? 'odd' : 'even' ]}
/>
</>
);
});

stories.add("Custom components - Title of weeks Component", () => {
return (
<RangePicker
Expand Down

0 comments on commit 44be8c6

Please sign in to comment.