@dvrd/dvr-controls 1.0.62 → 1.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.ts
CHANGED
|
@@ -48,7 +48,7 @@ import DvrdButton, {DvrdButtonProps} from './src/js/button/dvrdButton';
|
|
|
48
48
|
import DvrdDatePicker from './src/js/date/dvrdDatePicker';
|
|
49
49
|
import DvrdInputController from './src/js/textField/dvrdInputController';
|
|
50
50
|
import DvrdNumberInput from './src/js/textField/dvrdNumberInput';
|
|
51
|
-
import
|
|
51
|
+
import DVRDPasswordInput from './src/js/textField/dvrdPasswordInput';
|
|
52
52
|
import Link from './src/js/link/link';
|
|
53
53
|
import DvrdOptionsList from './src/js/optionsList/dvrdOptionsList';
|
|
54
54
|
import DvrdSelectController from './src/js/select/dvrdSelectController';
|
|
@@ -98,7 +98,7 @@ export {
|
|
|
98
98
|
DvrdDatePicker,
|
|
99
99
|
DvrdInputController as DvrdInput,
|
|
100
100
|
DvrdNumberInput,
|
|
101
|
-
|
|
101
|
+
DVRDPasswordInput,
|
|
102
102
|
Link,
|
|
103
103
|
DvrdOptionsList,
|
|
104
104
|
DvrdSelectController as DvrdSelect,
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import './style/passwordInput.scss';
|
|
|
6
6
|
|
|
7
7
|
import React, {KeyboardEventHandler, PureComponent} from 'react';
|
|
8
8
|
|
|
9
|
-
import {ControlVariant, ElementPosition, OrnamentShape,
|
|
9
|
+
import {ControlVariant, ElementPosition, OrnamentShape, StrengthGauge} from "../../util/interfaces";
|
|
10
10
|
import TextField from '../v2/inputController_v2';
|
|
11
11
|
import AwesomeIcon from '../../icon/awesomeIcon';
|
|
12
12
|
import {directTimeout, generateComponentId} from "../../util/componentUtil";
|
|
@@ -39,7 +39,7 @@ interface Props {
|
|
|
39
39
|
autoFocus?: boolean;
|
|
40
40
|
inputProps?: object;
|
|
41
41
|
autoSelect?: boolean;
|
|
42
|
-
strengthGauche?:
|
|
42
|
+
strengthGauche?: StrengthGauge[];
|
|
43
43
|
strengthColors: string[];
|
|
44
44
|
strengthLabels: string[];
|
|
45
45
|
placeholder?: string;
|
|
@@ -3,38 +3,65 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import './style/dvrdPassword.scss';
|
|
5
5
|
|
|
6
|
-
import React, {
|
|
7
|
-
import {AwesomeIcon, ElementPosition} from '@dvrd/dvr-controls';
|
|
6
|
+
import React, {useState} from 'react';
|
|
8
7
|
import DvrdInputController, {InputControllerProps} from "./dvrdInputController";
|
|
8
|
+
import classNames from 'classnames';
|
|
9
|
+
import {ElementPosition, StrengthGauge} from "../util/interfaces";
|
|
10
|
+
import AwesomeIcon from "../icon/awesomeIcon";
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
interface Props extends Omit<InputControllerProps, 'ornaments' | 'ornamentClassName'> {
|
|
13
|
+
withPasswordStrength?: boolean;
|
|
14
|
+
passwordStrengthGauges?: Array<StrengthGauge>;
|
|
15
|
+
wrapperClassName?: string;
|
|
16
|
+
passwordGaugeClassName?: string;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
+
const defaultStrengthGauges = (): StrengthGauge[] => [
|
|
20
|
+
{validator: (password: string) => password.length >= 8},
|
|
21
|
+
{validator: (password: string) => /\d+/.test(password)},
|
|
22
|
+
{validator: (password: string) => /[A-Z]+/.test(password)},
|
|
23
|
+
{validator: (password: string) => /[!@#$%^&*()_+=\-\[\]{}|'";:/?.>,<`~]/.test(password)}
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export default function DVRDPasswordInput(props: Props) {
|
|
27
|
+
const [inputType, setInputType] = useState<'password' | 'text'>('password');
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
29
|
+
function getPasswordStrength(): number {
|
|
30
|
+
const gauges = props.passwordStrengthGauges ?? defaultStrengthGauges();
|
|
31
|
+
return gauges.reduce(
|
|
32
|
+
(prev: number, current: StrengthGauge) => current.validator(props.value.toString()) ? prev + 1 : prev, 0);
|
|
33
|
+
}
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
function onClickOrnament() {
|
|
36
|
+
setInputType(inputType === 'password' ? 'text' : 'password');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function renderOrnament() {
|
|
40
|
+
const iconName = inputType === 'password' ? 'eye' : 'eye-slash';
|
|
28
41
|
return {
|
|
29
42
|
placement: ElementPosition.RIGHT,
|
|
30
|
-
element: <AwesomeIcon name={
|
|
43
|
+
element: <AwesomeIcon name={iconName} onClick={onClickOrnament} className='dvrd-password-toggle'/>
|
|
31
44
|
};
|
|
32
|
-
}
|
|
45
|
+
}
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
function renderStrength() {
|
|
48
|
+
if (!props.withPasswordStrength) return null;
|
|
49
|
+
const strength = getPasswordStrength();
|
|
36
50
|
return (
|
|
37
|
-
<
|
|
51
|
+
<div className={classNames('password-meter', props.passwordGaugeClassName)}>
|
|
52
|
+
<span className={classNames('password-strength', strength > 0 && 'pass')}/>
|
|
53
|
+
<span className={classNames('password-strength', strength > 1 && 'pass')}/>
|
|
54
|
+
<span className={classNames('password-strength', strength > 2 && 'pass')}/>
|
|
55
|
+
<span className={classNames('password-strength', strength > 3 && 'pass')}/>
|
|
56
|
+
</div>
|
|
38
57
|
);
|
|
39
58
|
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div className={classNames('dvrd-password-input', props.wrapperClassName)}>
|
|
62
|
+
<DvrdInputController {...props} inputProps={{...props.inputProps, type: inputType}}
|
|
63
|
+
ornaments={renderOrnament()}/>
|
|
64
|
+
{renderStrength()}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
40
67
|
}
|
|
@@ -4,12 +4,34 @@
|
|
|
4
4
|
|
|
5
5
|
@import '../../../style/variables';
|
|
6
6
|
|
|
7
|
-
.dvrd-password-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
.dvrd-password-input {
|
|
8
|
+
display: grid;
|
|
9
|
+
row-gap: 1rem;
|
|
10
|
+
.dvrd-password-toggle {
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
transition: color .2s ease-in-out;
|
|
13
|
+
color: $color-gray-3;
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
&:hover {
|
|
16
|
+
color: $color-gray-5;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.password-meter {
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: repeat(4, calc(25% - calc(1.5rem / 4)));
|
|
23
|
+
grid-column-gap: .5rem;
|
|
24
|
+
margin-top: -.25rem;
|
|
25
|
+
width: 100%;
|
|
26
|
+
|
|
27
|
+
.password-strength {
|
|
28
|
+
background-color: #E5E7EB;
|
|
29
|
+
border-radius: 1rem;
|
|
30
|
+
height: .5rem;
|
|
31
|
+
|
|
32
|
+
&.pass {
|
|
33
|
+
background-color: #77C695;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
14
36
|
}
|
|
15
37
|
}
|
|
@@ -171,7 +171,7 @@ export type CustomAppEvent = {
|
|
|
171
171
|
export type ChangeFunction<T = any> = (value: T, evt?: React.ChangeEvent) => void;
|
|
172
172
|
export type ChangeKeyFunction<K = string, V = any> = (key: K) => ChangeFunction<V>;
|
|
173
173
|
export type ModelResponse<T> = (obj: T, success: boolean | undefined, data: ResponseData) => void;
|
|
174
|
-
export type
|
|
174
|
+
export type StrengthGauge = { validator: (password: string) => boolean };
|
|
175
175
|
export type PDFSetting = { key: string; label: string; type: PDFSettingType; value: any };
|
|
176
176
|
|
|
177
177
|
export type PDFElementParams<T extends PDFElementType, O extends IndexedObject<any>> = {
|
|
@@ -113,7 +113,7 @@ function _handleResponse(response: Response, config: FetchOptions) {
|
|
|
113
113
|
config.callback(data, response);
|
|
114
114
|
}
|
|
115
115
|
});
|
|
116
|
-
} else config.callback({status: 'success'}, response);
|
|
116
|
+
} else config.callback({status: 'success', success: true}, response);
|
|
117
117
|
} else
|
|
118
118
|
_onErrorResponse(response, config);
|
|
119
119
|
}
|