@plesk/ui-library 3.27.0 → 3.27.3

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.
Files changed (46) hide show
  1. package/cjs/components/Dialog/Dialog.js +11 -2
  2. package/cjs/components/Drawer/DrawerProgress.js +15 -1
  3. package/cjs/components/FormFieldPassword/FormFieldPassword.js +24 -214
  4. package/cjs/components/FormFieldPassword/PasswordMeter.js +81 -0
  5. package/cjs/components/FormFieldPassword/estimatePassword.js +203 -0
  6. package/cjs/components/FormFieldPassword/generatePassword.js +21 -0
  7. package/cjs/components/FormFieldPassword/index.js +5 -5
  8. package/cjs/components/Icon/Icon.js +1 -1
  9. package/cjs/components/List/List.js +1 -1
  10. package/cjs/components/ProgressDialog/ProgressDialog.js +2 -1
  11. package/cjs/components/Rating/images/rating.svg +5 -5
  12. package/cjs/index.js +1 -1
  13. package/dist/images/rating.svg +5 -5
  14. package/dist/plesk-ui-library-rtl.css +1 -1
  15. package/dist/plesk-ui-library-rtl.css.map +1 -1
  16. package/dist/plesk-ui-library.css +1 -1
  17. package/dist/plesk-ui-library.css.map +1 -1
  18. package/dist/plesk-ui-library.js +336 -309
  19. package/dist/plesk-ui-library.js.map +1 -1
  20. package/dist/plesk-ui-library.min.js +5 -5
  21. package/dist/plesk-ui-library.min.js.map +1 -1
  22. package/esm/components/Dialog/Dialog.js +11 -2
  23. package/esm/components/Drawer/DrawerProgress.js +16 -2
  24. package/esm/components/FormFieldPassword/FormFieldPassword.js +22 -206
  25. package/esm/components/FormFieldPassword/PasswordMeter.js +61 -0
  26. package/esm/components/FormFieldPassword/estimatePassword.js +187 -0
  27. package/esm/components/FormFieldPassword/generatePassword.js +14 -0
  28. package/esm/components/FormFieldPassword/index.js +3 -2
  29. package/esm/components/Icon/Icon.js +1 -1
  30. package/esm/components/List/List.js +1 -1
  31. package/esm/components/ProgressDialog/ProgressDialog.js +2 -1
  32. package/esm/components/Rating/images/rating.svg +5 -5
  33. package/esm/index.js +1 -1
  34. package/package.json +13 -8
  35. package/styleguide/build/bundle.f38c467d.js +2 -0
  36. package/styleguide/build/{bundle.ff1f903a.js.LICENSE.txt → bundle.f38c467d.js.LICENSE.txt} +0 -0
  37. package/styleguide/images/rating.svg +5 -5
  38. package/styleguide/index.html +2 -2
  39. package/types/package.d.ts +5 -0
  40. package/types/src/components/FormFieldPassword/FormFieldPassword.d.ts +91 -0
  41. package/types/src/components/FormFieldPassword/PasswordMeter.d.ts +9 -0
  42. package/types/src/components/FormFieldPassword/estimatePassword.d.ts +13 -0
  43. package/types/src/components/FormFieldPassword/index.d.ts +2 -0
  44. package/cjs/components/FormFieldPassword/passwordScore.js +0 -131
  45. package/esm/components/FormFieldPassword/passwordScore.js +0 -122
  46. package/styleguide/build/bundle.ff1f903a.js +0 -2
