UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

368 lines (367 loc) 11.9 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "DEFAULT_DATE_FORMAT", { enumerable: true, get: function () { return _validators.DEFAULT_DATE_FORMAT; } }); exports.default = void 0; var _react = require("react"); var _index = _interopRequireDefault(require("../String/index.js")); var _index2 = _interopRequireDefault(require("../Composition/index.js")); var _index3 = _interopRequireDefault(require("../Selection/index.js")); var _Context = _interopRequireDefault(require("../../../../shared/Context.js")); var _validators = require("./validators.js"); var _useTranslation = _interopRequireDefault(require("../../hooks/useTranslation.js")); var _DateFormatUtils = require("../../../../components/date-format/DateFormatUtils.js"); var _index4 = require("../../hooks/index.js"); var _useIterateItemNo = require("../../Iterate/ItemNo/useIterateItemNo.js"); var _withComponentMarkers = _interopRequireDefault(require("../../../../shared/helpers/withComponentMarkers.js")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function DateOfBirth(props) { const [, forceUpdate] = (0, _react.useReducer)(() => ({}), {}); const { errorDateOfBirth, errorDateOfBirthFuture, errorRequired, label, dayLabel, monthLabel, yearLabel, dayPlaceholder, monthPlaceholder, yearPlaceholder } = (0, _useTranslation.default)().DateOfBirth; const { locale } = (0, _react.useContext)(_Context.default); const { dateFormat = _validators.DEFAULT_DATE_FORMAT, labelSuffix, required } = props; const dayRef = (0, _react.useRef)(props?.emptyValue); const monthRef = (0, _react.useRef)(props?.emptyValue); const yearRef = (0, _react.useRef)(props?.emptyValue); const errorMessages = (0, _react.useMemo)(() => { return { 'Field.errorRequired': errorRequired, 'Field.errorPattern': errorDateOfBirth, ...props.errorMessages }; }, [errorDateOfBirth, errorRequired, props.errorMessages]); const provideAdditionalArgs = (0, _react.useCallback)(value => { const [year, month, day] = (0, _validators.splitValue)(value, dateFormat); if (year && month && day) { return { year, month, day }; } return undefined; }, [dateFormat]); const dateOfBirthValidator = (0, _react.useCallback)(value => (0, _validators.validateDateOfBirth)(value, { dateFormat, errorDateOfBirth, errorDateOfBirthFuture }), [errorDateOfBirth, errorDateOfBirthFuture, dateFormat]); const { onBlurValidator: propOnBlurValidator, onChangeValidator, value: propValue, space, ...otherProps } = props; const onBlurValidator = (0, _react.useMemo)(() => { if (propOnBlurValidator === false) { return undefined; } if (typeof propOnBlurValidator === 'function') { return (value, args) => { const coreResult = dateOfBirthValidator(value); if (coreResult instanceof Error) { return coreResult; } return propOnBlurValidator(value, args); }; } return dateOfBirthValidator; }, [propOnBlurValidator, dateOfBirthValidator]); const preparedProps = (0, _react.useMemo)(() => ({ ...otherProps, value: propValue, errorMessages, onBlurValidator, onChangeValidator, exportValidators: { dateOfBirthValidator }, provideAdditionalArgs }), [otherProps, propValue, errorMessages, onBlurValidator, onChangeValidator, dateOfBirthValidator, provideAdditionalArgs]); const { emptyValue, label: labelProp, width = 'large', help, labelSrOnly, labelSize, labelDescription, labelDescriptionInline, error, disabled, htmlAttributes, handleChange, onDayChange, onMonthChange, onYearChange, setHasFocus, value: fieldValue } = (0, _index4.useFieldProps)(preparedProps); const labelWithItemNo = (0, _useIterateItemNo.useIterateItemNo)({ label: labelProp !== null && labelProp !== void 0 ? labelProp : label, labelSuffix, required }); const prepareEventValues = (0, _react.useCallback)(({ day = dayRef.current || emptyValue, month = monthRef.current || emptyValue, year = yearRef.current || emptyValue } = {}) => { return { year, month, day }; }, [emptyValue]); const callOnChange = (0, _react.useCallback)(data => { const eventValues = prepareEventValues(data); handleChange(joinValue([eventValues.year, eventValues.month, eventValues.day], dateFormat), eventValues); }, [prepareEventValues, handleChange, dateFormat]); const callOnBlurOrFocus = (0, _react.useCallback)(hasFocus => { setHasFocus(hasFocus, undefined, prepareEventValues()); }, [prepareEventValues, setHasFocus]); (0, _react.useEffect)(() => { if (fieldValue) { const [year, month, day] = (0, _validators.splitValue)(fieldValue, dateFormat); const currentValues = joinValue([yearRef.current, monthRef.current, dayRef.current], dateFormat); const shouldUpdate = !dayRef.current && !monthRef.current && !yearRef.current || fieldValue !== currentValues; if (shouldUpdate) { dayRef.current = day; monthRef.current = month; yearRef.current = year; forceUpdate(); } } else { const currentValues = joinValue([yearRef.current, monthRef.current, dayRef.current], dateFormat); if (currentValues) { dayRef.current = emptyValue; monthRef.current = emptyValue; yearRef.current = emptyValue; forceUpdate(); } } }, [fieldValue, dateFormat, emptyValue]); const handleDayChange = (0, _react.useCallback)(value => { const day = dayRef.current = value || emptyValue; forceUpdate(); callOnChange({ day, month: monthRef.current, year: yearRef.current }); onDayChange?.(day); }, [emptyValue, callOnChange, onDayChange]); const handleMonthChange = (0, _react.useCallback)(value => { const month = monthRef.current = value || emptyValue; forceUpdate(); callOnChange({ day: dayRef.current, month, year: yearRef.current }); onMonthChange?.(month); }, [emptyValue, callOnChange, onMonthChange]); const handleYearChange = (0, _react.useCallback)(value => { const year = yearRef.current = value || emptyValue; forceUpdate(); callOnChange({ day: dayRef.current, month: monthRef.current, year }); onYearChange?.(year); }, [emptyValue, callOnChange, onYearChange]); const normalizeDay = (0, _react.useCallback)(value => { if (!value) { return value; } const trimmed = value.trim(); if (/^[1-9]$/.test(trimmed)) { return trimmed.padStart(2, '0'); } return trimmed; }, []); const normalizeYear = (0, _react.useCallback)(value => { if (!value) { return value; } const trimmed = value.trim(); if (/^\d{1,2}$/.test(trimmed)) { const padded = trimmed.padStart(2, '0'); const currentYear = new Date().getFullYear(); const currentCentury = Math.floor(currentYear / 100) * 100; let normalized = currentCentury + parseInt(padded, 10); if (normalized > currentYear) { normalized -= 100; } return String(normalized); } return trimmed; }, []); const handleOnBlur = (0, _react.useCallback)(() => { callOnBlurOrFocus(false); }, [callOnBlurOrFocus]); const handleDayBlur = (0, _react.useCallback)(() => { const normalized = normalizeDay(dayRef.current); if (normalized && normalized !== dayRef.current) { handleDayChange(normalized); } handleOnBlur(); }, [handleDayChange, handleOnBlur, normalizeDay]); const handleYearBlur = (0, _react.useCallback)(() => { const normalized = normalizeYear(yearRef.current); if (normalized && normalized !== yearRef.current) { handleYearChange(normalized); } handleOnBlur(); }, [handleOnBlur, handleYearChange, normalizeYear]); const handleOnFocus = (0, _react.useCallback)(() => { callOnBlurOrFocus(true); }, [callOnBlurOrFocus]); const compositionFieldProps = { className: 'dnb-forms-field-date-of-birth', error, label: labelWithItemNo, labelSrOnly, labelSize, labelDescription, labelDescriptionInline, space }; const months = (0, _react.useMemo)(() => { return [...Array(12)].map((_, i) => { const nr = String(i + 1); const value = nr.padStart(2, '0'); const title = capitalizeFirstLetter((0, _DateFormatUtils.formatDate)(new Date(0, i, 1), { locale, options: { month: 'long' } })); return { value, title, searchContent: [title, nr, value] }; }); }, [locale]); const onBlurAutocomplete = (0, _react.useCallback)(event => { var _event$value; const nr = parseFloat((_event$value = event.value) !== null && _event$value !== void 0 ? _event$value : ''); if (!isNaN(nr)) { const monthValue = months.find(m => parseFloat(m.value) === nr)?.value; const month = monthValue || emptyValue; monthRef.current = month; forceUpdate(); callOnChange({ month }); } else { const monthValue = months.find(m => m.title === event.value)?.value; if (monthValue) { monthRef.current = monthValue; forceUpdate(); callOnChange({ month: monthValue }); } } }, [callOnChange, emptyValue, months]); return (0, _jsxRuntime.jsxs)(_index2.default, { width: width, help: help, ...compositionFieldProps, children: [(0, _jsxRuntime.jsx)(_index.default, { value: dayRef.current, autoComplete: "bday-day", labelDescription: dayLabel, labelSize: labelSize, width: "3.5rem", inputMode: "numeric", mask: [/[0-9]/, /[0-9]/], placeholder: dayPlaceholder, onChange: handleDayChange, onFocus: handleOnFocus, onBlur: handleDayBlur, disabled: disabled, htmlAttributes: htmlAttributes }), (0, _jsxRuntime.jsx)(_index3.default, { className: "dnb-forms-field-date-of-birth__month", value: monthRef.current, variant: "autocomplete", labelDescription: monthLabel, labelSize: labelSize, width: "10.75rem", placeholder: "", autocompleteProps: { openOnFocus: true, icon: '', placeholder: monthPlaceholder, autoComplete: 'bday-month', independentWidth: true, disableReorder: true, onBlur: onBlurAutocomplete }, data: months, onChange: handleMonthChange, onFocus: handleOnFocus, onBlur: handleOnBlur, disabled: disabled, htmlAttributes: htmlAttributes }), (0, _jsxRuntime.jsx)(_index.default, { value: yearRef.current, autoComplete: "bday-year", labelDescription: yearLabel, width: "stretch", inputMode: "numeric", mask: [/[0-9]/, /[0-9]/, /[0-9]/, /[0-9]/], placeholder: yearPlaceholder, onChange: handleYearChange, onFocus: handleOnFocus, onBlur: handleYearBlur, disabled: disabled, htmlAttributes: htmlAttributes })] }); } (0, _withComponentMarkers.default)(DateOfBirth, { _supportsSpacingProps: undefined }); var _default = exports.default = DateOfBirth; function capitalizeFirstLetter(s) { return s.charAt(0).toUpperCase() + s.slice(1); } function joinValue(array, dateFormat = _validators.DEFAULT_DATE_FORMAT) { const [year, month, day] = array; if (!year || !month || !day) { return undefined; } return dateFormat.replace('yyyy', year).replace('MM', month).replace('dd', day); } //# sourceMappingURL=DateOfBirth.js.map