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 11520x                   4200x   4200x   4200x 4200x 1894x 5x       4200x 4200x 4200x 4200x 4200x   4200x   4200x   4200x 4200x 4200x 4200x 4200x   4200x   4200x           4200x                                                   4200x 4200x   4200x   4200x       4200x                                 4200x   4200x                              
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);
    } else Iif (state.mode === 'quarters') {
        formattedDate = formatDateTime(date, '[Q]Q', state.timeZone, lang);
    } else Iif (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 '';
    }
}