@dvrd/dvr-controls 1.0.62 → 1.0.64

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 DvrdPasswordInput from './src/js/textField/dvrdPasswordInput';
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
- DvrdPasswordInput,
101
+ DVRDPasswordInput,
102
102
  Link,
103
103
  DvrdOptionsList,
104
104
  DvrdSelectController as DvrdSelect,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvrd/dvr-controls",
3
- "version": "1.0.62",
3
+ "version": "1.0.64",
4
4
  "description": "Custom web controls",
5
5
  "main": "index.ts",
6
6
  "files": [
@@ -84,12 +84,12 @@ export default function DvrdCheckbox(props: Props) {
84
84
  }
85
85
  return {borderColor: convertColor(color)};
86
86
  }, [error, useDarkestColor, isHovered, disabled, baseColor, contrastColor]);
87
- const checkStyle: CSSProperties = useMemo(() => {
87
+ const [checkStyle, partialCheckStyle]: [CSSProperties, CSSProperties] = useMemo(() => {
88
88
  let color: string = baseColor;
89
89
  if (!!error) color = 'red';
90
90
  else if (disabled) color = 'color-gray-4';
91
91
  else if (useDarkestColor) color = findDarkestColor(baseColor, contrastColor);
92
- return {color: convertColor(color)};
92
+ return [{color: convertColor(color)}, {backgroundColor: convertColor(color)}];
93
93
  }, [error, disabled, useDarkestColor, baseColor, contrastColor]);
94
94
  const mainColor = useMemo(() => {
95
95
  return useDarkestColor ? findDarkestColor(baseColor, contrastColor) : baseColor;
@@ -114,11 +114,15 @@ export default function DvrdCheckbox(props: Props) {
114
114
  className: classNames(checkIcon.props.className, checkClassName),
115
115
  style: {...checkIcon.props.style, ...checkStyle}
116
116
  });
117
+ else if (checked === 'partial') return (
118
+ <div className={classNames(checkClassName, 'partial-icon')} style={partialCheckStyle}/>
119
+ );
117
120
  let checkName: IconName = 'check';
118
- if(typeof checkIcon === 'string') checkName = checkIcon as IconName;
121
+ let additionalClassName: string | null = null;
122
+ if (typeof checkIcon === 'string') checkName = checkIcon as IconName;
119
123
  else if (asRadio) checkName = 'circle';
120
- else if (checked === 'partial') checkName = 'minus';
121
- return <AwesomeIcon name={checkName} className={checkClassName} style={checkStyle}/>;
124
+ return <AwesomeIcon name={checkName} className={classNames(checkClassName, additionalClassName)}
125
+ style={checkStyle}/>;
122
126
  }
123
127
 
124
128
  function renderError() {
@@ -47,6 +47,13 @@
47
47
  transition: opacity .1s ease-in-out, visibility .1s ease-in-out;
48
48
  user-select: none;
49
49
 
50
+ &.partial-icon {
51
+ top: 50%;
52
+ width: 12px;
53
+ height: 3px;
54
+ border-radius: 4px;
55
+ }
56
+
50
57
  &.checked {
51
58
  visibility: visible;
52
59
  opacity: 1;
@@ -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, StrengthGauche} from "../../util/interfaces";
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?: 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, {PureComponent} from '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
- interface State {
12
- type: 'password' | 'text';
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
- export default class DvrdPasswordInput extends PureComponent<InputControllerProps, State> {
16
- state: State = {
17
- type: 'password',
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
- onClickOrnament = () => {
21
- const {type} = this.state;
22
- if (type === 'password') this.setState({type: 'text'});
23
- else this.setState({type: 'password'});
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
- renderOrnament = () => {
27
- const {type} = this.state, element = type === 'password' ? 'eye' : 'eye-slash';
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={element} onClick={this.onClickOrnament} className='dvrd-password-toggle'/>
43
+ element: <AwesomeIcon name={iconName} onClick={onClickOrnament} className='dvrd-password-toggle'/>
31
44
  };
32
- };
45
+ }
33
46
 
34
- render = () => {
35
- const {type} = this.state, {inputProps} = this.props;
47
+ function renderStrength() {
48
+ if (!props.withPasswordStrength) return null;
49
+ const strength = getPasswordStrength();
36
50
  return (
37
- <DvrdInputController {...this.props} inputProps={{...inputProps, type}} ornaments={this.renderOrnament()}/>
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-toggle {
8
- cursor: pointer;
9
- transition: color .2s ease-in-out;
10
- color: $color-gray-3;
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
- &:hover {
13
- color: $color-gray-5;
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 StrengthGauche = { validator: (password: string) => boolean };
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
  }