All files / src/components/RangeDatePicker RangeDatePicker.tsx

100% Statements 11/11
81.25% Branches 13/16
100% Functions 4/4
100% Lines 11/11

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    2x                                     2x         20x   20x     20x   20x   20x                 2x                                                             1x     14x             14x            
'use client';
 
import React from 'react';
 
import type {DateTime} from '@gravity-ui/date-utils';
import {Calendar as CalendarIcon, Clock as ClockIcon} from '@gravity-ui/icons';
import {Button, Icon, Popup, TextInput} from '@gravity-ui/uikit';
 
import {block} from '../../utils/cn';
import {RangeCalendar} from '../Calendar';
import {useDatePickerProps} from '../DatePicker';
import type {DatePickerProps} from '../DatePicker';
import {StubButton} from '../DatePicker/StubButton';
import {HiddenInput} from '../HiddenInput/HiddenInput';
import {RangeDateField} from '../RangeDateField';
import type {RangeValue} from '../types';
 
import {useRangeDatePickerState} from './hooks/useRangeDatePickerState';
 
import './RangeDatePicker.scss';
 
const b = block('range-date-picker');
 
export type RangeDatePickerProps = DatePickerProps<RangeValue<DateTime>>;
 
export function RangeDatePicker({className, ...props}: RangeDatePickerProps) {
    const [anchor, setAnchor] = React.useState<HTMLDivElement | null>(null);
 
    const state = useRangeDatePickerState(props);
 
    const {groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps} =
        useDatePickerProps(state, props);
 
    const isOnlyTime = state.formatInfo.hasTime && !state.formatInfo.hasDate;
 
    return (
        <div className={b(null, className)} {...groupProps}>
            {!isOnlyTime && (
                <div ref={setAnchor} className={b('popup-anchor')}>
                    <Popup anchorElement={anchor} {...popupProps}>
                        <div className={b('popup-content')}>
                            {typeof props.children === 'function' ? (
                                props.children({...calendarProps, value: state.value})
                            ) : (
                                <RangeCalendar {...calendarProps} value={state.value} />
                            )}
                            {state.formatInfo.hasTime && (
                                <div className={b('time-field-wrapper')}>
                                    <RangeDateField {...timeInputProps} />
                                </div>
                            )}
                        </div>
                    </Popup>
                </div>
            )}
            <TextInput
                {...fieldProps}
                className={b('field')}
                endContent={
                    <React.Fragment>
                        {!isOnlyTime && (
                            <Button {...calendarButtonProps}>
                                <Icon data={CalendarIcon} />
                            </Button>
                        )}
                        {isOnlyTime && (
                            <StubButton size={calendarButtonProps.size} icon={ClockIcon} />
                        )}
                    </React.Fragment>
                }
            />
            <HiddenInput
                name={props.name}
                form={props.form}
                onReset={(v) => {
                    state.dateFieldState.setDate(v);
                }}
                value={state.value}
                toStringValue={(v) => (v ? v.start.toISOString() : '')}
                disabled={state.disabled}
            />
            <HiddenInput
                name={props.name}
                form={props.form}
                value={state.value}
                toStringValue={(v) => (v ? v.end.toISOString() : '')}
                disabled={state.disabled}
            />
        </div>
    );
}