function TextField()

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>
      )}
    </>
  );
}