playbook_ui 11.12.0 → 11.12.1.pre.alpha.passphrase1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/_button.scss +1 -1
  3. data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +56 -97
  4. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb +145 -1
  5. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.jsx +127 -3
  6. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.md +11 -2
  7. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.html.erb +136 -0
  8. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +90 -8
  9. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.md +5 -0
  10. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.html.erb +51 -0
  11. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.jsx +39 -0
  12. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +0 -2
  13. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +6 -20
  14. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +2 -2
  15. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +1 -1
  16. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +318 -5
  17. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +134 -48
  18. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +11 -5
  19. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.html.erb +123 -0
  20. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +96 -20
  21. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +6 -2
  22. data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +4 -0
  23. data/app/pb_kits/playbook/pb_passphrase/docs/index.js +1 -0
  24. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -1
  25. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +5 -9
  26. data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +0 -47
  27. data/lib/playbook/version.rb +2 -2
  28. metadata +9 -8
  29. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +0 -1
  30. data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +0 -55
  31. data/app/pb_kits/playbook/pb_passphrase/useHaveIBeenPwned.js +0 -52
  32. data/app/pb_kits/playbook/pb_passphrase/useZxcvbn.js +0 -58
@@ -1,10 +1,323 @@
1
+ <%= pb_rails("passphrase", props: { label: "Default Settings", classname: "def_passphrase" }) %>
1
2
 
2
- <%= pb_rails("passphrase", props: { label: "Default Settings"}) %>
3
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "def_bar" }) %>
3
4
 
4
- <%= pb_rails("passphrase", props: { label: "Min length = 5", min_length: 5}) %>
5
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "def_caption" }) %>
5
6
 
6
- <%= pb_rails("passphrase", props: { label: "Min length = 30", min_length: 30}) %>
7
+ <%= pb_rails("text_input", props: { label: "Calculated Strength", value: "0", disabled: true, id: "calc_strength" }) %>
7
8
 
8
- <%= pb_rails("passphrase", props: { average_threshold: 1, label: "Average Threshold = 1"}) %>
9
+ <%= pb_rails("passphrase", props: { label: "Min length = 5", classname: "min_5" }) %>
9
10
 
