# All files / src/Input Input.tsx

100% Statements 29/29
100% Branches 14/14
100% Functions 5/5
100% Lines 29/29

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
    1012x
    2x
    2x
    2x

    2x

    2x
    2x

    2x

    2x

    2x

    7x
    7x

    7x
    7x
    7x
    7x
    1x

    3x

    1x
    1x
    1x

    7x
    7x

    7x

    7x

    7x

    2x

    2x

    2x
     import * as React from 'react'
    import classNames from 'classnames'
    import { createUseStyles } from '@fluent-ui/styles'
    import { styles } from './Input.styled'
    import { Theme } from '../styles'
    import { InputClassProps, InputProps, InputPropTypes } from './Input.type'

    import { ChromeClose as ChromeCloseIcon } from '@fluent-ui/icons'
    import Transition from '../Transition'

    export const name = 'Input'

    const useStyles = createUseStyles<Theme, InputClassProps>(styles, { name })

    const Input: React.FC<InputProps> = React.forwardRef<HTMLInputElement, InputProps>(
      (props, ref): React.ReactElement => {
        const {
          className: classNameProp,
          style,
          value,
          onChange,
          placeholder,
          disabled,
          cleared,
          password,
          error,
          ...rest
        } = props

        const clearedRef = React.useRef<HTMLSpanElement>(null)
        const [clearedHeight, setClearedHeight] = React.useState(0)
        React.useEffect((): void => {
          if (clearedRef && clearedRef.current) {
            setClearedHeight(clearedRef.current.offsetHeight)
          }
        }, [])
        function handleChange(e: React.ChangeEvent<HTMLInputElement> | null): void {
          onChange && onChange(e ? e.target.value : '')
        }
        function handleClear(e: React.MouseEvent<HTMLElement>): void {
          e.preventDefault()
          e.stopPropagation()
          handleChange(null)
        }

        const classes = useStyles(props)
        const className = classNames(
          classes.root,
          {
            [classes.error]: error
          },
          classNameProp
        )
        const clearedInputStyle = React.useMemo(
          (): object =>
            cleared
              ? {
                  paddingRight: clearedHeight
                }
              : {},
          [cleared, clearedHeight]
        )

        return (
          <div className={classes.wrapper} style={style}>
            <input
              className={className}
              ref={ref}
              value={value}
              onChange={handleChange}
              placeholder={placeholder}
              disabled={disabled}
              type={password ? 'password' : 'text'}
              style={clearedInputStyle}
              {...rest}
            />
            {cleared && (
              <Transition visible={!!value} wrapper={false}>
                <span
                  className={classes.clearedIcon}
                  onClick={handleClear}
                  ref={clearedRef}
                  style={{
                    width: clearedHeight
                  }}
                >
                  <ChromeCloseIcon />
                </span>
              </Transition>
            )}
          </div>
        )
      }
    )

    Input.displayName = `F${name}`

    Input.propTypes = InputPropTypes

    export default Input