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                   1932x   1932x   1932x 1932x 1386x 2x       1932x 1932x 1932x 1932x 1932x   1932x   1932x   1932x 1932x 1932x 1932x 1932x   1932x   1932x           1932x                                                   1932x 1932x   1932x   1932x       1932x                                 1932x   1932x                              
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 '';
    }
}