10
- <%= pb_rails("passphrase", props: { label: "Strong Threshold = 4", strong_threshold: 4}) %>
11
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "min_5_bar" }) %>
12
+
13
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "min_5_caption" }) %>
14
+
15
+ <%= pb_rails("passphrase", props: { label: "Min length = 30", classname: "min_30" }) %>
16
+
17
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "min_30_bar" }) %>
18
+
19
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "min_30_caption" }) %>
20
+
21
+ <%= pb_rails("passphrase", props: { label: "Average Threshold = 1", classname: "avg_1" }) %>
22
+
23
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "avg_1_bar" }) %>
24
+
25
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "avg_1_caption" }) %>
26
+
27
+ <%= pb_rails("passphrase", props: { label: "Strong Threshold = 4", classname: "strong_4" }) %>
28
+
29
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "strong_4_bar" }) %>
30
+
31
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "strong_4_caption" }) %>
32
+
33
+
34
+
35
+ <%= javascript_tag do %>
36
+ window.addEventListener("DOMContentLoaded", () => {
37
+
38
+
39
+ // variables for the passphrase kits you are targeting
40
+ const defPassphrase = document.querySelector(".def_passphrase").querySelector("input")
41
+ const min5 = document.querySelector(".min_5").querySelector("input")
42
+ const min30 = document.querySelector(".min_30").querySelector("input")
43
+ const avg1 = document.querySelector(".avg_1").querySelector("input")
44
+ const strong4 = document.querySelector(".strong_4").querySelector("input")
45
+
46
+ // variable for the text_input kit you are targeting
47
+ const calcStrength = document.querySelector("#calc_strength")
48
+
49
+ // variables for the progress_simple kits you are targeting
50
+ const defBarVariant = document.getElementById("def_bar")
51
+ const defBarPercent = document.getElementById("def_bar").querySelector("div")
52
+ const min5BarVariant = document.getElementById("min_5_bar")
53
+ const min5BarPercent = document.getElementById("min_5_bar").querySelector("div")
54
+ const min30BarVariant = document.getElementById("min_30_bar")
55
+ const min30BarPercent = document.getElementById("min_30_bar").querySelector("div")
56
+ const avg1BarVariant = document.getElementById("avg_1_bar")
57
+ const avg1BarPercent = document.getElementById("avg_1_bar").querySelector("div")
58
+ const strong4BarVariant = document.getElementById("strong_4_bar")
59
+ const strong4BarPercent = document.getElementById("strong_4_bar").querySelector("div")
60
+
61
+ // hide all the progress_simple bars
62
+ defBarVariant.style.display = 'none';
63
+ defBarPercent.style.display = 'none';
64
+ min5BarVariant.style.display = 'none';
65
+ min5BarPercent.style.display = 'none';
66
+ min30BarVariant.style.display = 'none';
67
+ min30BarPercent.style.display = 'none';
68
+ avg1BarVariant.style.display = 'none';
69
+ avg1BarPercent.style.display = 'none';
70
+ strong4BarVariant.style.display = 'none';
71
+ strong4BarPercent.style.display = 'none';
72
+
73
+ // variables for the caption kits you are targeting
74
+ const defCaption = document.getElementById("def_caption")
75
+ const min5Caption = document.getElementById("min_5_caption")
76
+ const min30Caption = document.getElementById("min_30_caption")
77
+ const avg1Caption = document.getElementById("avg_1_caption")
78
+ const strong4Caption = document.getElementById("strong_4_caption")
79
+
80
+ // hide all the captions
81
+ defCaption.style.display = 'none';
82
+ min5Caption.style.display = 'none';
83
+ min30Caption.style.display = 'none';
84
+ avg1Caption.style.display = 'none';
85
+ strong4Caption.style.display = 'none';
86
+
87
+ // funtion that determines strenght of user passowrd using zxcvbn
88
+ const handleStrengthCalculation = (settings) => {
89
+
90
+ // define the settings object with its defaults
91
+ const {
92
+ passphrase = "",
93
+ common = false,
94
+ isPwned = false,
95
+ averageThreshold = 2,
96
+ minLength = 12,
97
+ strongThreshold = 3,
98
+ } = settings
99
+
100
+ // define the resultsByScore objects, these return an object with a variant and percentage,
101
+ // depending on the score of the password
102
+ const resultByScore = {
103
+ 0: {
104
+ variant: 'negative',
105
+ label: '',
106
+ percent: 0,
107
+ },
108
+ 1: {
109
+ variant: 'negative',
110
+ label: 'This passphrase is too common',
111
+ percent: 25,
112
+ },
113
+ 2: {
114
+ variant: 'negative',
115
+ label: 'Too weak',
116
+ percent: 25,
117
+ },
118
+ 3: {
119
+ variant: 'warning',
120
+ label: 'Almost there, keep going!',
121
+ percent: 50,
122
+ },
123
+ 4: {
124
+ variant: 'positive',
125
+ label: 'Success! Strong passphrase',
126
+ percent: 100,
127
+ }
128
+ }
129
+
130
+ const { score } = zxcvbn(passphrase);
131
+
132
+ const noPassphrase = passphrase.length <= 0
133
+ const commonPassphrase = common || isPwned
134
+ const weakPassphrase = passphrase.length < minLength || score < averageThreshold
135
+ const averagePassphrase = score < strongThreshold
136
+ const strongPassphrase = score >= strongThreshold
137
+
138
+ // conditional that returns the score of the password, along with the resultByScore object
139
+ // so we can change the percantage and variant of the progress_simple kit
140
+ if (noPassphrase) {
141
+ return {...resultByScore[0], score}
142
+ } else if (commonPassphrase) {
143
+ return {...resultByScore[1], score}
144
+ } else if (weakPassphrase) {
145
+ return {...resultByScore[2], score}
146
+ } else if (averagePassphrase){
147
+ return {...resultByScore[3], score}
148
+ } else if (strongPassphrase) {
149
+ return {...resultByScore[4], score}
150
+ }
151
+ }
152
+
153
+
154
+ // event listeners attached to the input field
155
+ min5.addEventListener('input', (e) => {
156
+ const passphrase = e.target.value;
157
+
158
+ // defining setting object to spread into handleStrengthCalculation
159
+ setting = {
160
+ minLength: 5,
161
+ }
162
+
163
+ // pass in passphrase and setting object to handleStrengthCalculation and set that equal to result variable
164
+ const result = handleStrengthCalculation({passphrase, ...setting})
165
+
166
+ // set the value of the text_input to the score
167
+ calcStrength.value = result.score
168
+
169
+ // conditional statment to show or hide progress_simple bar and caption if user has entered a password
170
+ if (passphrase) {
171
+ min5BarVariant.style.display = 'block';
172
+
173
+ min5BarPercent.style.display = 'block';
174
+
175
+ min5Caption.style.display = 'block';
176
+ } else {
177
+ min5BarVariant.style.display = 'none';
178
+
179
+ min5BarPercent.style.display = 'none';
180
+
181
+ min5Caption.style.display = 'none';
182
+ }
183
+
184
+ // set the width of the progress_simple kit
185
+ min5BarPercent.style.width = result.percent.toString()+ "%"
186
+
187
+
188
+ // set the variant of the progress_simple kit
189
+ min5BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
190
+
191
+
192
+ // set the text of the caption kit
193
+ min5Caption.textContent = result.label
194
+ });
195
+
196
+ defPassphrase.addEventListener('input', (e) => {
197
+ const passphrase = e.target.value;
198
+
199
+ const result = handleStrengthCalculation({passphrase})
200
+
201
+ calcStrength.value = result.score
202
+
203
+ if (passphrase) {
204
+ defBarVariant.style.display = 'block';
205
+
206
+ defBarPercent.style.display = 'block';
207
+
208
+ defCaption.style.display = 'block';
209
+ } else {
210
+ defBarVariant.style.display = 'none';
211
+
212
+ defBarPercent.style.display = 'none';
213
+
214
+ defCaption.style.display = 'none';
215
+ }
216
+
217
+ defBarPercent.style.width = result.percent.toString()+ "%"
218
+
219
+ defBarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
220
+
221
+ defCaption.textContent = result.label
222
+
223
+ });
224
+
225
+ min30.addEventListener('input', (e) => {
226
+ const passphrase = e.target.value;
227
+
228
+ setting = {
229
+ minLength: 30,
230
+ }
231
+
232
+ const result = handleStrengthCalculation({passphrase, ...setting})
233
+
234
+ calcStrength.value = result.score
235
+
236
+ if (passphrase) {
237
+ min30BarVariant.style.display = 'block';
238
+
239
+ min30BarPercent.style.display = 'block';
240
+
241
+ min30Caption.style.display = 'block';
242
+ } else {
243
+ min30BarVariant.style.display = 'none';
244
+
245
+ min30BarPercent.style.display = 'none';
246
+
247
+ min30Caption.style.display = 'none';
248
+ }
249
+
250
+ min30BarPercent.style.width = result.percent.toString()+ "%"
251
+
252
+ min30BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
253
+
254
+ min30Caption.textContent = result.label
255
+ });
256
+
257
+ avg1.addEventListener('input', (e) => {
258
+ const passphrase = e.target.value;
259
+
260
+ setting = {
261
+ averageThreshold: 1,
262
+ }
263
+
264
+ const result = handleStrengthCalculation({passphrase, ...setting})
265
+
266
+ calcStrength.value = result.score
267
+
268
+ if (passphrase) {
269
+ avg1BarVariant.style.display = 'block';
270
+
271
+ avg1BarPercent.style.display = 'block';
272
+
273
+ avg1Caption.style.display = 'block';
274
+ } else {
275
+ avg1BarVariant.style.display = 'none';
276
+
277
+ avg1BarPercent.style.display = 'none';
278
+
279
+ avg1Caption.style.display = 'none';
280
+ }
281
+
282
+ avg1BarPercent.style.width = result.percent.toString()+ "%"
283
+
284
+ avg1BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
285
+
286
+ avg1Caption.textContent = result.label
287
+ });
288
+
289
+ strong4.addEventListener('input', (e) => {
290
+ const passphrase = e.target.value;
291
+
292
+ setting = {
293
+ strongThreshold: 4,
294
+ }
295
+
296
+ const result = handleStrengthCalculation({passphrase, ...setting})
297
+
298
+ calcStrength.value = result.score
299
+
300
+ if (passphrase) {
301
+ strong4BarVariant.style.display = 'block';
302
+
303
+ strong4BarPercent.style.display = 'block';
304
+
305
+ strong4Caption.style.display = 'block';
306
+ } else {
307
+ strong4BarVariant.style.display = 'none';
308
+
309
+ strong4BarPercent.style.display = 'none';
310
+
311
+ strong4Caption.style.display = 'none';
312
+ }
313
+
314
+ strong4BarPercent.style.width = result.percent.toString()+ "%"
315
+
316
+ strong4BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
317
+
318
+ strong4Caption.textContent = result.label
319
+ });
320
+
321
+
322
+ })
323
+ <% end %>
@@ -1,71 +1,157 @@
1
1
  import React, { useState } from 'react'
