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.tsx190
1 files changed, 190 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..de7e7848e
--- /dev/null
+++ b/packages/forms/src/input/index.tsx
@@ -0,0 +1,190 @@
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 scorePassword: false,
41 showLabel: true,
42 showPasswordToggle: false,
43 type: 'text',
44 disabled: false,
45 };
46
47 state = {
48 passwordScore: 0,
49 showPassword: false,
50 };
51
52 private inputRef = createRef<HTMLInputElement>();
53
54 componentDidMount() {
55 const { focus, data } = this.props;
56
57 if (this.inputRef && this.inputRef.current) {
58 if (focus) {
59 this.inputRef.current.focus();
60 }
61
62 if (data) {
63 Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]);
64 }
65 }
66 }
67
68 onChange(e: React.ChangeEvent<HTMLInputElement>) {
69 const {
70 scorePassword,
71 onChange,
72 } = this.props;
73
74 if (onChange) {
75 onChange(e);
76 }
77
78 if (this.inputRef && this.inputRef.current && scorePassword) {
79 this.setState({ passwordScore: scorePasswordFunc(this.inputRef.current.value) });
80 }
81 }
82
83 render() {
84 const {
85 classes,
86 className,
87 disabled,
88 error,
89 id,
90 inputClassName,
91 label,
92 prefix,
93 scorePassword,
94 suffix,
95 showLabel,
96 showPasswordToggle,
97 type,
98 value,
99 name,
100 placeholder,
101 spellCheck,
102 onBlur,
103 } = this.props;
104
105 const {
106 showPassword,
107 passwordScore,
108 } = this.state;
109
110 const inputType = type === 'password' && showPassword ? 'text' : type;
111
112 return (
113 <Wrapper
114 className={className}
115 identifier="franz-input"
116 >
117 <Label
118 title={label}
119 showLabel={showLabel}
120 htmlFor={id}
121 >
122 <div
123 className={classnames({
124 [`${inputClassName}`]: inputClassName,
125 [`${classes.hasPasswordScore}`]: scorePassword,
126 [`${classes.wrapper}`]: true,
127 [`${classes.disabled}`]: disabled,
128 [`${classes.hasError}`]: error,
129 })}>
130 {prefix && (
131 <span className={classes.prefix}>
132 {prefix}
133 </span>
134 )}
135 <input
136 id={id}
137 type={inputType}
138 name={name}
139 defaultValue={value as string}
140 placeholder={placeholder}
141 spellCheck={spellCheck}
142 className={classes.input}
143 ref={this.inputRef}
144 onChange={this.onChange.bind(this)}
145 onBlur={onBlur}
146 disabled={disabled}
147 />
148 {suffix && (
149 <span className={classes.suffix}>
150 {suffix}
151 </span>
152 )}
153 {showPasswordToggle && (
154 <button
155 type="button"
156 className={classes.formModifier}
157 onClick={() => this.setState(prevState => ({ showPassword: !prevState.showPassword }))}
158 tabIndex={-1}
159 >
160 <Icon
161 path={!showPassword ? mdiEye : mdiEyeOff}
162 size={1}
163 />
164 </button>
165 )}
166 </div>
167 {scorePassword && (
168 <div className={classnames({
169 [`${classes.passwordScore}`]: true,
170 [`${classes.hasError}`]: error,
171 })}>
172 <meter
173 value={passwordScore < 5 ? 5 : passwordScore}
174 low={30}
175 high={75}
176 optimum={100}
177 max={100}
178 />
179 </div>
180 )}
181 </Label>
182 {error && (
183 <Error message={error} />
184 )}
185 </Wrapper>
186 );
187 }
188}
189
190export const Input = injectSheet(styles)(InputComponent);