import _extends from "@babel/runtime/helpers/esm/extends"; import * as React from 'react'; import { useRifm } from 'rifm'; import { useUtils } from './useUtils'; import { maskedDateFormatter, getDisplayDate, checkMaskIsValidForCurrentFormat, getMaskFromCurrentFormat } from '../utils/text-field-helper'; export const useMaskedInput = ({ acceptRegex = /[\d]/gi, disabled, disableMaskedInput, ignoreInvalidInputs, inputFormat, inputProps, label, mask, onChange, rawValue, readOnly, rifmFormatter, TextFieldProps, validationError }) => { const utils = useUtils(); const formatHelperText = utils.getFormatHelperText(inputFormat); const { shouldUseMaskedInput, maskToUse } = React.useMemo(() => { // formatting of dates is a quite slow thing, so do not make useless .format calls if (disableMaskedInput) { return { shouldUseMaskedInput: false, maskToUse: '' }; } const computedMaskToUse = getMaskFromCurrentFormat(mask, inputFormat, acceptRegex, utils); return { shouldUseMaskedInput: checkMaskIsValidForCurrentFormat(computedMaskToUse, inputFormat, acceptRegex, utils), maskToUse: computedMaskToUse }; }, [acceptRegex, disableMaskedInput, inputFormat, mask, utils]); const formatter = React.useMemo(() => shouldUseMaskedInput && maskToUse ? maskedDateFormatter(maskToUse, acceptRegex) : st => st, [acceptRegex, maskToUse, shouldUseMaskedInput]); // TODO: Implement with controlled vs uncontrolled `rawValue` const parsedValue = rawValue === null ? null : utils.date(rawValue); // Track the value of the input const [innerInputValue, setInnerInputValue] = React.useState(parsedValue); // control the input text const [innerDisplayedInputValue, setInnerDisplayedInputValue] = React.useState(getDisplayDate(utils, rawValue, inputFormat)); // Inspired from autocomplete: https://github.com/mui/material-ui/blob/2c89d036dc2e16f100528f161600dffc83241768/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js#L185:L201 const prevRawValue = React.useRef(); const prevLocale = React.useRef(utils.locale); const prevInputFormat = React.useRef(inputFormat); React.useEffect(() => { const rawValueHasChanged = rawValue !== prevRawValue.current; const localeHasChanged = utils.locale !== prevLocale.current; const inputFormatHasChanged = inputFormat !== prevInputFormat.current; prevRawValue.current = rawValue; prevLocale.current = utils.locale; prevInputFormat.current = inputFormat; if (!rawValueHasChanged && !localeHasChanged && !inputFormatHasChanged) { return; } const newParsedValue = rawValue === null ? null : utils.date(rawValue); const isAcceptedValue = rawValue === null || utils.isValid(newParsedValue); let innerEqualsParsed = innerInputValue === null && newParsedValue === null; // equal by being both null if (innerInputValue !== null && newParsedValue !== null) { const areEqual = utils.isEqual(innerInputValue, newParsedValue); if (areEqual) { innerEqualsParsed = true; } else { const diff = Math.abs(utils.getDiff(innerInputValue, newParsedValue)); // diff in ms innerEqualsParsed = diff === 0 ? areEqual // if no diff, use equal to test the time-zone : diff < 1000; // accept a difference bellow 1s } } if (!localeHasChanged && !inputFormatHasChanged && (!isAcceptedValue || innerEqualsParsed)) { return; } // When dev set a new valid value, we trust them const newDisplayDate = getDisplayDate(utils, rawValue, inputFormat); setInnerInputValue(newParsedValue); setInnerDisplayedInputValue(newDisplayDate); }, [utils, rawValue, inputFormat, innerInputValue]); const handleChange = text => { const finalString = text === '' || text === mask ? '' : text; setInnerDisplayedInputValue(finalString); const date = finalString === null ? null : utils.parse(finalString, inputFormat); if (ignoreInvalidInputs && !utils.isValid(date)) { return; } setInnerInputValue(date); onChange(date, finalString || undefined); }; const rifmProps = useRifm({ value: innerDisplayedInputValue, onChange: handleChange, format: rifmFormatter || formatter }); const inputStateArgs = shouldUseMaskedInput ? rifmProps : { value: innerDisplayedInputValue, onChange: event => { handleChange(event.currentTarget.value); } }; return _extends({ label, disabled, error: validationError, inputProps: _extends({}, inputStateArgs, { disabled, placeholder: formatHelperText, readOnly, type: shouldUseMaskedInput ? 'tel' : 'text' }, inputProps) }, TextFieldProps); };