@kubit-ui-web/react-components
Version:
Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience
364 lines • 17.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useInputDate = void 0;
const react_1 = require("react");
const useInput_1 = require("../../../hooks/useInput/useInput");
const provider_1 = require("../../../provider/utils/provider");
const formatDate_1 = require("../../../utils/date/formatDate");
const formatDateToNative_1 = require("../../../utils/syntheticComponents/syntheticDate/helper/formatDateToNative");
const syntheticDate_1 = require("../../../utils/syntheticComponents/syntheticDate/syntheticDate");
const useInternalValidations_1 = require("../../input/hooks/useInternalValidations");
const input_1 = require("../../input/types/input");
const internalErrors_1 = require("../../input/types/internalErrors");
const verifyDate_1 = require("../utils/verifyDate");
const useInputDate = ({ ref, errorExecution, internalErrorExecution, keyValidation, max, min, maxLength, minLength, maxDate = new Date(), mask, maskType, disabled, error, currentValue, today = '', type, truncate, informationAssociated, disabledCopyAndPaste, onWrapperBlur, onBlur, onChange, onFocus, onKeyDown, onError, onInternalErrors, onPaste, ...props }) => {
// Ghost prototype
const { setDate } = (0, react_1.useMemo)(() => {
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
return (0, syntheticDate_1.syntheticDate)(props.name);
}
return { setDate: () => null };
}, []);
// Auxiliar methods
const buildRangeDates = (date) => {
const orderDates = date.sort((a, b) => new Date(a).getTime() - new Date(b).getTime());
return {
startDate: orderDates[0],
endDate: orderDates[1],
};
};
const getDate = (date) => {
if (date) {
const formatedDate = formatDate(date, props.format);
return formatedDate;
}
return '';
};
const orderStringDates = (date) => {
const isValidDate = (0, verifyDate_1.verifyDate)(props.format, date, props.minDate, maxDate, props.dateSeparator, props.hasRange, today);
const datesFormatted = [
transformDate(date.split(' ')[0], props.format),
transformDate(date.split(' ')[1], props.format),
];
return isValidDate
? [...datesFormatted].sort((a, b) => new Date(a).getTime() - new Date(b).getTime())
: date;
};
// used when selecting date in calendar or transforming dates in internal validation
// updates date and dateFormatted states
// set the showcalendar state to false
const handleChangeDate = (newDate, hasError = false) => {
if (!hasError) {
if (props.hasRange && newDate.length === 2) {
props.onSelectedDateChange?.(buildRangeDates([newDate[0], newDate[1]]));
setDateFormatted(newDate);
if (newDate[1]) {
setCalendarOpen(false);
}
}
else {
props.onSelectedDateChange?.(newDate[0]);
setDateFormatted([newDate[0]]);
setCalendarOpen(false);
}
props.onCalendarOpen?.(false);
}
onError?.(hasError);
};
// validate formatted dates when date range
const handleChangeInternalValidateDateRange = (dateRange) => {
const isValidDateRange = (0, verifyDate_1.verifyDate)(props.format, dateRange, props.minDate, maxDate, props.dateSeparator, true, today);
// Regex to split dates with dateSeparator ("to")
const regexSplit = /[\sA-Za-z]+/;
const dateRangeFormatted = dateRange.split(regexSplit);
if (dateRangeFormatted && dateRangeFormatted?.length >= 2) {
if (isValidDateRange) {
removeInternalError(internalErrors_1.InternalErrorType.INVALID_DATE_RANGE);
}
else {
addInternalError(internalErrors_1.InternalErrorType.INVALID_DATE_RANGE);
}
}
handleChangeDate([
transformDate(dateRangeFormatted[0], props.format),
transformDate(dateRangeFormatted[1], props.format),
], !isValidDateRange);
};
// validate formatted dates when single date
const handleChangeInternalValidateSingleDate = (date) => {
const isValidDate = (0, verifyDate_1.verifyDate)(props.format, date, props.minDate, maxDate, props.dateSeparator, props.hasRange, today);
if (isValidDate) {
removeInternalError(internalErrors_1.InternalErrorType.INVALID_DATE);
}
else {
addInternalError(internalErrors_1.InternalErrorType.INVALID_DATE);
}
handleChangeDate([transformDate(date, props.format)], !isValidDate);
};
const createDateFormatted = (initialDate, initialSecondDate) => {
if (initialDate) {
if (initialSecondDate) {
return [initialDate, initialSecondDate];
}
return [initialDate];
}
return [];
};
// states, constants and refs
const [calendarOpen, setCalendarOpen] = (0, react_1.useState)(false);
const [dateFormatted, setDateFormatted] = (0, react_1.useState)(createDateFormatted(props.initialDate, props.initialSecondDate));
const firstRender = (0, react_1.useRef)(true);
const { transformDate, formatDate } = (0, provider_1.useUtilsProvider)();
const { internalErrors, addInternalError, removeInternalError } = (0, useInternalValidations_1.useInternalValidations)(type, undefined, onInternalErrors);
// Methods
// Popover control calendar
const handleOpenCalendar = (open) => {
setCalendarOpen(open);
props.onCalendarOpen?.(open);
};
const handleClickInput = event => {
if (calendarOpen) {
setCalendarOpen(false);
props.onCalendarOpen?.(false);
}
props.onClick?.(event);
};
const onBlurDate = event => {
if (event.currentTarget.contains(event.relatedTarget)) {
return;
}
const inputValue = inputRef?.current?.value ?? '';
if (errorExecution === input_1.ERROR_EXECUTION.ON_BLUR) {
if (props.hasRange) {
handleChangeInternalValidateDateRange(inputValue);
}
else {
handleChangeInternalValidateSingleDate(inputValue);
}
}
const hasError = internalErrors.length > 0;
props.onDateError?.(hasError);
let adaptEvent;
const dateValue = inputValue;
if (props.hasRange) {
const hasSeparator = props.dateSeparator && dateValue.includes(props.dateSeparator);
const secondDateExists = dateValue.length > props.format.length;
const dates = hasSeparator
? dateValue.split(props.dateSeparator)
: dateValue.split(' ');
const firstDate = (0, formatDateToNative_1.formatDateToNative)(dates[0].trim(), props.format, true);
const secondDate = secondDateExists
? (0, formatDateToNative_1.formatDateToNative)(dates[1].trim(), props.format, true)
: '';
const firstValueAsNumber = firstDate.length && (0, formatDate_1.formatDateToUTC)(firstDate).getTime();
const secondValueAsNumber = secondDate.length && (0, formatDate_1.formatDateToUTC)(secondDate).getTime();
const firstValueAsDate = firstDate.length && (0, formatDate_1.formatDateToUTC)(firstDate);
const secondValueAsDate = secondDate.length && (0, formatDate_1.formatDateToUTC)(secondDate);
adaptEvent = {
target: {
value: `${firstDate} ${secondDate}`,
valueAsNumber: `${firstValueAsNumber} ${secondValueAsNumber}`.trim(),
valueAsDate: `${firstValueAsDate} - ${secondValueAsDate}`,
},
};
}
else {
adaptEvent = setDate(dateValue, props.format);
}
onWrapperBlur?.(adaptEvent);
};
// validate formatted dates
const handleChangeInternalValidate = event => {
const dateValue = event?.target?.value;
// reset the internal errors for new verify
if (internalErrors.includes(internalErrors_1.InternalErrorType.INVALID_DATE)) {
removeInternalError(internalErrors_1.InternalErrorType.INVALID_DATE);
}
else if (internalErrors.includes(internalErrors_1.InternalErrorType.INVALID_DATE_RANGE)) {
removeInternalError(internalErrors_1.InternalErrorType.INVALID_DATE_RANGE);
}
// date range
if (dateValue?.length === props.format?.length * 2 + 1) {
if (errorExecution === input_1.ERROR_EXECUTION.ON_CHANGE) {
handleChangeInternalValidateDateRange(dateValue);
}
const orderedRangeDates = orderStringDates(dateValue);
// if the first date is invalid give an error
const hasError = internalErrors.length > 0;
// add ordered dates in ref value
if (inputRef?.current) {
inputRef.current.value =
!hasError && typeof orderedRangeDates !== 'string'
? `${formatDate(orderedRangeDates[0], props.format)} ${formatDate(orderedRangeDates[1], props.format)}`
: dateValue;
}
// add date separator in ref value
inputRef?.current?.setRangeText(` ${props.dateSeparator}`, props.format.length, props.format.length, 'end');
// single date
}
else if (dateValue?.length === props.format?.length &&
errorExecution === input_1.ERROR_EXECUTION.ON_CHANGE) {
handleChangeInternalValidateSingleDate(dateValue);
}
let adaptEvent;
if (props.hasRange) {
const hasSeparator = props.dateSeparator && dateValue.includes(props.dateSeparator);
const secondDateExists = dateValue.length > props.format.length;
const dates = hasSeparator
? dateValue.split(props.dateSeparator)
: dateValue.split(' ');
const firstDate = (0, formatDateToNative_1.formatDateToNative)(dates[0].trim(), props.format, true);
const secondDate = secondDateExists
? (0, formatDateToNative_1.formatDateToNative)(dates[1].trim(), props.format, true)
: '';
const firstValueAsNumber = firstDate.length && (0, formatDate_1.formatDateToUTC)(firstDate).getTime();
const secondValueAsNumber = secondDate.length && (0, formatDate_1.formatDateToUTC)(secondDate).getTime();
const firstValueAsDate = firstDate.length && (0, formatDate_1.formatDateToUTC)(firstDate);
const secondValueAsDate = secondDate.length && (0, formatDate_1.formatDateToUTC)(secondDate);
adaptEvent = {
target: {
value: `${firstDate} ${secondDate}`,
valueAsNumber: `${firstValueAsNumber} ${secondValueAsNumber}`.trim(),
valueAsDate: `${firstValueAsDate} - ${secondValueAsDate}`,
},
};
}
else {
adaptEvent = setDate(dateValue, props.format);
}
onChange?.(adaptEvent);
};
const handlePickCalendarDate = (newPickDate) => {
// clean errors setted by internal validation, when date is selected from calendar
if (internalErrors.includes(internalErrors_1.InternalErrorType.INVALID_DATE)) {
removeInternalError(internalErrors_1.InternalErrorType.INVALID_DATE);
}
else if (internalErrors.includes(internalErrors_1.InternalErrorType.INVALID_DATE_RANGE)) {
removeInternalError(internalErrors_1.InternalErrorType.INVALID_DATE_RANGE);
}
const orderedDates = [...newPickDate].sort((a, b) => new Date(a).getTime() - new Date(b).getTime());
const formattedDates = orderedDates.map(date => formatDate(date, props.format));
const hasSecondaDate = formattedDates.length === 2;
const dateValue = hasSecondaDate ? formattedDates.join(' ') : formattedDates[0];
handleChangeDate(newPickDate);
if (props.hasRange) {
handleSetValue(`${getDate(orderedDates[0])} ${getDate(orderedDates[1])}`);
}
else if (dateValue?.length === props.format?.length) {
if (inputRef?.current) {
// Inner input value should be set before the rerendering
// This avoid calling onChange event when input.value is different from the current value when picking a date
inputRef.current.value = dateValue;
// When selecting a date from the calendar, set the cursor to the end of the input
eventKeyPressRef.current = {
key: '',
cursor: {
start: dateValue.length,
end: dateValue.length,
},
};
}
handleSetValue(dateValue);
}
let adaptEvent;
if (hasSecondaDate) {
const firstNativeDate = (0, formatDateToNative_1.formatDateToNative)(getDate(orderedDates[0]), props.format, true);
const secondNativeDate = (0, formatDateToNative_1.formatDateToNative)(getDate(orderedDates[1]), props.format, true);
const firstValueAsNumber = (0, formatDate_1.formatDateToUTC)(orderedDates[0]).getTime();
const secondValueAsNumber = (0, formatDate_1.formatDateToUTC)(orderedDates[1]).getTime();
adaptEvent = {
target: {
value: `${firstNativeDate} ${secondNativeDate}`,
valueAsNumber: `${firstValueAsNumber} ${secondValueAsNumber}`,
valueAsDate: `${orderedDates[0]} - ${orderedDates[1]}`,
},
};
}
else {
const dateSelected = getDate(orderedDates[0]);
adaptEvent = setDate(dateSelected, props.format);
}
onChange?.(adaptEvent);
};
(0, react_1.useEffect)(() => {
// On close calendar input will recive focus automatically
// Also avoid focus when rendering the component
if (!calendarOpen && !firstRender.current) {
inputRef?.current?.focus();
}
firstRender.current = false;
}, [calendarOpen]);
const { value, state, eventKeyPressRef, inputRef, handleChangeInternal, handleBlurInternal, handleFocusInternal, handleKeyDownInternal, handleSetValue, handlePasteInternal, } = (0, useInput_1.useInput)({
ref,
keyValidation,
internalErrorExecution,
max,
min,
maxLength,
minLength,
mask,
maskType,
disabled,
error: error || internalErrors.length > 0,
currentValue,
type,
truncate,
informationAssociated,
disabledCopyAndPaste,
onBlur,
onFocus,
onKeyDown,
onError,
onInternalErrors,
onChange: handleChangeInternalValidate,
onPaste,
});
// update initial dates when they have value
(0, react_1.useEffect)(() => {
setDateFormatted(createDateFormatted(props.initialDate && (0, formatDate_1.formatDateToUTC)(props.initialDate), props.initialSecondDate && (0, formatDate_1.formatDateToUTC)(props.initialSecondDate)));
if (props.hasRange) {
const newValue = props.initialDate || props.initialSecondDate
? `${getDate(props.initialDate)} ${props.dateSeparator} ${getDate(props.initialSecondDate)}`
: '';
handleSetValue(newValue);
}
else {
handleSetValue(getDate(props.initialDate));
}
}, [props.initialDate, props.initialSecondDate]);
(0, react_1.useEffect)(() => {
if (String(value).length === props.format?.length * 2 + 1) {
// to set date separator when date is selected from calendar
inputRef?.current?.setRangeText(` ${props.dateSeparator}`, props.format.length, props.format.length, 'end');
if (inputRef?.current) {
handleSetValue(inputRef?.current?.value);
}
}
//Set "Today, " when today date is selected or typed on single date
if (String(value) === formatDate(new Date(), props.format) &&
String(value)?.length === props.format?.length &&
!props.hasRange) {
handleSetValue(`${today}${value}`);
}
}, [value]);
return {
dateFormatted,
calendarOpen,
handleClickInput,
handlePickCalendarDate,
handleOpenCalendar,
handleChangeInternalValidate,
value,
state,
inputRef,
handleChangeInternal,
handleBlurInternal,
handleWrapperBlur: onBlurDate,
handleFocusInternal,
handleKeyDownInternal,
handleSetValue,
handlePasteInternal,
};
};
exports.useInputDate = useInputDate;
//# sourceMappingURL=useInputDate.js.map