@spaced-out/ui-design-system
Version:
Sense UI components library
113 lines (103 loc) • 2.83 kB
Flow
// @flow strict
import * as React from 'react';
// $FlowFixMe[untyped-import]
import moment from 'moment';
import type {DateRange} from '../../types';
import {
formatIsoDate,
getDaysInMonth,
inDateRange,
isEndOfRange,
isStartDateEndDateSame,
isStartOfRange,
MARKERS,
NAVIGATION_ACTION,
WEEKDAYS,
} from '../../utils';
import {
getTranslation,
isAfter,
isBefore,
isSame,
} from '../../utils/date-range-picker';
import {BodySmall, TEXT_COLORS} from '../Text';
import {Day} from './Day';
import css from './Calendar.module.css';
type CalendarProps = {
value: string,
marker: $Values<typeof MARKERS>,
minDate?: string,
maxDate?: string,
hoverDay: string,
dateRange: DateRange,
inHoverRange: (day: string) => boolean,
handlers: {
onDayClick: (day: string) => void,
onDayHover: (day: string) => void,
onMonthNavigate: (
marker: $Values<typeof MARKERS>,
action: $Values<typeof NAVIGATION_ACTION>,
) => void,
},
today: string,
t: ?(key: string, fallback: string) => string,
};
export const Calendar = ({
value,
marker,
minDate,
maxDate = formatIsoDate(),
handlers,
hoverDay,
dateRange,
inHoverRange,
today,
t,
}: CalendarProps): React.Node => (
<div className={css.calendar}>
<div className={css.calendarRow}>
{WEEKDAYS.map((day) => (
<BodySmall
key={day}
className={css.calendarRowItem}
color={TEXT_COLORS.tertiary}
>
{getTranslation(t, day)}
</BodySmall>
))}
</div>
{getDaysInMonth(value).map((week, index) => (
<div key={week[index]} className={css.calendarRow}>
{week.map((date: string) => {
const isRangeValid = isStartDateEndDateSame(dateRange);
const isStart = isStartOfRange(dateRange, date);
const isEnd = isEndOfRange(dateRange, date);
const highlighted =
inDateRange(dateRange, date) || inHoverRange(date);
const {onDayClick, onDayHover} = handlers;
const dateValue = moment.utc(date);
return (
<Day
key={date}
date={date}
filled={isStart || isEnd}
onClick={() => onDayClick(date)}
onHover={() => onDayHover(date)}
outlined={isSame(date, today, 'd')}
disabled={
(minDate && isBefore(date, minDate)) ||
isAfter(date, maxDate) ||
!isSame(date, value, 'month')
}
endOfRange={isEnd && !isRangeValid}
highlighted={highlighted && !isRangeValid}
startOfRange={isStart && !isRangeValid}
value={dateValue.date()}
hoverDay={hoverDay}
/>
);
})}
</div>
))}
</div>
);