UNPKG

@kubit-ui-web/react-components

Version:

Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience

178 lines 8.86 kB
import { jsx as _jsx } from "react/jsx-runtime"; import React from 'react'; import { ItemRove } from '../../../components/itemRove/itemRove'; import { useRoveFocus } from '../../../hooks/useRoveFocus/useRoveFocus'; import { useUtilsProvider } from '../../../provider/utils/provider'; import { NEUTRAL_DATE } from '../../../types/date/date'; import { ButtonType } from '../../button/types/type'; import { WEEK_DAYS } from '../constants/constants'; import { getAllDaysInMonth } from '../utils/getAllDaysInMonth'; import { getFirstDayOfMonth } from '../utils/getFirstDayOfMonth'; import { getStateDay } from '../utils/getState'; import { groupDaysByWeeks } from '../utils/groupDaysByWeeks'; import { getDaysAndEmptyDaysUntilMaxDate, getFirstEmptyAndDisabledDays, handleKeyDownMove, handleKeyLeftMove, handleKeyPageDownMove, handleKeyPageUpMove, handleKeyRightMove, handleKeyTabMove, handleKeyUpMove, } from '../utils/handleKeysmoves'; // styles import { ElementEmptyStyled, ElementStyled, ItemRoveStyled, ListStyled, TableRowStyled, } from './list.styled'; import { ListDaysStateType } from './types/state'; export const List = ({ dataTestId = 'item', hasRange, selectedDate, disabledDates = [], ...props }) => { const { formatDate, dateHelpers, transformDate } = useUtilsProvider(); const currentMonth = props.currentDate.getMonth() + 1; const currentYear = props.currentDate.getFullYear(); const today = formatDate(new Date(), NEUTRAL_DATE); const days = getAllDaysInMonth(currentMonth, currentYear); const dayStarted = getFirstDayOfMonth(currentYear, currentMonth - 1) - (props.sundayFirst ? 0 : 1); const dayList = [...new Array(dayStarted >= 0 ? dayStarted : 6), ...days]; const emptyDaysList = dayList.filter(day => day === undefined); const [positionDateRange, setPositionDateRange] = React.useState(0); const [ghostDateSelected, setGhostDateSelected] = React.useState(0); const handleKeyMoveConfig = { dayList, maxDate: props.maxDate, currentDate: props.currentDate, minDate: props.minDate, firstEmptyAndDisabledDays: getFirstEmptyAndDisabledDays(emptyDaysList, props.minDate, props.currentDate), daysAndEmptyDaysUntilMaxDate: getDaysAndEmptyDaysUntilMaxDate(emptyDaysList, props.maxDate, props.currentDate), }; const config = React.useMemo(() => ({ calendarBlankDaysSize: emptyDaysList.length, size: dayList.length, keyDownMove: handleKeyDownMove(handleKeyMoveConfig), keyUpMove: handleKeyUpMove(handleKeyMoveConfig), keyRightMove: handleKeyRightMove(handleKeyMoveConfig), keyLeftMove: handleKeyLeftMove(handleKeyMoveConfig), keyTabMove: handleKeyTabMove, keyPageDownMove: handleKeyPageDownMove(handleKeyMoveConfig), keyPageUpMove: handleKeyPageUpMove(handleKeyMoveConfig), currentFocusSelected: (selectedDate[0] ? selectedDate[0].getDate() : new Date().getDate()) + emptyDaysList.length - 1, }), [emptyDaysList.length, dayList.length, props.currentDate, props.minDate, props.maxDate]); const [focus, setFocus, listEl] = useRoveFocus(config); const handleFocus = (index) => { // when focus is on an empty date at the beginning if (index) { if (focus < emptyDaysList.length) { setFocus(emptyDaysList.length); } // when focus is on an empty date at the end if (focus > dayList.length) { setFocus(dayList.length - 1); } } return focus === index; }; const onChangeSelectedDate = (newDate) => { const [firstDate, secondDate] = selectedDate; if (hasRange) { if ((firstDate && secondDate) || (!firstDate && !secondDate)) { props.setSelectedDate([newDate, 0]); setPositionDateRange(1); if (newDate instanceof Date) { props.onDayClick?.(newDate.getDate().toString()); } } else { props.setSelectedDate([firstDate, newDate]); setPositionDateRange(0); if (newDate instanceof Date) { props.onDayClick?.(newDate.getDate().toString()); } } } else { props.setSelectedDate([newDate]); if (newDate instanceof Date) { props.onDayClick?.(newDate.getDate().toString()); } } }; const isGhostSelected = (dayFormatted) => { if (ghostDateSelected) { if (ghostDateSelected < selectedDate[0]) { return dayFormatted > ghostDateSelected && dayFormatted < selectedDate[0]; } else if (ghostDateSelected > selectedDate[0]) { return dayFormatted < ghostDateSelected && dayFormatted > selectedDate[0]; } } else if (dayFormatted > selectedDate[0]) { return dayFormatted < selectedDate[1]; } else if (dayFormatted < selectedDate[0]) { return dayFormatted > selectedDate[1]; } return false; }; const isSelectedToLeft = (dayFormatted) => { if (!hasRange) { return false; } const selectedIndex = selectedDate?.findIndex(date => date && dayFormatted && formatDate(date, NEUTRAL_DATE) === formatDate(dayFormatted, NEUTRAL_DATE)); if (selectedIndex === 0 && ghostDateSelected) { return ghostDateSelected < dayFormatted; } else if (selectedIndex === 0) { return dayFormatted > selectedDate[1]; } else if (selectedIndex === 1) { return dayFormatted > selectedDate[0]; } return false; }; const isSelectedToRight = (dayFormatted) => { if (!hasRange) { return false; } const selectedIndex = selectedDate?.findIndex(date => date && dayFormatted && formatDate(date, NEUTRAL_DATE) === formatDate(dayFormatted, NEUTRAL_DATE)); if (selectedIndex === 0 && ghostDateSelected) { return ghostDateSelected > dayFormatted; } else if (selectedIndex === 0) { return dayFormatted < selectedDate[1]; } else if (selectedIndex === 1) { return dayFormatted < selectedDate[0]; } return false; }; const buildDays = () => { return groupDaysByWeeks(dayList).map((grupo, index) => (_jsx(TableRowStyled, { children: grupo.map((day, dayIndex) => { const dayFormatted = day ? day : 0; let isDisabled = day ? dateHelpers.isBefore(day, props.minDate) || dateHelpers.isAfter(day, transformDate(formatDate(props.maxDate, NEUTRAL_DATE), NEUTRAL_DATE)) : true; if (!isDisabled) { isDisabled = disabledDates.some(disabledDate => day && dateHelpers.isDatesEqual(day, disabledDate, false)); } const stateDay = getStateDay({ dayFormatted, isSelectedToLeft, isSelectedToRight, isGhostSelected, selectedDate, hasRange, today, formatDate, }); return day ? (_jsx(ItemRoveStyled, { "$disabled": isDisabled, "aria-selected": stateDay === ListDaysStateType.SELECTED ? true : undefined, state: stateDay, styles: props.styles, children: _jsx(ItemRove, { ariaDisabled: isDisabled, ariaLabel: formatDate(day, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', }), asElement: ElementStyled, dataTestId: `${dataTestId}-${dayIndex + WEEK_DAYS * index}`, focus: handleFocus(dayIndex + WEEK_DAYS * index), index: dayIndex + WEEK_DAYS * index, type: ButtonType.BUTTON, onMouseOver: () => { if (positionDateRange === 1) { setGhostDateSelected(dayFormatted); } }, onSelectItem: () => { !isDisabled && onChangeSelectedDate(dayFormatted); }, children: day.getDate() }) }, `day${dayIndex + WEEK_DAYS * index}${dayFormatted}`)) : (_jsx(ElementEmptyStyled, { "aria-hidden": true, "aria-label": "empty day" }, `day${dayIndex + WEEK_DAYS * index}${dayFormatted}`)); }) }, index))); }; return (_jsx(ListStyled, { ref: listEl, styles: props.styles, children: buildDays() })); }; //# sourceMappingURL=list.js.map