@@ -40,6 +40,7 @@ const Dialog = ({
40
40
  closable,
41
41
  onClose,
42
42
  closingConfirmation,
43
+ canClose,
43
44
  ...props
44
45
  }) => {
45
46
  const [isVisible, setIsVisible] = useState(isOpen);
@@ -150,8 +151,8 @@ const Dialog = ({
150
151
  className: classNames(baseClassName, className),
151
152
  isOpen: isVisible,
152
153
  onClose: onCloseWithConfirmation,
153
- canCloseOnBackdropClick: closable,
154
- canCloseOnEscapePress: closable,
154
+ canCloseOnBackdropClick: canClose && closable,
155
+ canCloseOnEscapePress: canClose && closable,
155
156
  size: size
156
157
  }, props), (title || subtitle || actions) && /*#__PURE__*/React.createElement("header", {
157
158
  className: `${baseClassName}__header`
@@ -174,6 +175,7 @@ const Dialog = ({
174
175
  className: `${baseClassName}__header-actions`
175
176
  }, actions, closable && /*#__PURE__*/React.createElement(Button, {
176
177
  className: `${baseClassName}__header-close`,
178
+ disabled: !canClose,
177
179
  ghost: true,
178
180
  size: "lg",
179
181
  icon: "cross-mark",
@@ -279,6 +281,12 @@ Dialog.propTypes = {
279
281
  */
280
282
  closable: PropTypes.bool,
281
283
 
284
+ /**
285
+ * Disable close dialog button
286
+ * @since 4.0.0
287
+ */
288
+ canClose: PropTypes.bool,
289
+
282
290
  /**
283
291
  * On close event handler. Called immediately after dialog closed by "cancel" button or "Esc" key.
284
292
  * @since 0.0.68
@@ -322,6 +330,7 @@ Dialog.defaultProps = {
322
330
  form: undefined,
323
331
  size: 'md',
324
332
  closable: true,
333
+ canClose: true,
325
334
  onClose: undefined,
326
335
  closingConfirmation: undefined,
327
336
  children: undefined,
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
3
  // Copyright 1999-2019. Plesk International GmbH. All rights reserved.
4
- import React, { Component, Fragment } from 'react';
4
+ import React, { Component, Fragment, isValidElement, cloneElement } from 'react';
5
5
  import Button from '../Button';
6
6
  import Translate from '../Translate';
7
7
  import Progress from '../Progress';
@@ -9,6 +9,20 @@ import ProgressStep, { STATUS_DONE, STATUS_ERROR, STATUS_NOT_STARTED } from '../
9
9
  import { CLS_PREFIX } from '../../constants';
10
10
  import { safeInvoke } from '../utils';
11
11
 
12
+ const renderAdditionalButtons = buttons => {
13
+ const buttonProcessing = button => {
14
+ if ( /*#__PURE__*/isValidElement(button) && button.type === Button) {
15
+ return /*#__PURE__*/cloneElement(button, {
16
+ size: 'lg'
17
+ });
18
+ }
19
+
20
+ return button;
21
+ };
22
+
23
+ return Array.isArray(buttons) ? buttons.map(buttonProcessing) : buttonProcessing(buttons);
24
+ };
25
+
12
26
  class DrawerProgress extends Component {
13
27
  constructor(...args) {
14
28
  super(...args);
@@ -125,7 +139,7 @@ class DrawerProgress extends Component {
125
139
  }, step)))));
126
140
  const footer = hasFooter ? /*#__PURE__*/React.createElement("div", {
127
141
  className: `${baseClassName}__footer`
128
- }, buttons, canCancel && /*#__PURE__*/React.createElement(Button, {
142
+ }, renderAdditionalButtons(buttons), canCancel && /*#__PURE__*/React.createElement(Button, {
129
143
  onClick: this.handleCancel,
130
144
  size: "lg"
131
145
  }, /*#__PURE__*/React.createElement(Translate, {
@@ -1,32 +1,21 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
- // Copyright 1999-2021. Plesk International GmbH. All rights reserved.
3
+ // Copyright 1999-2022. Plesk International GmbH. All rights reserved.
4
4
  import React, { Component, Fragment, createRef } from 'react';
5
- import PropTypes from 'prop-types';
6
5
  import classNames from 'classnames';
7
6
  import { CLS_PREFIX } from '../../constants';
8
7
  import Button from '../Button';
9
8
  import FormField from '../FormField';
10
9
  import Input from '../Input';
11
- import Popover from '../Popover';
12
10
  import Translate from '../Translate';
13
- import passwordScore, { PASSWORD_SCORE_RULES } from './passwordScore';
11
+ import PasswordMeter from './PasswordMeter';
12
+ import generatePassword from './generatePassword';
14
13
  import locale from './locale/en-US';
15
- const symbolClasses = {
16
- upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
17
- lower: 'abcdefghijklmnopqrstuvwxyz',
18
- number: '0123456789',
19
- special: '!@#$%^&*?_~'
20
- };
21
- export const generatePassword = () => {
22
- const password = ['upper', 'lower', 'lower', 'lower', 'number', 'number', 'special', 'number', 'upper', 'upper', 'lower', 'lower', 'lower', 'lower', 'lower', 'lower'];
23
- return password.sort((a, b) => Math.floor(b.length * Math.random()) - Math.floor(a.length * Math.random())).map(symbolClass => symbolClasses[symbolClass][Math.floor(symbolClasses[symbolClass].length * Math.random())]).join('');
24
- };
14
+
25
15
  /**
26
16
  * `FormFieldPassword` component provides secure way to enter a password.
27
17
  * @since 0.0.58
28
18
  */
29
-
30
19
  class FormFieldPassword extends Component {
31
20
  constructor(...args) {
32
21
  super(...args);
@@ -55,117 +44,6 @@ class FormFieldPassword extends Component {
55
44
  _defineProperty(this, "handleBlur", this.handleClosePasswordMeter);
56
45
  }
57
46
 
58
- passwordScore(value) {
59
- if (!value) {
60
- return {
61
- intent: null,
62
- strength: null,
63
- unusedRules: []
64
- };
65
- }
66
-
67
- const {
68
- passwordScoreRules
69
- } = this.props;
70
- const {
71
- score,
72
- unusedRules
73
- } = passwordScore(value, passwordScoreRules);
74
- let intent = 'success';
75
- let strength = /*#__PURE__*/React.createElement(Translate, {
76
- content: "FormFieldPassword.strengthVeryStrong",
77
- fallback: locale.strengthVeryStrong
78
- });
79
-
80
- if (score < 16) {
81
- intent = 'danger';
82
- strength = /*#__PURE__*/React.createElement(Translate, {
83
- content: "FormFieldPassword.strengthVeryWeak",
84
- fallback: locale.strengthVeryWeak
85
- });
86
- } else if (score < 25) {
87
- intent = 'danger';
88
- strength = /*#__PURE__*/React.createElement(Translate, {
89
- content: "FormFieldPassword.strengthWeak",
90
- fallback: locale.strengthWeak
91
- });
92
- } else if (score < 35) {
93
- intent = 'warning';
94
- strength = /*#__PURE__*/React.createElement(Translate, {
95
- content: "FormFieldPassword.strengthMedium",
96
- fallback: locale.strengthMedium
97
- });
98
- } else if (score < 45) {
99
- intent = 'success';
100
- strength = /*#__PURE__*/React.createElement(Translate, {
101
- content: "FormFieldPassword.strengthStrong",
102
- fallback: locale.strengthStrong
103
- });
104
- }
105
-
106
- return {
107
- intent,
108
- strength,
109
- unusedRules
110
- };
111
- }
112
-
113
- renderPasswordMeter(value, target) {
114
- const {
115
- passwordMeterVisible
116
- } = this.state;
117
- const {
118
- passwordMeterProps
119
- } = this.props;
120
- const {
121
- intent,
122
- strength,
123
- unusedRules
124
- } = this.passwordScore(value);
125
- return /*#__PURE__*/React.createElement(Popover, _extends({
126
- visible: passwordMeterVisible && !!value,
127
- target: target,
128
- targetRef: this.targetRef,
129
- placement: "bottom-right",
130
- intent: intent,
131
- canCloseOnOutsideClick: false,
132
- canCloseOnEscapePress: false,
133
- onClose: this.handleClosePasswordMeter
134
- }, passwordMeterProps), /*#__PURE__*/React.createElement(Translate, {
135
- content: "FormFieldPassword.passwordStrength",
136
- fallback: locale.passwordStrength,
137
- params: {
138
- strength: /*#__PURE__*/React.createElement("b", null, strength)
139
- }
140
- }), /*#__PURE__*/React.createElement("br", null), unusedRules.length ? /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Translate, {
141
- content: "FormFieldPassword.improvePassword",
142
- fallback: locale.improvePassword
143
- }), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("ul", null, unusedRules.slice(0, 3).map(({
144
- rule
145
- }, index) => {
146
- const {
147
- name
148
- } = rule;
149
- let {
150
- message
151
- } = rule;
152
-
153
- if (name && !message) {
154
- message = /*#__PURE__*/React.createElement(Translate, {
155
- content: `FormFieldPassword.${name}`,
156
- fallback: locale[name]
157
- });
158
- }
159
-
160
- return /*#__PURE__*/React.createElement("li", {
161
- key: name || index.toString()
162
- }, message);
163
- }))) : /*#__PURE__*/React.createElement(Translate, {
164
- content: "FormFieldPassword.yourPasswordIsStrong",
165
- fallback: locale.yourPasswordIsStrong
166
- }));
167
- }
168
-
169
47
  renderGenerateButton({
170
48
  setValue,
171
49
  isDisabled
@@ -207,12 +85,15 @@ class FormFieldPassword extends Component {
207
85
  hideGenerateButton,
208
86
  hidePasswordMeter,
209
87
  passwordMeterProps,
210
- passwordScoreRules,
211
88
  size,
212
89
  autoFocus,
213
90
  autoComplete,
214
91
  ...props
215
92
  } = this.props;
93
+ const {
94
+ visible,
95
+ passwordMeterVisible
96
+ } = this.state;
216
97
  return /*#__PURE__*/React.createElement(FormField, _extends({
217
98
  className: classNames(baseClassName, className)
218
99
  }, props), ({
@@ -222,18 +103,18 @@ class FormFieldPassword extends Component {
222
103
  setValue,
223
104
  isDisabled
224
105
  }) => {
106
+ const value = getValue('');
225
107
  const input = /*#__PURE__*/React.createElement(Input, {
226
108
  id: getId(),
227
109
  name: getName(),
228
- type: this.state.visible ? 'text' : 'password',
229
- value: getValue(''),
110
+ type: visible ? 'text' : 'password',
111
+ value: value,
230
112
  onChange: e => {
231
113
  setValue(e.target.value);
232
114
  this.setState({
233
115
  passwordMeterVisible: true
234
116
  });
235
117
  },
236
- onFocus: this.handleFocus,
237
118
  onBlur: this.handleBlur,
238
119
  autoFocus: autoFocus,
239
120
  autoComplete: autoComplete,
@@ -242,8 +123,8 @@ class FormFieldPassword extends Component {
242
123
  suffix: hideShowButton ? null : /*#__PURE__*/React.createElement(Button, {
243
124
  className: `${baseClassName}__button--show`,
244
125
  onClick: this.handleToggleClick,
245
- icon: this.state.visible ? 'visible' : 'invisible',
246
- tooltip: this.state.visible ? /*#__PURE__*/React.createElement(Translate, {
126
+ icon: visible ? 'visible' : 'invisible',
127
+ tooltip: visible ? /*#__PURE__*/React.createElement(Translate, {
247
128
  content: "FormFieldPassword.hidePassword",
248
129
  fallback: locale.hidePassword
249
130
  }) : /*#__PURE__*/React.createElement(Translate, {
@@ -262,7 +143,12 @@ class FormFieldPassword extends Component {
262
143
  className: classNames(`${baseClassName}__control`, `${baseClassName}__control--${size}`)
263
144
  }, /*#__PURE__*/React.createElement("div", {
264
145
  className: classNames(`${baseClassName}__field`, `${baseClassName}__field--${size}`)
265
- }, hidePasswordMeter ? input : this.renderPasswordMeter(getValue(), input)), hideGenerateButton ? null : this.renderGenerateButton({
146
+ }, hidePasswordMeter ? input : /*#__PURE__*/React.createElement(PasswordMeter, _extends({
147
+ value: value,
148
+ targetRef: this.targetRef,
149
+ visible: passwordMeterVisible && value !== '',
150
+ onClose: this.handleClosePasswordMeter
151
+ }, passwordMeterProps), input)), hideGenerateButton ? null : this.renderGenerateButton({
266
152
  setValue,
267
153
  isDisabled
268
154
  }));
@@ -271,87 +157,17 @@ class FormFieldPassword extends Component {
271
157
 
272
158
  }
273
159
 
274
- FormFieldPassword.propTypes = {
275
- /**
276
- * Is show button hidden?
277
- * @since 0.0.59
278
- */
279
- hideShowButton: PropTypes.bool,
280
-
281
- /**
282
- * Is generate button hidden?
283
- * @since 0.0.59
284
- */
285
- hideGenerateButton: PropTypes.bool,
286
-
287
- /**
288
- * Is password meter hidden?
289
- * @since 0.0.59
290
- */
291
- hidePasswordMeter: PropTypes.bool,
292
-
293
- /**
294
- * Additional props for password meter. . See [Popover](#!/Popover) for more information.
295
- * @since 1.5.6
296
- */
297
- passwordMeterProps: PropTypes.object,
298
-
299
- /**
300
- * A set of custom password score rules.
301
- * @since 3.21.0
302
- */
303
- passwordScoreRules: PropTypes.arrayOf(PropTypes.shape({
304
- name: PropTypes.string,
305
- message: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
306
- score: PropTypes.func.isRequired
307
- })),
308
-
309
- /**
310
- * Size of the control
311
- * @since 1.5.6
312
- */
313
- size: PropTypes.oneOf(['md', 'lg', 'xl', 'fill']),
314
-
315
- /**
316
- * The browser will automatically focus on the component upon rendering the screen
317
- * @since 1.9.0
318
- */
319
- autoFocus: PropTypes.bool,
320
-
321
- /**
322
- * Prevent password autocompletion.
323
- * @since 2.5.1
324
- */
325
- autoComplete: PropTypes.oneOf(['new-password']),
326
-
327
- /**
328
- * A render function for customizing the password generation button.
329
- * @since 3.13.0
330
- */
331
- generateButton: PropTypes.func,
332
-
333
- /**
334
- * @ignore
335
- */
336
- className: PropTypes.string,
337
-
338
- /**
339
- * @ignore
340
- */
341
- baseClassName: PropTypes.string
342
- };
343
- FormFieldPassword.defaultProps = {
160
+ _defineProperty(FormFieldPassword, "defaultProps", {
344
161
  hideShowButton: false,
345
162
  generateButton: undefined,
346
163
  hideGenerateButton: false,
347
164
  hidePasswordMeter: false,
348
165
  passwordMeterProps: {},
349
- passwordScoreRules: undefined,
350
166
  size: 'md',
351
167
  autoFocus: undefined,
352
168
  autoComplete: undefined,
353
169
  className: undefined,
354
170
  baseClassName: `${CLS_PREFIX}form-field-password`
355
- };
356
- FormFieldPassword.PASSWORD_SCORE_RULES = PASSWORD_SCORE_RULES;
171
+ });
172
+
357
173
  export default FormFieldPassword;
@@ -0,0 +1,61 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ // Copyright 1999-2022. Plesk International GmbH. All rights reserved.
3
+ import React, { Fragment, useState, useEffect } from 'react';
4
+ import Popover from '../Popover';
5
+ import Translate from '../Translate';
6
+ import estimatePassword, { DEFAULT_RULES } from './estimatePassword';
7
+ import locale from './locale/en-US';
8
+ const strengthIntents = {
9
+ VeryWeak: 'danger',
10
+ Weak: 'danger',
11
+ Medium: 'warning',
12
+ Strong: 'success',
13
+ VeryStrong: 'success'
14
+ };
15
+
16
+ const PasswordMeter = ({
17
+ value,
18
+ visible,
19
+ onEstimate,
20
+ children,
21
+ ...props
22
+ }) => {
23
+ const [result, setResult] = useState(null);
24
+ useEffect(() => {
25
+ if (!visible) {
26
+ return;
27
+ }
28
+
29
+ Promise.resolve(onEstimate ? onEstimate(value, estimatePassword, DEFAULT_RULES) : estimatePassword(value)).then(result => {
30
+ setResult(result);
31
+ });
32
+ }, [visible, value, onEstimate]);
33
+ return /*#__PURE__*/React.createElement(Popover, _extends({
34
+ visible: visible && result !== null,
35
+ target: children,
36
+ placement: "bottom-right",
37
+ intent: result ? strengthIntents[result.strength] : undefined,
38
+ canCloseOnOutsideClick: false,
39
+ canCloseOnEscapePress: false
40
+ }, props), result !== null && result !== void 0 && result.strength ? /*#__PURE__*/React.createElement(Translate, {
41
+ component: "div",
42
+ content: "FormFieldPassword.passwordStrength",
43
+ fallback: locale.passwordStrength,
44
+ params: {
45
+ strength: /*#__PURE__*/React.createElement("b", null, /*#__PURE__*/React.createElement(Translate, {
46
+ content: `FormFieldPassword.strength${result === null || result === void 0 ? void 0 : result.strength}`,
47
+ fallback: locale[`strength${result === null || result === void 0 ? void 0 : result.strength}`]
48
+ }))
49
+ }
50
+ }) : null, result !== null && result !== void 0 && result.suggestions.length ? /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Translate, {
51
+ content: "FormFieldPassword.improvePassword",
52
+ fallback: locale.improvePassword
53
+ }), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("ul", null, result.suggestions.slice(0, 3).map((suggestion, index) => /*#__PURE__*/React.createElement("li", {
54
+ key: index.toString()
55
+ }, suggestion)))) : /*#__PURE__*/React.createElement(Translate, {
56
+ content: "FormFieldPassword.yourPasswordIsStrong",
57
+ fallback: locale.yourPasswordIsStrong
58
+ }));
59
+ };
60
+
61
+ export default PasswordMeter;
@@ -0,0 +1,187 @@
1
+ // Copyright 1999-2022. Plesk International GmbH. All rights reserved.
2
+ import React from 'react';
3
+ import Translate from '../Translate';
4
+ import locale from './locale/en-US';
5
+ export const DEFAULT_RULES = [{
6
+ name: 'passwordTooShort',
7
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
8
+ content: `FormFieldPassword.passwordTooShort`,
9
+ fallback: locale.passwordTooShort
10
+ }),
11
+
12
+ score(passwd) {
13
+ return passwd.length < 5 ? -1 : 0;
14
+ }
15
+
16
+ }, {
17
+ name: 'passwordLength',
18
+
19
+ score(passwd) {
20
+ if (passwd.length < 5) {
21
+ return 3;
22
+ }
23
+
24
+ if (passwd.length > 4 && passwd.length < 8) {
25
+ return 6;
26
+ }
27
+
28
+ if (passwd.length > 7 && passwd.length < 16) {
29
+ return 12;
30
+ }
31
+
32
+ return 18;
33
+ }
34
+
35
+ }, {
36
+ name: 'lettersLowerCase',
37
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
38
+ content: `FormFieldPassword.lettersLowerCase`,
39
+ fallback: locale.lettersLowerCase
40
+ }),
41
+
42
+ score(passwd) {
43
+ // [verified] at least one lower case letter
44
+ return passwd.match(/[a-z]/) ? 1 : -1;
45
+ }
46
+
47
+ }, {
48
+ name: 'lettersUpperCase',
49
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
50
+ content: `FormFieldPassword.lettersUpperCase`,
51
+ fallback: locale.lettersUpperCase
52
+ }),
53
+
54
+ score(passwd) {
55
+ // [verified] at least one upper case letter
56
+ return passwd.match(/[A-Z]/) ? 5 : -1;
57
+ }
58
+
59
+ }, {
60
+ name: 'numbers1',
61
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
62
+ content: `FormFieldPassword.numbers1`,
63
+ fallback: locale.numbers1
64
+ }),
65
+
66
+ score(passwd) {
67
+ // [verified] at least one number
68
+ return passwd.match(/\d+/) ? 5 : -1;
69
+ }
70
+
71
+ }, {
72
+ name: 'numbers3',
73
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
74
+ content: `FormFieldPassword.numbers3`,
75
+ fallback: locale.numbers3
76
+ }),
77
+
78
+ score(passwd) {
79
+ // [verified] at least three numbers
80
+ return passwd.match(/(.*[0-9].*[0-9].*[0-9])/) ? 5 : -1;
81
+ }
82
+
83
+ }, {
84
+ name: 'specialChar1',
85
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
86
+ content: `FormFieldPassword.specialChar1`,
87
+ fallback: locale.specialChar1
88
+ }),
89
+
90
+ score(passwd) {
91
+ // [verified] at least one special character
92
+ return passwd.match(/[!@#$%^&*?_~]/) ? 5 : -1;
93
+ }
94
+
95
+ }, {
96
+ name: 'specialChar2',
97
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
98
+ content: `FormFieldPassword.specialChar2`,
99
+ fallback: locale.specialChar2
100
+ }),
101
+
102
+ score(passwd) {
103
+ // [verified] at least two special characters
104
+ return passwd.match(/(.*[!@#$%^&*?_~].*[!@#$%^&*?_~])/) ? 5 : -1;
105
+ }
106
+
107
+ }, {
108
+ name: 'comboUpperAndLower',
109
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
110
+ content: `FormFieldPassword.comboUpperAndLower`,
111
+ fallback: locale.comboUpperAndLower
112
+ }),
113
+
114
+ score(passwd) {
115
+ // [verified] both upper and lower case
116
+ return passwd.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) ? 2 : -1;
117
+ }
118
+
119
+ }, {
120
+ name: 'comboLettersAndNumbers',
121
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
122
+ content: `FormFieldPassword.comboLettersAndNumbers`,
123
+ fallback: locale.comboLettersAndNumbers
124
+ }),
125
+
126
+ score(passwd) {
127
+ // [verified] both letters and numbers
128
+ return passwd.match(/([a-zA-Z])/) && passwd.match(/([0-9])/) ? 2 : -1;
129
+ }
130
+
131
+ }, {
132
+ name: 'comboLettersNumbersSpecial',
133
+ suggestion: /*#__PURE__*/React.createElement(Translate, {
134
+ content: `FormFieldPassword.comboLettersNumbersSpecial`,
135
+ fallback: locale.comboLettersNumbersSpecial
136
+ }),
137
+
138
+ score(passwd) {
139
+ // [verified] letters, numbers, and special characters
140
+ return passwd.match(/([a-zA-Z0-9].*[!@#$%^&*?_~])|([!@#$%^&*?_~].*[a-zA-Z0-9])/) ? 2 : -1;
141
+ }
142
+
143
+ }];
144
+ export default ((password, rules = DEFAULT_RULES) => {
145
+ const suggestions = [];
146
+ let passwordScore = 0;
147
+ rules.forEach(({
148
+ suggestion,
149
+ score
150
+ }) => {
151
+ const ruleScore = score(password);
152
+
153
+ if (ruleScore < 0 && suggestion) {
154
+ suggestions.push(suggestion);
155
+ } else {
156
+ passwordScore += ruleScore;
157
+ }
158
+ });
159
+ let strength;
160
+
161
+ switch (true) {
162
+ case passwordScore < 16:
163
+ strength = 'VeryWeak';
164
+ break;
165
+
166
+ case passwordScore < 25:
167
+ strength = 'Weak';
168
+ break;
169
+
170
+ case passwordScore < 35:
171
+ strength = 'Medium';
172
+ break;
173
+
174
+ case passwordScore < 45:
175
+ strength = 'Strong';
176
+ break;
177
+
178
+ default:
179
+ strength = 'VeryStrong';
180
+ break;
181
+ }
182
+
183
+ return {
184
+ strength,
185
+ suggestions
186
+ };
187
+ });
@@ -0,0 +1,14 @@
1
+ // Copyright 1999-2022. Plesk International GmbH. All rights reserved.
2
+ const symbolClasses = {
3
+ upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
4
+ lower: 'abcdefghijklmnopqrstuvwxyz',
5
+ number: '0123456789',
6
+ special: '!@#$%^&*?_~'
7
+ };
8
+
9
+ const generatePassword = () => {
10
+ const password = ['upper', 'upper', 'upper', 'lower', 'lower', 'lower', 'lower', 'lower', 'lower', 'lower', 'lower', 'number', 'number', 'number', 'special', 'special'];
11
+ return password.sort((a, b) => Math.floor(b.length * Math.random()) - Math.floor(a.length * Math.random())).map(symbolClass => symbolClasses[symbolClass][Math.floor(symbolClasses[symbolClass].length * Math.random())]).join('');
12
+ };
13
+
14
+ export default generatePassword;
@@ -1,2 +1,3 @@
1
- // Copyright 1999-2017. Plesk International GmbH. All rights reserved.
2
- export { default, generatePassword } from './FormFieldPassword';
1
+ // Copyright 1999-2022. Plesk International GmbH. All rights reserved.
2
+ export { default } from './FormFieldPassword';
3
+ export { default as generatePassword } from './generatePassword';
@@ -73,7 +73,7 @@ const Icon = ({
73
73
  }, props), newName ? /*#__PURE__*/React.createElement("svg", {
74
74
  focusable: "false"
75
75
  }, /*#__PURE__*/React.createElement("use", {
76
- xlinkHref: getHref(newName, newSize)
76
+ href: getHref(newName, newSize)
77
77
  })) : src && /*#__PURE__*/React.createElement("img", {
78
78
  src: src,
79
79
  alt: alt
@@ -1190,7 +1190,7 @@ class List extends Component {
1190
1190
  [`${baseClassName}__table--vertical`]: vertical,
1191
1191
  [`${baseClassName}__table--reorderable`]: reorderable
1192
1192
  })
1193
- }, props, reorderableProps), hasTitle && /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", {
1193
+ }, reorderableProps), hasTitle && /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", {
1194
1194
  className: classNames(`${baseClassName}__table-thead`, {
1195
1195
  [`${baseClassName}__row--expanded`]: this.isAllRowsExpanded(data, this.state.expandedRows)
1196
1196
  })
@@ -131,7 +131,8 @@ class ProgressDialog extends Component {
131
131
  }, props, {
132
132
  isOpen: isOpen,
133
133
  onClose: this.handleClose,
134
- closable: canClose || canCancel
134
+ closable: canClose || canCancel,
135
+ canClose: canClose
135
136
  }), description && /*#__PURE__*/React.createElement("div", {
136
137
  className: `${baseClassName}__description`
137
138
  }, description), /*#__PURE__*/React.createElement(Progress, {