pstream is dead; long live pstream
taciturnaxolotl.github.io/pstream-ng/
1import classNames from "classnames";
2import { forwardRef, useState } from "react";
3
4import { Icon, Icons } from "../Icon";
5
6export interface TextInputControlPropsNoLabel {
7 onChange?: (data: string) => void;
8 onUnFocus?: () => void;
9 onFocus?: () => void;
10 value?: string;
11 name?: string;
12 autoComplete?: string;
13 placeholder?: string;
14 className?: string;
15 passwordToggleable?: boolean;
16}
17
18export interface TextInputControlProps extends TextInputControlPropsNoLabel {
19 label?: string;
20}
21
22export const TextInputControl = forwardRef<
23 HTMLInputElement,
24 TextInputControlProps
25>(
26 (
27 {
28 onChange,
29 onUnFocus,
30 value,
31 label,
32 name,
33 autoComplete,
34 className,
35 placeholder,
36 onFocus,
37 passwordToggleable,
38 },
39 ref,
40 ) => {
41 let inputType = "text";
42 const [showPassword, setShowPassword] = useState(true);
43 if (passwordToggleable) inputType = showPassword ? "password" : "text";
44
45 const input = (
46 <div className="relative">
47 <input
48 type={inputType}
49 ref={ref}
50 className={classNames(className, passwordToggleable && "pr-12")}
51 placeholder={placeholder}
52 onChange={(e) => onChange && onChange(e.target.value)}
53 value={value}
54 name={name}
55 autoComplete={autoComplete}
56 onBlur={() => onUnFocus && onUnFocus()}
57 onFocus={() => onFocus?.()}
58 onKeyDown={(e) =>
59 e.key === "Enter" ? (e.target as HTMLInputElement).blur() : null
60 }
61 />
62 {passwordToggleable ? (
63 <button
64 type="button"
65 className="absolute top-1/2 -translate-y-1/2 right-1 text-xl p-3"
66 onClick={() => setShowPassword(!showPassword)}
67 >
68 <Icon icon={showPassword ? Icons.EYE : Icons.EYE_SLASH} />
69 </button>
70 ) : null}
71 </div>
72 );
73
74 if (label) {
75 return (
76 <label>
77 <span>{label}</span>
78 {input}
79 </label>
80 );
81 }
82
83 return input;
84 },
85);