2
2
 
3
- import Body from '../../pb_body/_body'
4
- import Passphrase from '../../pb_passphrase/_passphrase'
5
- import TextInput from '../../pb_text_input/_text_input'
3
+ import { Body, Caption, Passphrase, ProgressSimple, TextInput } from '../..'
4
+ import zxcvbn from 'zxcvbn'
5
+
6
6
 
7
7
  const PassphraseMeterSettings = (props) => {
8
8
  const [input, setInput] = useState('')
9
+ const [result, setResult] = useState({})
10
+ const [calculatedStrength, setCalculatedStrength] = useState(0)
11
+
12
+ const meterSettings = [
13
+ {
14
+ label: "Default settings"
15
+ },
16
+ {
17
+ minLength: 5,
18
+ label: "Min length = 5",
19
+ },
20
+ {
21
+ minLength: 30,
22
+ label: "Min length = 30",
23
+ },
24
+ {
25
+ label: "Average threshold = 1",
26
+ averageThreshold: 1,
27
+ },
28
+ {
29
+ label: "Strong Threshold = 4",
30
+ strongThreshold: 4,
31
+ },
32
+ ]
33
+
34
+ const handleStrengthCalculation = (settings) => {
35
+ const {
36
+ passphrase = "",
37
+ common = false,
38
+ isPwned = false,
39
+ averageThreshold = 2,
40
+ minLength = 12,
41
+ strongThreshold = 3,
42
+ } = settings
43
+
44
+ const resultByScore = {
45
+ 0: {
46
+ variant: 'negative',
47
+ label: '',
48
+ percent: 0,
49
+ },
50
+ 1: {
51
+ variant: 'negative',
52
+ label: 'This passphrase is too common',
53
+ percent: 25,
54
+ },
55
+ 2: {
56
+ variant: 'negative',
57
+ label: 'Too weak',
58
+ percent: 25,
59
+ },
60
+ 3: {
61
+ variant: 'warning',
62
+ label: 'Almost there, keep going!',
63
+ percent: 50,
64
+ },
65
+ 4: {
66
+ variant: 'positive',
67
+ label: 'Success! Strong passphrase',
68
+ percent: 100,
69
+ }
70
+ }
71
+
72
+ const { score } = zxcvbn(passphrase);
73
+
74
+ const noPassphrase = passphrase.length <= 0
75
+ const commonPassphrase = common || isPwned
76
+ const weakPassphrase = passphrase.length < minLength || score < averageThreshold
77
+ const averagePassphrase = score < strongThreshold
78
+ const strongPassphrase = score >= strongThreshold
79
+
80
+ if (noPassphrase) {
81
+ return {...resultByScore[0], score}
82
+ } else if (commonPassphrase) {
83
+ return {...resultByScore[1], score}
84
+ } else if (weakPassphrase) {
85
+ return {...resultByScore[2], score}
86
+ } else if (averagePassphrase){
87
+ return {...resultByScore[3], score}
88
+ } else if (strongPassphrase) {
89
+ return {...resultByScore[4], score}
90
+ }
91
+ }
9
92
 
10
- const handleChange = (e) => setInput(e.target.value)
93
+
94
+ const handleChange = (e) => {
95
+ const passphrase = e.target.value;
96
+
97
+ setInput(passphrase)
98
+
99
+ const calculated = []
100
+
101
+ meterSettings.forEach((setting, index) => {
102
+ const results = handleStrengthCalculation({passphrase, ...setting})
103
+ if (index == 0) setCalculatedStrength(results.score)
104
+ calculated.push(results)
105
+ })
106
+
107
+ setResult(calculated)
108
+ }
11
109
 
12
- const [strength, setStrength] = useState(0)
13
- const handleStrengthChange = (str) => setStrength(str)
14
110
  return (
15
111
  <>
16
112
  <div>
17
113
  <Body>
18
- {'These examples will all share the same input value. Type in any of the inputs to see how the strength meter changes in response to different settings.'}
114
+ {
115
+ "These examples will all share the same input value. Type in any of the inputs to see how the strength meter changes in response to different settings."
116
+ }
19
117
  </Body>
20
- <br />
21
- <TextInput
22
- disabled
23
- label="Calculated Strength"
24
- readOnly
25
- value={strength}
26
- />
27
-
28
- <Passphrase
29
- label="Default settings"
30
- onChange={handleChange}
31
- onStrengthChange={handleStrengthChange}
32
- value={input}
33
- {...props}
34
- />
35
-
36
- <Passphrase
37
- label="Min length = 5"
38
- minLength={5}
39
- onChange={handleChange}
40
- value={input}
41
- {...props}
42
- />
43
118
  <Passphrase
44
- label="Min length = 30"
45
- minLength={30}
119
+ label={"Type your passphrase"}
46
120
  onChange={handleChange}
47
121
  value={input}
48
122
  {...props}
49
123
  />
50
-
51
- <Passphrase
52
- averageThreshold={1}
53
- label="Average threshold = 1"
54
- onChange={handleChange}
55
- value={input}
56
- {...props}
57
- />
58
-
59
- <Passphrase
60
- label="Strong Threshold = 4"
61
- onChange={handleChange}
62
- strongThreshold={4}
63
- value={input}
64
- {...props}
124
+ <TextInput
125
+ disabled
126
+ label="Calculated Strength"
127
+ readOnly
128
+ value={calculatedStrength}
65
129
  />
130
+ {meterSettings.map((settings, index) => (
131
+ <div key={index}>
132
+ <Passphrase
133
+ label={settings.label}
134
+ onChange={handleChange}
135
+ value={input}
136
+ {...props}
137
+ />
138
+ {input.length > 0 && (
139
+ <>
140
+ <ProgressSimple
141
+ percent={result[index].percent}
142
+ variant={result[index].variant}
143
+ />
144
+ <Caption size='xs'
145
+ text={result[index].label}
146
+ />
147
+ </>
148
+ )}
149
+ </div>
150
+ ))}
151
+
66
152
  </div>
67
153
  </>
68
- )
154
+ );
69
155
  }
