aboutsummaryrefslogtreecommitdiffstats
path: root/packages/forms/src/input/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/forms/src/input/index.tsx')
-rw-r--r--packages/forms/src/input/index.tsx193
1 files changed, 193 insertions, 0 deletions
diff --git a/packages/forms/src/input/index.tsx b/packages/forms/src/input/index.tsx
new file mode 100644
index 000000000..478738cad
--- /dev/null
+++ b/packages/forms/src/input/index.tsx
@@ -0,0 +1,193 @@
1import { mdiEye, mdiEyeOff } from '@mdi/js';
2import Icon from '@mdi/react';
3import classnames from 'classnames';
4import React, { Component, createRef } from 'react';
5import injectSheet from 'react-jss';
6
7import { IFormField, IWithStyle } from '../typings/generic';
8
9import { Error } from '../error';
10import { Label } from '../label';
11import { Wrapper } from '../wrapper';
12import { scorePasswordFunc } from './scorePassword';
13
14import styles from './styles';
15
16interface IData {
17 [index: string]: string;
18}
19
20interface IProps extends React.InputHTMLAttributes<HTMLInputElement>, IFormField, IWithStyle {
21 focus?: boolean;
22 prefix?: string;
23 suffix?: string;
24 scorePassword?: boolean;
25 showPasswordToggle?: boolean;
26 data: IData;
27 inputClassName?: string;
28}
29
30interface IState {
31 showPassword: boolean;
32 passwordScore: number;
33}
34
35class InputComponent extends Component<IProps, IState> {
36 public static defaultProps = {
37 focus: false,
38 onChange: () => {},
39 onBlur: () => {},
40 onFocus: () => {},
41 scorePassword: false,
42 showLabel: true,
43 showPasswordToggle: false,
44 type: 'text',
45 disabled: false,
46 };
47
48 state = {
49 passwordScore: 0,
50 showPassword: false,
51 };
52
53 private inputRef = createRef<HTMLInputElement>();
54
55 componentDidMount() {
56 const { focus, data } = this.props;
57
58 if (this.inputRef && this.inputRef.current) {
59 if (focus) {
60 this.inputRef.current.focus();
61 }
62
63 if (data) {
64 Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]);
65 }
66 }
67 }
68
69 onChange(e: React.ChangeEvent<HTMLInputElement>) {
70 const {
71 scorePassword,
72 onChange,
73 } = this.props;
74
75 if (onChange) {
76 onChange(e);
77 }
78
79 if (this.inputRef && this.inputRef.current && scorePassword) {
80 this.setState({ passwordScore: scorePasswordFunc(this.inputRef.current.value) });
81 }
82 }
83
84 render() {
85 const {
86 classes,
87 className,
88 disabled,
89 error,
90 id,
91 inputClassName,
92 label,
93 prefix,
94 scorePassword,
95 suffix,
96 showLabel,
97 showPasswordToggle,
98 type,
99 value,
100 name,
101 placeholder,
102 spellCheck,
103 onBlur,
104 onFocus,
105 } = this.props;
106
107 const {
108 showPassword,
109 passwordScore,
110 } = this.state;
111
112 const inputType = type === 'password' && showPassword ? 'text' : type;
113
114 return (
115 <Wrapper
116 className={className}
117 identifier="franz-input"
118 >
119 <Label
120 title={label}
121 showLabel={showLabel}
122 htmlFor={id}
123 >
124 <div
125 className={classnames({
126 [`${inputClassName}`]: inputClassName,
127 [`${classes.hasPasswordScore}`]: scorePassword,
128 [`${classes.wrapper}`]: true,
129 [`${classes.disabled}`]: disabled,
130 [`${classes.hasError}`]: error,
131 })}>
132 {prefix && (
133 <span className={classes.prefix}>
134 {prefix}
135 </span>
136 )}
137 <input
138 id={id}
139 type={inputType}
140 name={name}
141 value={value as string}
142 placeholder={placeholder}
143 spellCheck={spellCheck}
144 className={classes.input}
145 ref={this.inputRef}
146 onChange={this.onChange.bind(this)}
147 onFocus={onFocus}
148 onBlur={onBlur}
149 disabled={disabled}
150 />
151 {suffix && (
152 <span className={classes.suffix}>
153 {suffix}
154 </span>
155 )}
156 {showPasswordToggle && (
157 <button
158 type="button"
159 className={classes.formModifier}
160 onClick={() => this.setState(prevState => ({ showPassword: !prevState.showPassword }))}
161 tabIndex={-1}
162 >
163 <Icon
164 path={!showPassword ? mdiEye : mdiEyeOff}
165 size={1}
166 />
167 </button>
168 )}
169 </div>
170 {scorePassword && (
171 <div className={classnames({
172 [`${classes.passwordScore}`]: true,
173 [`${classes.hasError}`]: error,
174 })}>
175 <meter
176 value={passwordScore < 5 ? 5 : passwordScore}
177 low={30}
178 high={75}
179 optimum={100}
180 max={100}
181 />
182 </div>
183 )}
184 </Label>
185 {error && (
186 <Error message={error} />
187 )}
188 </Wrapper>
189 );
190 }
191}
192
193export const Input = injectSheet(styles)(InputComponent);