@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
257 lines • 7.48 kB
JavaScript
import { useCallback, useMemo } from 'react';
import { pickSpacingProps } from "../../../../components/flex/utils.js";
import { useFieldProps } from "../../hooks/index.js";
import { clsx } from 'clsx';
import FieldBlock from "../../FieldBlock/index.js";
import SegmentedField from "../../../../components/input-masked/segmented-field/SegmentedField.js";
import useTranslation from "../../hooks/useTranslation.js";
import { FormError } from "../../utils/index.js";
import { jsx as _jsx } from "react/jsx-runtime";
function Time(props = {}) {
var _useTranslation$Time;
const {
label: timeLabel,
errorRequired,
hoursPlaceholder,
minutesPlaceholder,
secondsPlaceholder,
hours: hoursLabel,
minutes: minutesLabel,
seconds: secondsLabel
} = (_useTranslation$Time = useTranslation().Time) !== null && _useTranslation$Time !== void 0 ? _useTranslation$Time : {};
const {
showSeconds
} = props;
const timeValidator = useCallback(value => validateTime(value, showSeconds), [showSeconds]);
const {
onBlurValidator = timeValidator,
onChangeValidator,
errorMessages: propErrorMessages,
validateInitially: validateInitiallyProp,
validateContinuously,
value: valueProp,
transformIn: transformInProp,
onStatusChange
} = props;
const errorMessages = useMemo(() => ({
'Field.errorRequired': errorRequired,
...propErrorMessages
}), [errorRequired, propErrorMessages]);
const fromInput = useCallback(values => {
const {
hours,
minutes,
seconds
} = values;
if (!hours && !minutes && (!showSeconds || !seconds)) {
return undefined;
}
return showSeconds ? `${hours}:${minutes}:${seconds}` : `${hours}:${minutes}`;
}, [showSeconds]);
const validateRequired = useCallback((value, {
required,
error
}) => {
return required && !value ? error : undefined;
}, []);
const validateInitially = useMemo(() => validateInitiallyProp || (valueProp ? true : undefined), [validateInitiallyProp, valueProp]);
const fromExternal = useCallback(external => {
if (typeof external !== 'string') {
return external;
}
const {
hours,
minutes,
seconds
} = stringToTimeValue(external);
if (!hours && !minutes) {
return undefined;
}
return seconds ? `${hours}:${minutes}:${seconds}` : `${hours}:${minutes}`;
}, []);
const transformIn = useCallback(value => {
if (!transformInProp) {
return value;
}
const external = transformInProp(value);
if (typeof external === 'string') {
return external;
}
if (!external?.hours && !external?.minutes && !external?.seconds) {
return value;
}
const hours = external.hours;
const minutes = external.minutes;
if (!hours && !minutes) {
return undefined;
}
const seconds = external.seconds;
return seconds ? `${hours}:${minutes}:${seconds}` : `${hours}:${minutes}`;
}, [transformInProp]);
const provideAdditionalArgs = useCallback(value => {
const {
hours,
minutes,
seconds
} = stringToTimeValue(value);
return {
hours: hours || undefined,
minutes: minutes || undefined,
...(showSeconds && {
seconds: seconds || undefined
})
};
}, [showSeconds]);
const preparedProps = {
...props,
errorMessages,
validateInitially,
validateContinuously,
fromExternal,
transformIn,
fromInput,
provideAdditionalArgs,
validateRequired,
onBlurValidator: onBlurValidator,
onChangeValidator,
onStatusChange,
exportValidators: {
timeValidator
}
};
const {
id,
path,
itemPath,
className,
label = timeLabel,
hasError,
info,
warning,
disabled,
size,
value = '',
htmlAttributes,
handleFocus,
handleBlur,
handleChange,
setDisplayValue
} = useFieldProps(preparedProps);
const time = useMemo(() => {
const {
hours,
minutes,
seconds
} = stringToTimeValue(value);
return {
hours: hours || '',
minutes: minutes || '',
seconds: showSeconds && seconds || ''
};
}, [value, showSeconds]);
useMemo(() => {
if ((path || itemPath) && time.hours && time.minutes) {
setDisplayValue(time.seconds ? `${time.hours}:${time.minutes}:${time.seconds}` : `${time.hours}:${time.minutes}`);
}
}, [time.hours, time.minutes, time.seconds, itemPath, path, setDisplayValue]);
const status = hasError ? 'error' : warning ? 'warning' : info ? 'information' : null;
const fieldBlockProps = {
id,
forId: `${id}-input`,
className: clsx('dnb-forms-field-time', className),
label,
...pickSpacingProps(props)
};
return _jsx(FieldBlock, {
...fieldBlockProps,
children: _jsx(SegmentedField, {
stretch: true,
id: `${id}-input`,
values: time,
status: status === 'error',
disabled: disabled,
size: size,
onChange: handleChange,
onBlur: handleBlur,
onFocus: handleFocus,
delimiter: ":",
inputMode: "numeric",
inputs: [{
id: 'hours',
label: hoursLabel,
mask: [/[0-9]/, /[0-9]/],
spinButton: {
min: 0,
max: 24,
getInitialValue: () => new Date().getHours()
},
placeholder: hoursPlaceholder?.repeat(2),
...htmlAttributes
}, {
id: 'minutes',
label: minutesLabel,
mask: [/[0-9]/, /[0-9]/],
spinButton: {
min: 0,
max: 59,
getInitialValue: () => new Date().getMinutes()
},
placeholder: minutesPlaceholder?.repeat(2),
...htmlAttributes
}, ...(showSeconds ? [{
id: 'seconds',
label: secondsLabel,
mask: [/[0-9]/, /[0-9]/],
spinButton: {
min: 0,
max: 59,
getInitialValue: () => new Date().getSeconds()
},
placeholder: secondsPlaceholder?.repeat(2),
...htmlAttributes
}] : [])]
})
});
}
function stringToTimeValue(value) {
if (typeof value !== 'string' || !value.includes(':')) {
return {
hours: undefined,
minutes: undefined,
seconds: undefined
};
}
const [hours, minutes, seconds] = value.split(':');
return {
hours,
minutes,
seconds
};
}
function validateTime(time, showSeconds) {
if (!time || !time.includes(':')) {
return undefined;
}
const {
hours,
minutes,
seconds
} = stringToTimeValue(time);
if (!hours && !minutes && (!showSeconds || !seconds)) {
return [];
}
const hoursNumber = Number(hours);
const minutesNumber = Number(minutes);
const secondsNumber = Number(seconds);
const hoursInvalid = !hours || hours.length !== 2 || isNaN(hoursNumber) || hoursNumber < 0 || hoursNumber > 24;
const minutesInvalid = !minutes || minutes.length !== 2 || isNaN(minutesNumber) || minutesNumber < 0 || minutesNumber > 59;
const secondsInvalid = showSeconds && (!seconds || seconds.length !== 2 || isNaN(secondsNumber) || secondsNumber < 0 || secondsNumber > 59);
const is24WithNonZero = hoursNumber === 24 && (minutesNumber !== 0 || showSeconds && secondsNumber !== 0);
if (hoursInvalid || minutesInvalid || secondsInvalid || is24WithNonZero) {
return new FormError('Time.errorInvalidTime');
}
return undefined;
}
Time._supportsEufemiaSpacingProps = true;
export default Time;
//# sourceMappingURL=Time.js.map