All files / src/components/CalendarView/hooks useCalendarCellProps.ts

67.44% Statements 29/43
57.44% Branches 27/47
60% Functions 3/5
67.44% Lines 29/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 11519x                   4074x   4074x   4074x 4074x 1684x 5x       4074x 4074x 4074x 4074x 4074x   4074x   4074x   4074x 4074x 4074x 4074x 4074x   4074x   4074x           4074x                                                   4074x 4074x   4074x   4074x       4074x                                 4074x   4074x                              
import React from 'react';
 
import type {DateTime} from '@gravity-ui/date-utils';
import {useLang} from '@gravity-ui/uikit';
 
import {formatDateTime} from '../../utils/dates';
 
import type {CalendarState, RangeCalendarState} from './types';
 
export function useCalendarCellProps(date: DateTime, state: CalendarState | RangeCalendarState) {
    const ref = React.useRef<HTMLDivElement>(null);
 
    const {lang} = useLang();
 
    const isFocused = state.isCellFocused(date);
    React.useEffect(() => {
        if (isFocused) {
            ref.current?.focus({preventScroll: true});
        }
    }, [isFocused]);
 
    const tabIndex = state.focusedDate.isSame(date, state.mode) ? 0 : -1;
    const isDisabled = state.isCellDisabled(date);
    const isSelected = state.isSelected(date);
    const highlightedRange = 'highlightedRange' in state && state.highlightedRange;
    const isRangeSelection = Boolean(highlightedRange && isSelected);
    const isSelectionStart =
        isSelected && highlightedRange && date.isSame(highlightedRange.start, state.mode);
    const isSelectionEnd =
        isSelected && highlightedRange && date.isSame(highlightedRange.end, state.mode);
    const isOutsideCurrentRange =
        state.mode === 'days' ? !state.focusedDate.isSame(date, 'month') : false;
    const isUnavailable = state.isCellUnavailable(date);
    const isSelectable = !isDisabled && !isUnavailable;
    const isCurrent = state.isCurrent(date);
    const isWeekend = state.isWeekend(date);
 
    const label = getDateLabel(date, state, lang);
 
    const cellProps: React.HTMLAttributes<unknown> = {
        role: 'gridcell',
        'aria-selected': isSelected ? 'true' : undefined,
        'aria-disabled': isDisabled ? 'true' : undefined,
    };
 
    const buttonProps: React.HTMLAttributes<unknown> & {ref: React.Ref<HTMLDivElement>} = {
        ref,
        role: 'button',
        tabIndex: isDisabled ? undefined : tabIndex,
        'aria-disabled': isSelectable ? undefined : 'true',
        'aria-label': label,
        onClick: isSelectable
            ? () => {
                  state.setFocusedDate(date);
                  state.selectDate(date);
              }
            : undefined,
        onPointerEnter() {
            if ('highlightDate' in state && isSelectable) {
                if (isOutsideCurrentRange) {
                    const newDate = date.isBefore(state.focusedDate)
                        ? state.focusedDate.startOf('month')
                        : state.focusedDate.endOf('month').startOf('date');
                    state.highlightDate(newDate);
                } else {
                    state.highlightDate(date);
                }
            }
        },
    };
 
    let formattedDate = formatDateTime(date, 'D', state.timeZone, lang);
    Iif (state.mode === 'months') {
        formattedDate = formatDateTime(date, 'MMM', state.timeZone, lang);
    I} else if (state.mode === 'quarters') {
        formattedDate = formatDateTime(date, '[Q]Q', state.timeZone, lang);
    I} else if (state.mode === 'years') {
        formattedDate = formatDateTime(date, 'YYYY', state.timeZone, lang);
    }
 
    return {
        cellProps,
        buttonProps,
        formattedDate,
        isDisabled,
        isSelected,
        isRangeSelection,
        isSelectionStart,
        isSelectionEnd,
        isOutsideCurrentRange,
        isUnavailable,
        isCurrent,
        isWeekend,
    };
}
 
function getDateLabel(date: DateTime, state: CalendarState | RangeCalendarState, lang: string) {
    switch (state.mode) {
        case 'days': {
            return `${formatDateTime(date, 'dddd', state.timeZone, lang)}, ${formatDateTime(date, 'LL', state.timeZone, lang)}`;
        }
        case 'months': {
            return `${formatDateTime(date, 'MMMM YYYY', state.timeZone, lang)}`;
        }
        case 'quarters': {
            return `${formatDateTime(date, '[Q]Q YYYY', state.timeZone, lang)}`;
        }
        case 'years': {
            return `${formatDateTime(date, 'YYYY', state.timeZone, lang)}`;
        }
        default:
            return '';
    }
}