All files / src/components/RelativeDateField/hooks useRelativeDateFieldState.ts

82.14% Statements 23/28
80% Branches 28/35
75% Functions 3/4
82.14% Lines 23/28

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 1007x   7x                                                                         74x           74x 74x 2x     74x 3x     3x 3x 3x 3x 2x   1x             74x 21x 13x   8x     74x 74x 4x     74x   74x                                    
import React from 'react';
 
import {dateTimeParse, isLikeRelative} from '@gravity-ui/date-utils';
import type {DateTime} from '@gravity-ui/date-utils';
import {useControlledState} from '@gravity-ui/uikit';
 
import type {InputBase, Validation, ValueBase} from '../../types';
 
export interface RelativeDateFieldState {
    /** The current field value. */
    value: string | null;
    /** Sets the field value */
    setValue: (v: string | null) => void;
    /** Current user input */
    text: string;
    /** Sets text */
    setText: (t: string) => void;
    /** */
    parsedDate: DateTime | null;
    /** */
    lastCorrectDate: DateTime | null;
    /** */
    validationState?: 'invalid';
    /**
     * Whether the field is disabled.
     */
    disabled?: boolean;
    /**
     * Whether the value is immutable.
     */
    readOnly?: boolean;
}
 
export interface RelativeDateFieldOptions extends ValueBase<string | null>, InputBase, Validation {
    timeZone?: string;
    /** Round up parsed date to the nearest granularity. */
    roundUp?: boolean;
}
export function useRelativeDateFieldState(props: RelativeDateFieldOptions): RelativeDateFieldState {
    const [value, setValue] = useControlledState(
        props.value,
        props.defaultValue ?? null,
        props.onUpdate,
    );
 
    const [text, setText] = React.useState(value ?? '');
    if (value && value !== text) {
        setText(value);
    }
 
    const handleTextChange = (t: string) => {
        Iif (props.disabled || props.readOnly) {
            return;
        }
        setText(t);
        if (isLikeRelative(t)) {
            const date = dateTimeParse(t);
            if (date && date.isValid()) {
                setValue(t);
            } else {
                setValue(null);
            }
        } else E{
            setValue(null);
        }
    };
 
    const parsedDate = React.useMemo(() => {
        if (!value) {
            return null;
        }
        return dateTimeParse(value, {timeZone: props.timeZone, roundUp: props.roundUp}) ?? null;
    }, [value, props.timeZone, props.roundUp]);
 
    const [lastCorrectDate, setLastCorrectDate] = React.useState(parsedDate);
    if (parsedDate && parsedDate !== lastCorrectDate) {
        setLastCorrectDate(parsedDate);
    }
 
    const validationState = props.validationState || (text && !parsedDate) ? 'invalid' : undefined;
 
    return {
        value,
        setValue(v: string | null) {
            if (props.disabled || props.readOnly) {
                return;
            }
 
            setValue(v);
        },
        text,
        setText: handleTextChange,
        parsedDate,
        lastCorrectDate,
        validationState,
        disabled: props.disabled,
        readOnly: props.readOnly,
    };
}