70
156
 
71
157
  export default PassphraseMeterSettings
@@ -1,9 +1,15 @@
1
- By default, the minimum length is 12 and the strength meter will show a strength of 1 if not met. Notice the bar won't change from red until the minimum is met
2
- Use the `minLength` prop to adjust.
1
+ This example shows how to enhance the passphrase strenght by setting diferent thresholds and lengths.
3
2
 
3
+ The `meterSettings` array contains different settings for each rendered input. The `handleStrengthCalculation` handles the strength calculation using those settings, showing different results for the same `passphrase` input.
4
4
 
5
- The meter also response to `averageThreshold` and `strongTreshold` props. `averageThresold` defaults to 2, and `strongThreshold` defaults to 3.
6
- This means that the bar will turn yellow when the strength of the passphrase is calculated to be 2 on a 0-4 scale, and green when 3.
5
+ By default, `minLength` is 12. Try typing any value in the `Default Example` input. Notice that the bar won't change from red until the minimum is met.
7
6
 
8
7
  Adjust these props to tune the sensitivity of the bar.
9
- Note: minimum length trumps strength and will set the bar to a red color, despite whatever strength is calculated.
8
+
9
+ Note: minimum length trumps strength and will set the bar to a red color, despite whatever strength is calculated.
10
+
11
+ <div class="pb_pill_kit_warning"><div class="pb_title_kit_size_4 pb_pill_text">Disclaimer</div></div>
12
+
13
+ This example depends on the `zxcvbn` library.
14
+
15
+ You can use any library to achieve the same result, this example only intends to show how to add more features to the `Passphrase` kit.
@@ -0,0 +1,123 @@
1
+ <%= pb_rails("passphrase", props: { label: "Passphrase", classname: "passphrase_change" }) %>
2
+
3
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "bar_change" }) %>
4
+
5
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "caption_change" }) %>
6
+
7
+ <%= pb_rails("text_input", props: { label: "Passphrase Strength", value: "0", disabled: true, id: "calc_strength_change" }) %>
8
+
9
+
10
+ <%= javascript_tag do %>
11
+ window.addEventListener("DOMContentLoaded", () => {
12
+
13
+ // variables for the kits you are targeting
14
+ const passphrase = document.querySelector(".passphrase_change").querySelector("input")
15
+ const calcStrength = document.querySelector("#calc_strength_change")
16
+ const barVariant = document.getElementById("bar_change")
17
+ const barPercent = document.getElementById("bar_change").querySelector("div")
18
+ const caption = document.getElementById("caption_change")
19
+
20
+ // hide the bar and captions
21
+ barVariant.style.display = 'none';
22
+ barPercent.style.display = 'none';
23
+ caption.style.display = 'none';
24
+
25
+
26
+ const handleStrengthCalculation = (settings) => {
27
+ const {
28
+ passphrase = "",
29
+ common = false,
30
+ isPwned = false,
31
+ averageThreshold = 2,
32
+ minLength = 12,
33
+ strongThreshold = 3,
34
+ } = settings
35
+
36
+ const resultByScore = {
37
+ 0: {
38
+ variant: 'negative',
39
+ label: '',
40
+ percent: 0,
41
+ },
42
+ 1: {
43
+ variant: 'negative',
44
+ label: 'This passphrase is too common',
45
+ percent: 25,
46
+ },
47
+ 2: {
48
+ variant: 'negative',
49
+ label: 'Too weak',
50
+ percent: 25,
51
+ },
52
+ 3: {
53
+ variant: 'warning',
54
+ label: 'Almost there, keep going!',
55
+ percent: 50,
56
+ },
57
+ 4: {
58
+ variant: 'positive',
59
+ label: 'Success! Strong passphrase',
60
+ percent: 100,
61
+ }
62
+ }
63
+
64
+ const { score } = zxcvbn(passphrase);
65
+
66
+ const noPassphrase = passphrase.length <= 0
67
+ const commonPassphrase = common || isPwned
68
+ const weakPassphrase = passphrase.length < minLength || score < averageThreshold
69
+ const averagePassphrase = score < strongThreshold
70
+ const strongPassphrase = score >= strongThreshold
71
+
72
+ if (noPassphrase) {
73
+ return {...resultByScore[0], score}
74
+ } else if (commonPassphrase) {
75
+ return {...resultByScore[1], score}
76
+ } else if (weakPassphrase) {
77
+ return {...resultByScore[2], score}
78
+ } else if (averagePassphrase){
79
+ return {...resultByScore[3], score}
80
+ } else if (strongPassphrase) {
81
+ return {...resultByScore[4], score}
82
+ }
83
+ }
84
+
85
+ // event listeners attached to the input field
86
+ passphrase.addEventListener('input', (e) => {
87
+ const passphrase = e.target.value;
88
+
89
+ // pass in passphrase to the handleStrengthCalculation and set that equal to result variable
90
+ const result = handleStrengthCalculation({passphrase: passphrase})
91
+
92
+ // set the value of the text_input to the score
93
+ calcStrength.value = result.score
94
+
95
+ // conditional statment to show or hide progress_simple bar and caption if user has entered a password
96
+ if (passphrase) {
97
+ barVariant.style.display = 'block';
98
+
99
+ barPercent.style.display = 'block';
100
+
101
+ caption.style.display = 'block';
102
+ } else {
103
+ barVariant.style.display = 'none';
104
+
105
+ barPercent.style.display = 'none';
106
+
107
+ caption.style.display = 'none';
108
+ }
109
+
110
+ // set the width of the progress_simple kit
111
+ barPercent.style.width = result.percent.toString()+ "%"
112
+
113
+
114
+ // set the variant of the progress_simple kit
115
+ barVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
116
+
117
+
118
+ // set the text of the caption kit
119
+ caption.textContent = result.label
120
+ });
121
+
122
+ })
123
+ <% end %>