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 11514x                   1974x   1974x   1974x 1974x 1260x 2x       1974x 1974x 1974x 1974x 1974x   1974x   1974x   1974x 1974x 1974x 1974x 1974x   1974x   1974x           1974x                                                   1974x 1974x   1974x   1974x       1974x                                 1974x   1974x                              
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 '';
    }
}