aboutsummaryrefslogtreecommitdiffstats
path: root/packages/forms/src/input/index.tsx
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2019-03-18 03:28:03 -0700
committerLibravatar GitHub <noreply@github.com>2019-03-18 03:28:03 -0700
commit6134c1b49f919dd2c578bc490829d68e4d210f4e (patch)
tree1ad6530fbb7f19e4e9c9a235c6b44e0dfdbc47d4 /packages/forms/src/input/index.tsx
parentAdd missing bracket in brew install help (#1205) (diff)
downloadferdium-app-6134c1b49f919dd2c578bc490829d68e4d210f4e.tar.gz
ferdium-app-6134c1b49f919dd2c578bc490829d68e4d210f4e.tar.zst
ferdium-app-6134c1b49f919dd2c578bc490829d68e4d210f4e.zip
Release/5.0.1 beta.1 (#1344)
* Add lerna * Add theme * Add forms * Add misty config to build theme & forms * reset packages version * Publish - @meetfranz/forms@1.0.0 - @meetfranz/theme@1.0.0 * Reset package version * restructure packages * try ci with lerna * Fix missing packages in build * move storybook to root + typescript TODO: fix modules * Add lerna instructions * Merge * wip * Make packages work in electron, node and web * Finalize packages & replace storybook with homegrown `uidev` * Bring package-lock back in sync * Publish - @meetfranz/forms@1.0.1 - @meetfranz/theme@1.0.1 * fix webpack issue * expose legacy styles * Add toggle element to @meetfranz/forms * start typings package * Update package.json * Add buttons * Update theme * add types * Add mdi icons to buttons * Publish - @meetfranz/forms@1.0.2 - @meetfranz/theme@1.0.2 - @meetfranz/typings@0.0.1 * Button, add missing success state * Update lerna packages * Try to disable automatic npm ci * Try to get a working bundle * Add href and type to button component * Update packages * update versions * cleanup * Update package versions [ci skip] * Update versions * Add withTheme context to button * Update & reuse electron-rebuild * feat(Windows): Add option to quit Franz from Taskbar icon * Add missing withTheme * Fix package versions * Update versions * Add pageview event * Simplify analytics calls * Pin gulp-sass-variables to 1.1.1 * Add onFocus event * Add modal overlay color * remove legacy theme files * remove code * Add dialog to share franz on social media * Fix service count * remove ping * replace ms time strings with ms module * remove unused packages * fix value setter * new payment flow * fix module reference * feat(Spell check): Add en-gb spell check languages (#1306) * move devmode info * fix(Windows): Fix losing window when "Keep Franz in background" is enabled * fix(Service): Fix service zoom (cmd/ctrl+ & cmd/ctrl-) * fixes appveyor build issue * feat(App): Update electron to 4.0.7 * ignore intellij idea project files * Automatic i18n update (i18n.meetfranz.com) * feat(App): Add security checks for external URLs * setup react-intl translations managing script * use same zooming logic for all os * feat(Linux): Add auto updater for Linux AppImage builds * Add ctrl+ for zoom in on Windows * move translation scripts into src/i18n folder * only manage en-US translations * manage translations before git pushes * Fix unused i18n strings * Bump version to 5.0.1-beta.1 * fix(Service) shortcuts for activating prev/next service fixes #1298 * fix(Service): Fix shortcut for (un)muting notifications & audio * add missing react-intl files * correctly update services submenu on language change * fix(Windows): Fix copy & paste in service context menus Closes #1316 * fix(Linux): Fix minimized window focusing (#1304) (@skoruppa) * trigger build * Check if window is minimized before restoring it * restore() should be executed only when window is minimized * fix(Notifications): Fix notifications & notification click when icon is blob * Fix/service webview unmounting (#1328) * detach service when underlying webview unmounts * disable no-param-reassign eslint rule * Add notification debug events * Update electron to 4.0.8 Update required in order to fix performance degradation due to memory leak issue https://github.com/electron/electron/pull/16772. * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * 5.0.1-beta.1
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);