All files / src/input Input.tsx

90% Statements 9/10
78.57% Branches 11/14
50% Functions 1/2
90% Lines 9/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141                                                                                                                                                    22x         73x                             73x     73x 73x           73x   73x                         73x                                       22x  
import React from "react";
import classNames from "classnames";
import { Combine, StyledProps, Omit } from "../_type";
import { ControlledProps, useDefaultValue } from "../form/controlled";
import { forwardRefWithStatics } from "../_util/forward-ref-with-statics";
import { useConfig } from "../_util/config-context";
 
export type SizeType = "full" | "l" | "m" | "s" | "xs";
 
type InputElements = HTMLInputElement | HTMLTextAreaElement;
 
/**
 * Input 组件支持的属性。
 *
 * 除表格中列出的属性外,支持透传原生 `<input>` 或 `<textarea>` 标签支持的属性。
 */
export interface InputProps
  extends Combine<
    StyledProps,
    ControlledProps<string>,
    Omit<
      React.InputHTMLAttributes<HTMLInputElement> &
        React.TextareaHTMLAttributes<HTMLTextAreaElement>,
      "onChange" | "size"
    >
  > {
  /**
   * 是否多行输入
   */
  multiline?: boolean;
 
  /**
   * Input 组件不应该传入 children
   */
  children?: never;
 
  /**
   * 占位符
   */
  placeholder?: string;
 
  /**
   * 是否禁用
   * @default false
   */
  disabled?: boolean;
 
  /**
   * 是否为只读模式
   * @default false
   */
  readonly?: boolean;
 
  /**
   * 最大输入长度
   */
  maxLength?: number;
 
  /**
   * 原生 `<input>` 标签 `type` 属性
   */
  type?: React.InputHTMLAttributes<HTMLInputElement>["type"];
 
  /**
   * 输入框尺寸,使用 `full` 撑满容器宽度
   */
  size?: SizeType;
 
  /**
   * 改变 Input 的基本样式类名,不建议使用
   */
  baseClassName?: string;
}
 
export const Input = forwardRefWithStatics(
  (
    props: InputProps,
    ref: React.Ref<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    const { classPrefix } = useConfig();
    const {
      multiline,
      children, // never used
      placeholder,
      disabled,
      readonly,
      size,
      type,
      baseClassName,
      className,
      style,
      value,
      onChange,
      ...restProps
    } = useDefaultValue(props, "");
 
    const basename =
      baseClassName || `${classPrefix}-${multiline ? "textarea" : "input"}`;
    const inputClassName = classNames({
      [basename]: true,
      [className]: className,
      [`size-${size === "full" ? `${size}-width` : size}`]: size,
    });
 
    const hasRows = multiline && restProps.rows;
 
    const inputProps = {
      placeholder,
      className: inputClassName,
      readOnly: readonly,
      disabled,
      // 受样式限制 rows 属性没有生效
      style: hasRows ? { height: "auto", ...(style || {}) } : style,
      value,
      onChange: (event: React.ChangeEvent<InputElements>) =>
        onChange(event.target.value, { event }),
      ...restProps,
    };
 
    return multiline ? (
      <textarea ref={ref as React.Ref<HTMLTextAreaElement>} {...inputProps} />
    ) : (
      <input
        ref={ref as React.Ref<HTMLInputElement>}
        type={type}
        {...inputProps}
      />
    );
  },
  {
    // Input statics
 
    /**
     * 在表单布局中,和 label 的默认对齐方式
     */
    defaultLabelAlign: "middle",
  }
);
 
Input.displayName = "Input";