This repository was archived by the owner on Mar 18, 2025. It is now read-only.
forked from openedx/frontend-app-authn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPasswordField.jsx
109 lines (98 loc) · 4.09 KB
/
PasswordField.jsx
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
101
102
103
104
105
106
107
108
109
import React, { useState } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Form, Icon, IconButton, OverlayTrigger, Tooltip, useToggle,
} from '@edx/paragon';
import {
Check, Remove, Visibility, VisibilityOff,
} from '@edx/paragon/icons';
import PropTypes from 'prop-types';
import messages from './messages';
import { LETTER_REGEX, NUMBER_REGEX } from '../data/constants';
const PasswordField = (props) => {
const { formatMessage } = useIntl();
const [isPasswordHidden, setHiddenTrue, setHiddenFalse] = useToggle(true);
const [showTooltip, setShowTooltip] = useState(false);
const handleBlur = (e) => {
if (props.handleBlur) { props.handleBlur(e); }
setShowTooltip(props.showRequirements && false);
};
const handleFocus = (e) => {
if (props.handleFocus) {
props.handleFocus(e);
}
setTimeout(() => setShowTooltip(props.showRequirements && true), 150);
};
const HideButton = (
<IconButton onFocus={handleFocus} onBlur={handleBlur} name="password" src={VisibilityOff} iconAs={Icon} onClick={setHiddenTrue} size="sm" variant="secondary" alt={formatMessage(messages['hide.password'])} />
);
const ShowButton = (
<IconButton onFocus={handleFocus} onBlur={handleBlur} name="password" src={Visibility} iconAs={Icon} onClick={setHiddenFalse} size="sm" variant="secondary" alt={formatMessage(messages['show.password'])} />
);
const placement = window.innerWidth < 768 ? 'top' : 'left';
const tooltip = (
<Tooltip id={`password-requirement-${placement}`}>
<span id="letter-check" className="d-flex align-items-center">
{LETTER_REGEX.test(props.value) ? <Icon className="text-success mr-1" src={Check} /> : <Icon className="mr-1 text-light-700" src={Remove} />}
{formatMessage(messages['one.letter'])}
</span>
<span id="number-check" className="d-flex align-items-center">
{NUMBER_REGEX.test(props.value) ? <Icon className="text-success mr-1" src={Check} /> : <Icon className="mr-1 text-light-700" src={Remove} />}
{formatMessage(messages['one.number'])}
</span>
<span id="characters-check" className="d-flex align-items-center">
{props.value.length >= 8 ? <Icon className="text-success mr-1" src={Check} /> : <Icon className="mr-1 text-light-700" src={Remove} />}
{formatMessage(messages['eight.characters'])}
</span>
</Tooltip>
);
return (
<Form.Group className='grid-1' controlId={props.name} isInvalid={props.errorMessage !== ''}>
<OverlayTrigger key="tooltip" placement={placement} overlay={tooltip} show={showTooltip}>
<Form.Control
as="input"
className="form-group__form-field"
type={isPasswordHidden ? 'password' : 'text'}
name={props.name}
value={props.value}
autoComplete={props.autoComplete}
aria-invalid={props.errorMessage !== ''}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={props.handleChange}
controlClassName={props.borderClass}
trailingElement={isPasswordHidden ? ShowButton : HideButton}
floatingLabel={props.floatingLabel}
/>
</OverlayTrigger>
{props.errorMessage !== '' && (
<Form.Control.Feedback key="error" className="form-text-size" hasIcon={false} feedback-for={props.name} type="invalid">
{props.errorMessage}
<span className="sr-only">{formatMessage(messages['password.sr.only.helping.text'])}</span>
</Form.Control.Feedback>
)}
</Form.Group>
);
};
PasswordField.defaultProps = {
borderClass: '',
errorMessage: '',
handleBlur: null,
handleFocus: null,
handleChange: () => {},
showRequirements: true,
autoComplete: null,
};
PasswordField.propTypes = {
borderClass: PropTypes.string,
errorMessage: PropTypes.string,
floatingLabel: PropTypes.string.isRequired,
handleBlur: PropTypes.func,
handleFocus: PropTypes.func,
handleChange: PropTypes.func,
name: PropTypes.string.isRequired,
showRequirements: PropTypes.bool,
value: PropTypes.string.isRequired,
autoComplete: PropTypes.string,
};
export default PasswordField;