playbook_ui 11.12.1.pre.alpha.charts1 → 11.12.1.pre.alpha.passphrase1
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/index.js +1 -0
- data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.jsx +111 -0
- data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.jsx +151 -0
- data/app/pb_kits/playbook/pb_circle_chart/circle_chart.html.erb +21 -9
- data/app/pb_kits/playbook/pb_circle_chart/circle_chart.rb +47 -7
- data/app/pb_kits/playbook/pb_dashboard/{pbChartsDarkTheme.ts → pbChartsDarkTheme.js} +21 -6
- data/app/pb_kits/playbook/pb_dashboard/{pbChartsLightTheme.ts → pbChartsLightTheme.js} +21 -6
- data/app/pb_kits/playbook/pb_gauge/_gauge.jsx +112 -0
- data/app/pb_kits/playbook/pb_gauge/_gauge.scss +0 -4
- data/app/pb_kits/playbook/pb_gauge/docs/_gauge_complex.html.erb +1 -1
- data/app/pb_kits/playbook/pb_gauge/docs/_gauge_complex.jsx +8 -8
- data/app/pb_kits/playbook/pb_gauge/gauge.html.erb +11 -1
- data/app/pb_kits/playbook/pb_gauge/gauge.rb +8 -3
- data/app/pb_kits/playbook/pb_line_graph/_line_graph.jsx +113 -0
- data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +56 -97
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb +145 -1
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.jsx +127 -3
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.md +11 -2
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.html.erb +136 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +90 -8
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.md +5 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.html.erb +51 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.jsx +39 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +0 -2
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +6 -20
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +2 -2
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +1 -1
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +318 -5
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +134 -48
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +11 -5
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.html.erb +123 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +96 -20
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +6 -2
- data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -1
- data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +5 -9
- data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +0 -47
- data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.jsx +79 -0
- data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_tooltip.jsx +1 -1
- data/app/pb_kits/playbook/playbook-rails-react-bindings.js +0 -4
- data/app/pb_kits/playbook/playbook-rails.js +4 -0
- data/app/pb_kits/playbook/plugins/pb_chart.js +322 -0
- data/lib/playbook/version.rb +1 -1
- metadata +15 -16
- data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +0 -145
- data/app/pb_kits/playbook/pb_circle_chart/ChartsTypes.ts +0 -2
- data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +0 -216
- data/app/pb_kits/playbook/pb_dashboard/pbChartsColorsHelper.ts +0 -16
- data/app/pb_kits/playbook/pb_dashboard/themeTypes.ts +0 -16
- data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +0 -213
- data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +0 -148
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +0 -1
- data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +0 -55
- data/app/pb_kits/playbook/pb_passphrase/useHaveIBeenPwned.js +0 -52
- data/app/pb_kits/playbook/pb_passphrase/useZxcvbn.js +0 -58
- data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +0 -111
@@ -1,10 +1,323 @@
|
|
1
|
+
<%= pb_rails("passphrase", props: { label: "Default Settings", classname: "def_passphrase" }) %>
|
1
2
|
|
2
|
-
<%= pb_rails("
|
3
|
+
<%= pb_rails("progress_simple", props: { percent: 0, id: "def_bar" }) %>
|
3
4
|
|
4
|
-
<%= pb_rails("
|
5
|
+
<%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "def_caption" }) %>
|
5
6
|
|
6
|
-
<%= pb_rails("
|
7
|
+
<%= pb_rails("text_input", props: { label: "Calculated Strength", value: "0", disabled: true, id: "calc_strength" }) %>
|
7
8
|
|
8
|
-
<%= pb_rails("passphrase", props: {
|
9
|
+
<%= pb_rails("passphrase", props: { label: "Min length = 5", classname: "min_5" }) %>
|
9
10
|
|
10
|
-
<%= pb_rails("
|
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 '
|
4
|
-
import
|
5
|
-
|
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
|
-
|
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
|
-
{
|
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="
|
45
|
-
minLength={30}
|
119
|
+
label={"Type your passphrase"}
|
46
120
|
onChange={handleChange}
|
47
121
|
value={input}
|
48
122
|
{...props}
|
49
123
|
/>
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 %>
|