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,34 +1,110 @@
|
|
1
1
|
import React, { useState } from 'react'
|
2
|
+
import { useEffect } from 'react'
|
2
3
|
|
3
|
-
import Passphrase from '
|
4
|
-
|
5
|
-
import TextInput from '../../pb_text_input/_text_input'
|
4
|
+
import { Caption, Passphrase, ProgressSimple, TextInput} from '../..'
|
5
|
+
import zxcvbn from 'zxcvbn'
|
6
6
|
|
7
7
|
const PassphraseStrengthChange = (props) => {
|
8
8
|
const [input, setInput] = useState('')
|
9
|
+
const [checkStrength, setCheckStrength] = useState({
|
10
|
+
label: '',
|
11
|
+
percent: 0,
|
12
|
+
score: 0,
|
13
|
+
variant: ''
|
14
|
+
})
|
9
15
|
|
10
16
|
const handleChange = (e) => setInput(e.target.value)
|
11
17
|
|
12
|
-
const
|
13
|
-
|
18
|
+
const handleStrengthCalculation = (settings) => {
|
19
|
+
const {
|
20
|
+
passphrase = "",
|
21
|
+
common = false,
|
22
|
+
isPwned = false,
|
23
|
+
averageThreshold = 2,
|
24
|
+
minLength = 12,
|
25
|
+
strongThreshold = 3,
|
26
|
+
} = settings
|
27
|
+
|
28
|
+
const resultByScore = {
|
29
|
+
0: {
|
30
|
+
variant: 'negative',
|
31
|
+
label: '',
|
32
|
+
percent: 0,
|
33
|
+
},
|
34
|
+
1: {
|
35
|
+
variant: 'negative',
|
36
|
+
label: 'This passphrase is too common',
|
37
|
+
percent: 25,
|
38
|
+
},
|
39
|
+
2: {
|
40
|
+
variant: 'negative',
|
41
|
+
label: 'Too weak',
|
42
|
+
percent: 25,
|
43
|
+
},
|
44
|
+
3: {
|
45
|
+
variant: 'warning',
|
46
|
+
label: 'Almost there, keep going!',
|
47
|
+
percent: 50,
|
48
|
+
},
|
49
|
+
4: {
|
50
|
+
variant: 'positive',
|
51
|
+
label: 'Success! Strong passphrase',
|
52
|
+
percent: 100,
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
const { score } = zxcvbn(passphrase);
|
57
|
+
|
58
|
+
const noPassphrase = passphrase.length <= 0
|
59
|
+
const commonPassphrase = common || isPwned
|
60
|
+
const weakPassphrase = passphrase.length < minLength || score < averageThreshold
|
61
|
+
const averagePassphrase = score < strongThreshold
|
62
|
+
const strongPassphrase = score >= strongThreshold
|
63
|
+
|
64
|
+
if (noPassphrase) {
|
65
|
+
return {...resultByScore[0], score}
|
66
|
+
} else if (commonPassphrase) {
|
67
|
+
return {...resultByScore[1], score}
|
68
|
+
} else if (weakPassphrase) {
|
69
|
+
return {...resultByScore[2], score}
|
70
|
+
} else if (averagePassphrase){
|
71
|
+
return {...resultByScore[3], score}
|
72
|
+
} else if (strongPassphrase) {
|
73
|
+
return {...resultByScore[4], score}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
useEffect(() => {
|
78
|
+
const result = handleStrengthCalculation({ passphrase: input })
|
79
|
+
setCheckStrength({...result})
|
80
|
+
},[input])
|
14
81
|
|
15
82
|
return (
|
16
83
|
<>
|
17
|
-
<
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
84
|
+
<Passphrase
|
85
|
+
label="Passphrase"
|
86
|
+
onChange={handleChange}
|
87
|
+
value={input}
|
88
|
+
{...props}
|
89
|
+
/>
|
90
|
+
{input.length > 0 && (
|
91
|
+
<>
|
92
|
+
<ProgressSimple
|
93
|
+
percent={checkStrength.percent}
|
94
|
+
variant={checkStrength.variant}
|
95
|
+
/>
|
96
|
+
<Caption size='xs'
|
97
|
+
text={checkStrength.label}
|
98
|
+
/>
|
99
|
+
</>
|
100
|
+
)}
|
101
|
+
<TextInput
|
102
|
+
disabled
|
103
|
+
label="Passphrase Strength"
|
104
|
+
marginTop="xl"
|
105
|
+
readOnly
|
106
|
+
value={checkStrength.score}
|
107
|
+
/>
|
32
108
|
</>
|
33
109
|
)
|
34
110
|
}
|
@@ -1,3 +1,7 @@
|
|
1
|
-
|
1
|
+
Strength is calculated on a 0-4 scale by the <a href="https://github.com/dropbox/zxcvbn" target="_blank"> Zxcvbn package</a>.
|
2
2
|
|
3
|
-
|
3
|
+
<div class="pb_pill_kit_warning"><div class="pb_title_kit_size_4 pb_pill_text">Disclaimer</div></div>
|
4
|
+
|
5
|
+
This example depends on the `zxcvbn` library.
|
6
|
+
|
7
|
+
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.
|
@@ -2,13 +2,17 @@ examples:
|
|
2
2
|
|
3
3
|
rails:
|
4
4
|
- passphrase_default: Default
|
5
|
+
- passphrase_confirmation: Confirmation
|
5
6
|
- passphrase_meter_settings: Meter Settings
|
6
7
|
- passphrase_input_props: Input Props
|
7
8
|
- passphrase_tips: Tips
|
9
|
+
- passphrase_strength_change: Strength Change
|
10
|
+
- passphrase_common: Common Passphrases
|
8
11
|
- passphrase_breached: Breached Passphrases
|
9
12
|
|
10
13
|
react:
|
11
14
|
- passphrase_default: Default
|
15
|
+
- passphrase_confirmation: Confirmation
|
12
16
|
- passphrase_meter_settings: Meter Settings
|
13
17
|
- passphrase_input_props: Input Props
|
14
18
|
- passphrase_tips: Tips
|
@@ -1,4 +1,5 @@
|
|
1
1
|
export { default as PassphraseDefault } from './_passphrase_default.jsx'
|
2
|
+
export { default as PassphraseConfirmation } from './_passphrase_confirmation.jsx'
|
2
3
|
export { default as PassphraseMeterSettings } from './_passphrase_meter_settings'
|
3
4
|
export { default as PassphraseInputProps } from './_passphrase_input_props'
|
4
5
|
export { default as PassphraseTips } from './_passphrase_tips'
|
@@ -1 +1 @@
|
|
1
|
-
<%= react_component('Passphrase', object.passphrase_options) %>
|
1
|
+
<%= react_component('Passphrase', object.passphrase_options, class: object.classname,) %>
|
@@ -3,15 +3,14 @@
|
|
3
3
|
module Playbook
|
4
4
|
module PbPassphrase
|
5
5
|
class Passphrase < Playbook::KitBase
|
6
|
-
prop :average_threshold
|
7
|
-
prop :check_pwned
|
8
6
|
prop :confirmation, type: Playbook::Props::Boolean, default: false
|
9
7
|
prop :input_props, type: Playbook::Props::Hash, default: {}
|
10
8
|
prop :label
|
11
|
-
prop :
|
12
|
-
|
13
|
-
|
9
|
+
prop :show_tips_below, type: Playbook::Props::Enum,
|
10
|
+
values: %w[always xs sm md lg xl],
|
11
|
+
default: "always"
|
14
12
|
prop :tips, type: Playbook::Props::Array, default: []
|
13
|
+
prop :value, type: Playbook::Props::String
|
15
14
|
|
16
15
|
def classname
|
17
16
|
generate_classname("pb_passphrase")
|
@@ -19,18 +18,15 @@ module Playbook
|
|
19
18
|
|
20
19
|
def passphrase_options
|
21
20
|
{
|
22
|
-
checkPwned: check_pwned,
|
23
21
|
dark: dark,
|
24
22
|
id: id,
|
25
|
-
averageThreshold: average_threshold,
|
26
23
|
confirmation: confirmation,
|
27
24
|
inputProps: input_props,
|
28
25
|
label: label,
|
29
|
-
minLength: min_length,
|
30
26
|
showTipsBelow: show_tips_below,
|
31
|
-
strongThreshold: strong_threshold,
|
32
27
|
tips: tips,
|
33
28
|
uncontrolled: true,
|
29
|
+
value: value,
|
34
30
|
}.compact
|
35
31
|
end
|
36
32
|
end
|
@@ -64,41 +64,6 @@ test('passes input props to input element', () => {
|
|
64
64
|
expect(input).toBeDisabled()
|
65
65
|
})
|
66
66
|
|
67
|
-
test('progress bar is invisible when value is empty', () => {
|
68
|
-
render(
|
69
|
-
<Passphrase
|
70
|
-
data={{ testid: testId }}
|
71
|
-
/>
|
72
|
-
)
|
73
|
-
|
74
|
-
const kit = screen.getByTestId(testId)
|
75
|
-
expect(kit.querySelector('[class^=pb_progress_simple_wrapper]')).toHaveClass('progress-empty-input')
|
76
|
-
})
|
77
|
-
|
78
|
-
test('progress bar is visible when value is not empty', () => {
|
79
|
-
render(
|
80
|
-
<Passphrase
|
81
|
-
data={{ testid: testId }}
|
82
|
-
value="test_password_input"
|
83
|
-
/>
|
84
|
-
)
|
85
|
-
|
86
|
-
const kit = screen.getByTestId(testId)
|
87
|
-
expect(kit.querySelector('[class^=pb_progress_simple_wrapper]')).not.toHaveClass('progress-empty-input')
|
88
|
-
})
|
89
|
-
|
90
|
-
test('no progress bar is show when confirmation is true', () => {
|
91
|
-
render(
|
92
|
-
<Passphrase
|
93
|
-
confirmation
|
94
|
-
data={{ testid: testId }}
|
95
|
-
/>
|
96
|
-
)
|
97
|
-
|
98
|
-
const kit = screen.getByTestId(testId)
|
99
|
-
expect(kit.querySelector('[class^=pb_progress_simple_wrapper]')).toBeNull()
|
100
|
-
})
|
101
|
-
|
102
67
|
test('popover target shows when tips are given', () => {
|
103
68
|
render(
|
104
69
|
<Passphrase
|
@@ -121,15 +86,3 @@ test('popover target does not show when tips are not given', () => {
|
|
121
86
|
const kit = screen.getByTestId(testId)
|
122
87
|
expect(kit.querySelector('[class^=pb_popover_reference_wrapper]')).toBeNull()
|
123
88
|
})
|
124
|
-
|
125
|
-
test('data-strength attribute exposes strength of password', () => {
|
126
|
-
render(
|
127
|
-
<Passphrase
|
128
|
-
data={{ testid: testId }}
|
129
|
-
value="correct horse battery staple"
|
130
|
-
/>
|
131
|
-
)
|
132
|
-
|
133
|
-
const kit = screen.getByTestId(testId)
|
134
|
-
expect(parseInt(kit.getAttribute('data-strength'))).toBeGreaterThan(0)
|
135
|
-
})
|
@@ -0,0 +1,79 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React from 'react'
|
4
|
+
import classnames from 'classnames'
|
5
|
+
|
6
|
+
import { globalProps } from '../utilities/globalProps'
|
7
|
+
import pbChart from '../plugins/pb_chart'
|
8
|
+
|
9
|
+
type TreemapChartProps = {
|
10
|
+
chartData: array<{
|
11
|
+
name: string,
|
12
|
+
parent?: string | number,
|
13
|
+
value: number,
|
14
|
+
color?: string,
|
15
|
+
id?: string | number,
|
16
|
+
}>,
|
17
|
+
className?: string,
|
18
|
+
colors: array,
|
19
|
+
dark?: boolean,
|
20
|
+
drillable: boolean,
|
21
|
+
grouped: boolean,
|
22
|
+
height?: string,
|
23
|
+
id: number,
|
24
|
+
title: string,
|
25
|
+
tooltipHtml: string,
|
26
|
+
type?: string,
|
27
|
+
}
|
28
|
+
|
29
|
+
export default class TreemapChart extends React.Component<TreemapChartProps> {
|
30
|
+
static defaultProps = {
|
31
|
+
className: 'pb_treemap_chart',
|
32
|
+
dark: false,
|
33
|
+
drillable: false,
|
34
|
+
grouped: false,
|
35
|
+
type: 'treemap',
|
36
|
+
}
|
37
|
+
|
38
|
+
componentDidMount() {
|
39
|
+
const {
|
40
|
+
chartData,
|
41
|
+
className,
|
42
|
+
colors = [],
|
43
|
+
dark,
|
44
|
+
drillable,
|
45
|
+
grouped,
|
46
|
+
height,
|
47
|
+
id,
|
48
|
+
title = "",
|
49
|
+
tooltipHtml = '<span style="font-weight: bold; color:{point.color};">● </span>{point.name}: <b>{point.value}</b>',
|
50
|
+
type,
|
51
|
+
} = this.props
|
52
|
+
|
53
|
+
new pbChart(`.${className}`, {
|
54
|
+
chartData: chartData,
|
55
|
+
colors: colors,
|
56
|
+
dark,
|
57
|
+
drillable,
|
58
|
+
grouped,
|
59
|
+
height: height,
|
60
|
+
id: id,
|
61
|
+
title: title,
|
62
|
+
tooltipHtml,
|
63
|
+
type,
|
64
|
+
})
|
65
|
+
}
|
66
|
+
|
67
|
+
props: TreemapChartProps
|
68
|
+
|
69
|
+
render() {
|
70
|
+
const { className, id } = this.props
|
71
|
+
|
72
|
+
return (
|
73
|
+
<div
|
74
|
+
className={classnames(globalProps(this.props), className)}
|
75
|
+
id={id}
|
76
|
+
/>
|
77
|
+
)
|
78
|
+
}
|
79
|
+
}
|
@@ -39,7 +39,7 @@ const TreemapChartTooltip = (props) => (
|
|
39
39
|
chartData={chartData}
|
40
40
|
id="treemap-tooltip"
|
41
41
|
title="Favored Pizza Toppings"
|
42
|
-
tooltipHtml=
|
42
|
+
tooltipHtml={"<p>Custom tooltip for {point.name} <br/>with value: {point.value}</p>"}
|
43
43
|
{...props}
|
44
44
|
/>
|
45
45
|
</div>
|
@@ -4,13 +4,11 @@ import WebpackerReact from 'webpacker-react'
|
|
4
4
|
import ujs from 'webpacker-react/ujs'
|
5
5
|
|
6
6
|
import BarGraph from './pb_bar_graph/_bar_graph'
|
7
|
-
import CircleChart from './pb_circle_chart/_circle_chart'
|
8
7
|
import Dialog from './pb_dialog/_dialog'
|
9
8
|
import DialogBody from './pb_dialog/child_kits/_dialog_body'
|
10
9
|
import DialogFooter from './pb_dialog/child_kits/_dialog_footer'
|
11
10
|
import DialogHeader from './pb_dialog/child_kits/_dialog_header'
|
12
11
|
import DistributionBar from './pb_distribution_bar/_distribution_bar'
|
13
|
-
import Gauge from './pb_gauge/_gauge'
|
14
12
|
import Legend from './pb_legend/_legend'
|
15
13
|
import LineGraph from './pb_line_graph/_line_graph'
|
16
14
|
import Passphrase from './pb_passphrase/_passphrase'
|
@@ -20,7 +18,6 @@ import Typeahead from './pb_typeahead/_typeahead'
|
|
20
18
|
|
21
19
|
WebpackerReact.registerComponents({
|
22
20
|
BarGraph,
|
23
|
-
CircleChart,
|
24
21
|
Dialog,
|
25
22
|
DialogBody,
|
26
23
|
DialogFooter,
|
@@ -32,7 +29,6 @@ WebpackerReact.registerComponents({
|
|
32
29
|
RichTextEditor,
|
33
30
|
TreemapChart,
|
34
31
|
Typeahead,
|
35
|
-
Gauge,
|
36
32
|
})
|
37
33
|
|
38
34
|
ujs.setup(
|