File size: 2,429 Bytes
77fd7a1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React, { useState } from "react";
import styles from "./InputField.module.css";

interface InputFieldProps {
  label: string;
  value: string;
  width?: string;
  type?: string;
  icon?: React.ComponentType<any>;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  onIconMouseDown?: (
    event: React.MouseEvent<SVGSVGElement, MouseEvent>,
  ) => void;
  onFocus?: React.FocusEventHandler<HTMLInputElement>;
  onBlur?: React.FocusEventHandler<HTMLInputElement>;
  children?: React.ReactNode;
  onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
  inputRef?: React.Ref<HTMLInputElement>;
  autoComplete?: string;
}

function BaseInputField(props: Readonly<InputFieldProps>) {
  const {
    label,
    value,
    width = "325px",
    type = "text",
    icon: IconComponent,
    onIconMouseDown,
    onChange,
    onFocus,
    onBlur,
    children,
    inputRef,
    onKeyDown,
    autoComplete,
  } = props;

  const inlineStyles: React.CSSProperties = {
    width: width,
  };

  const [isInternalFocused, setIsInternalFocused] = useState<boolean>(false);

  function handleFocus(event: React.FocusEvent<HTMLInputElement>): void {
    setIsInternalFocused(true);
    if (onFocus) {
      onFocus(event);
    }
  }

  function handleBlur(event: React.FocusEvent<HTMLInputElement>): void {
    setIsInternalFocused(false);
    if (onBlur) {
      onBlur(event);
    }
  }

  const shouldFloat = isInternalFocused || value !== "";

  return (
    <div className={styles.inputContainer} style={inlineStyles}>
      <input
        type={type}
        className={styles.inputField}
        value={value}
        onChange={onChange}
        onFocus={handleFocus}
        onBlur={handleBlur}
        ref={inputRef}
        onKeyDown={onKeyDown}
        autoComplete={autoComplete}
      />

      <label
        className={`${styles.inputLabel} ${shouldFloat ? styles.inputLabelFloating : ""}`}
      >
        {label}
      </label>

      {children ? (
        <div
          className={`${styles.inputFieldIcon} ${shouldFloat ? styles.inputFieldIconFloating : ""}`}
        >
          {children}
        </div>
      ) : (
        IconComponent && (
          <IconComponent
            className={`${styles.inputFieldIcon} ${shouldFloat ? styles.inputFieldIconFloating : ""}`}
            onMouseDown={onIconMouseDown}
          />
        )
      )}
    </div>
  );
}

export default BaseInputField;