in packages/uniforms-patternfly/src/TextField.tsx [41:189]
function TextField({ onChange, helperText, ...props }: TextFieldProps) {
const isDateInvalid = useMemo(() => {
if (typeof props.value !== "string") {
return false;
}
if (props.type !== "date" && props.field?.format !== "date") {
return false;
}
const date = new Date(props.value);
if (typeof props.min === "string") {
const minDate = new Date(props.min);
if (minDate.toString() === "Invalid Date") {
return false;
} else if (date.toISOString() < minDate.toISOString()) {
return props.errorMessage && props.errorMessage.trim().length > 0
? props.errorMessage
: `Should be after ${props.min}`;
}
}
if (typeof props.max === "string") {
const maxDate = new Date(props.max);
if (maxDate.toString() === "Invalid Date") {
return false;
} else if (date.toISOString() > maxDate.toISOString()) {
return props.errorMessage && props.errorMessage.trim().length > 0
? props.errorMessage
: `Should be before ${props.max}`;
}
}
return false;
}, [props.value, props.max, props.min, props.errorMessage, props.type, props.field]);
const parseTime = useCallback((time: string) => {
const parsedTime = timeRgx.exec(time);
const date = new Date();
if (!parsedTime) {
return undefined;
}
date.setUTCHours(Number(parsedTime[1]), Number(parsedTime[2]!));
return date;
}, []);
const isTimeInvalid = useMemo(() => {
if (typeof props.value !== "string") {
return false;
}
if (props.type !== "time" && props.field?.format !== "time") {
return false;
}
const parsedTime = parseTime(props.value ?? "");
if (parsedTime && typeof props.min === "string" && timeRgx.exec(props.min)) {
const parsedMin = parseTime(props.min)!;
if (parsedTime < parsedMin) {
if (parsedMin.getUTCMinutes() < 10) {
return `Should be after ${parsedMin.getUTCHours()}:0${parsedMin.getUTCMinutes()}`;
}
return `Should be after ${parsedMin.getUTCHours()}:${parsedMin.getUTCMinutes()}`;
}
}
if (parsedTime && typeof props.max === "string" && timeRgx.exec(props.max)) {
const parsedMax = parseTime(props.max)!;
if (parsedTime > parsedMax) {
if (parsedMax.getUTCMinutes() < 10) {
return `Should be before ${parsedMax.getUTCHours()}:0${parsedMax.getUTCMinutes()}`;
}
return `Should be before ${parsedMax.getUTCHours()}:${parsedMax.getUTCMinutes()}`;
}
}
}, [props.type, props.field, props.value, props.max, props.min, parseTime]);
const fieldType = useMemo(() => {
if (props.field?.format === "date" || props.type === "date") {
return "date";
}
if (props.field?.format === "time" || props.type === "time") {
return "time";
}
return "text";
}, [props.field?.format, props.type]);
const onTextInputChange = useCallback(
(event, value) => {
if (fieldType !== "time" || value === "") {
onChange((event.target as any)?.value);
return;
}
// Time handler: Add seconds to be a valid time
onChange(`${value}:00`);
},
[fieldType, onChange]
);
const value = useMemo(() => {
if (fieldType === "time" && props.value !== "") {
const splitedTime = props.value?.split(":");
if ((splitedTime?.length ?? 0) > 2) {
return splitedTime?.slice(0, 2)?.join(":");
}
}
return props.value ?? "";
}, [fieldType, props.value]);
return wrapField(
{ ...props, help: helperText },
<>
<TextInput
aria-label={"uniforms text field"}
data-testid={"text-field"}
name={props.name}
isDisabled={props.disabled}
validated={props.error ? "error" : "default"}
onChange={onTextInputChange}
placeholder={props.placeholder}
ref={props.inputRef}
type={fieldType}
value={value}
{...filterDOMProps(props)}
/>
{fieldType === "time" && isTimeInvalid && (
<div
style={{
fontSize: "0.875rem",
color: "#c9190b",
marginTop: "0.25rem",
}}
>
{isTimeInvalid}
</div>
)}
{fieldType === "date" && isDateInvalid && (
<div
style={{
fontSize: "0.875rem",
color: "#c9190b",
marginTop: "0.25rem",
}}
>
{isDateInvalid}
</div>
)}
</>
);
}