playbook_ui 9.3.0.alpha.inline3 → 9.3.0.pre.alpha.password.strength.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/data/menu.yml +1 -0
  4. data/app/pb_kits/playbook/index.js +4 -3
  5. data/app/pb_kits/playbook/pb_badge/_badge.jsx +1 -26
  6. data/app/pb_kits/playbook/pb_date_picker/_date_picker.jsx +1 -6
  7. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.js +0 -3
  8. data/app/pb_kits/playbook/pb_flex/_flex.jsx +3 -6
  9. data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +205 -0
  10. data/app/pb_kits/playbook/pb_passphrase/_passphrase.scss +63 -0
  11. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +33 -0
  12. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +3 -0
  13. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +31 -0
  14. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +1 -0
  15. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +16 -0
  16. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +56 -0
  17. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.md +1 -0
  18. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +10 -0
  19. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +68 -0
  20. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +9 -0
  21. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +33 -0
  22. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +3 -0
  23. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.html.erb +26 -0
  24. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.jsx +54 -0
  25. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.md +1 -0
  26. data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +15 -0
  27. data/app/pb_kits/playbook/pb_passphrase/docs/index.js +6 -0
  28. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -0
  29. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +41 -0
  30. data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +123 -0
  31. data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +55 -0
  32. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.jsx +3 -4
  33. data/app/pb_kits/playbook/pb_text_input/_text_input.jsx +0 -3
  34. data/app/pb_kits/playbook/pb_textarea/_textarea.jsx +0 -3
  35. data/app/pb_kits/playbook/pb_typeahead/_typeahead.jsx +1 -9
  36. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +0 -13
  37. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx +11 -21
  38. data/app/pb_kits/playbook/pb_typeahead/components/Placeholder.jsx +4 -17
  39. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_default.jsx +0 -1
  40. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills.jsx +3 -8
  41. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +4 -4
  42. data/app/pb_kits/playbook/react_rails_kits.js +1 -0
  43. data/lib/playbook/version.rb +1 -1
  44. metadata +27 -4
  45. data/app/pb_kits/playbook/pb_typeahead/components/Input.jsx +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 354862f897edc053e27311b331ef01bb927323b9006af47752f1e51ae5e6eeca
4
- data.tar.gz: 38946538f1a04c0c2df4b5e0d7e5cfeeeecf3bea46e3af26abb4852456429553
3
+ metadata.gz: 8f2f364f3ddeeb9deedacb265c4740dc30e2ee30674ffac2b201a83a7ab04dfe
4
+ data.tar.gz: 34ba1be5b7fb2c41b49c4942239f365ea13793e34ed1195894d5172ca5cfca61
5
5
  SHA512:
6
- metadata.gz: fd7e15aab84fd9ac50f52bee181437b79d7d67c3df141c2c40d1349b1c568e9e235aa42308455cb18bd0073131786323182853ef2fe046040efb16c5bd93cb46
7
- data.tar.gz: d0619331fbaec43977d07d10f9f6aa3ed89b3de0ac5f9a8e1572844b8696c4ae4fbd55513f087d830c1f6ef092f2be24f2c757ae95d88f16dec0555741ff7580
6
+ metadata.gz: d03d13b429587603b894ad28a093ac0e0ff27c47dda184f0f655ba017405e7fcf6b14c2f75907b6c57c47156639fb9c5eba0d232bcf535bfbde2ba8fca9d0dcf
7
+ data.tar.gz: 989a00fe0377210d658918ebf38ef93f49621a9c4bdfd6c87c87f8914d09aa7f40ec58eaa1a46ddaaef52aca55d30662bf63049c4638352ec8705d684e19777c
@@ -55,6 +55,7 @@
55
55
  @import 'pb_multiple_users_stacked/multiple_users_stacked';
56
56
  @import 'pb_nav/nav';
57
57
  @import 'pb_online_status/online_status';
58
+ @import 'pb_passphrase/passphrase';
58
59
  @import 'pb_person/person';
59
60
  @import 'pb_person_contact/person_contact';
60
61
  @import 'pb_pill/pill';
@@ -26,6 +26,7 @@ kits:
26
26
  - form
27
27
  - form_group
28
28
  - form_pill
29
+ - passphrase
29
30
  - radio
30
31
  - rich_text_editor
31
32
  - select
@@ -61,6 +61,7 @@ export MultipleUsersStacked from './pb_multiple_users_stacked/_multiple_users_st
61
61
  export Nav from './pb_nav/_nav.jsx'
62
62
  export NavItem from './pb_nav/_item.jsx'
63
63
  export OnlineStatus from './pb_online_status/_online_status.jsx'
64
+ export Passphrase from './pb_passphrase/_passphrase.jsx'
64
65
  export PbReactPopover from './pb_popover/_popover.jsx'
65
66
  export Person from './pb_person/_person.jsx'
66
67
  export PersonContact from './pb_person_contact/_person_contact.jsx'
@@ -84,13 +85,13 @@ export StatChange from './pb_stat_change/_stat_change.jsx'
84
85
  export StatValue from './pb_stat_value/_stat_value.jsx'
85
86
  export Table from './pb_table/_table.jsx'
86
87
  export TableRow from './pb_table/_table_row.jsx'
87
- export Textarea from './pb_textarea/_textarea.jsx'
88
88
  export TextInput from './pb_text_input/_text_input.jsx'
89
+ export Textarea from './pb_textarea/_textarea.jsx'
89
90
  export Time from './pb_time/_time.jsx'
90
- export Timeline from './pb_timeline/_timeline.jsx'
91
+ export TimeRangeInline from './pb_time_range_inline/_time_range_inline.jsx'
91
92
  export TimeStacked from './pb_time_stacked/_time_stacked.jsx'
93
+ export Timeline from './pb_timeline/_timeline.jsx'
92
94
  export Timestamp from './pb_timestamp/_timestamp.jsx'
93
- export TimeRangeInline from './pb_time_range_inline/_time_range_inline.jsx'
94
95
  export Title from './pb_title/_title.jsx'
95
96
  export TitleCount from './pb_title_count/_title_count.jsx'
96
97
  export TitleDetail from './pb_title_detail/_title_detail.jsx'
@@ -3,7 +3,6 @@
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
5
  import { globalProps } from '../utilities/globalProps.js'
6
- import { Icon } from '../'
7
6
 
8
7
  import {
9
8
  buildAriaProps,
@@ -14,15 +13,8 @@ import {
14
13
  type BadgeProps = {
15
14
  aria?: object,
16
15
  className?: string,
17
- closeProps?: {
18
- onClick?: EventHandler,
19
- onMouseDown?: EventHandler,
20
- onTouchEnd?: EventHandler,
21
- },
22
16
  data?: object,
23
17
  id?: string,
24
- removeIcon?: Boolean,
25
- removeOnClick?: EventHandler,
26
18
  rounded?: boolean,
27
19
  text?: string,
28
20
  variant?: "error" | "info" | "neutral" | "primary" | "success" | "warning",
@@ -31,11 +23,8 @@ const Badge = (props: BadgeProps) => {
31
23
  const {
32
24
  aria = {},
33
25
  className,
34
- closeProps = {},
35
26
  data = {},
36
27
  id,
37
- removeIcon = false,
38
- removeOnClick = () => {},
39
28
  rounded = false,
40
29
  text,
41
30
  variant = 'neutral',
@@ -55,21 +44,7 @@ const Badge = (props: BadgeProps) => {
55
44
  className={css}
56
45
  id={id}
57
46
  >
58
- <span>
59
- {text}
60
- <If condition={removeIcon}>
61
- <span
62
- onClick={removeOnClick}
63
- style={{ cursor: 'pointer' }}
64
- {...closeProps}
65
- >
66
- <Icon
67
- fixedWidth
68
- icon="times"
69
- />
70
- </span>
71
- </If>
72
- </span>
47
+ <span>{text}</span>
73
48
  </div>
74
49
  )
75
50
  }
@@ -25,8 +25,6 @@ type DatePickerProps = {
25
25
  id?: String,
26
26
  inputAria?: object,
27
27
  inputData?: object,
28
- inputOnChange?: (String) => void,
29
- inputValue?: any,
30
28
  label?: String,
31
29
  maxDate: String,
32
30
  minDate: String,
@@ -57,8 +55,6 @@ const DatePicker = (props: DatePickerProps) => {
57
55
  id,
58
56
  inputAria,
59
57
  inputData,
60
- inputOnChange,
61
- inputValue,
62
58
  label = 'Date Picker',
63
59
  maxDate,
64
60
  minDate,
@@ -118,6 +114,7 @@ const DatePicker = (props: DatePickerProps) => {
118
114
  className={classes}
119
115
  id={id}
120
116
  >
117
+ {className}
121
118
  <div className="input_wrapper">
122
119
  <TextInput
123
120
  aria={inputAria}
@@ -129,9 +126,7 @@ const DatePicker = (props: DatePickerProps) => {
129
126
  id={pickerId}
130
127
  label={hideLabel ? null : label}
131
128
  name={name}
132
- onChange={inputOnChange}
133
129
  placeholder={placeholder}
134
- value={inputValue}
135
130
  />
136
131
  <If condition={!hideIcon}>
137
132
  <div
@@ -166,9 +166,6 @@ const datePickerHelper = (config) => {
166
166
  picker.input.style.caretColor = 'transparent'
167
167
  picker.input.style.cursor = 'pointer'
168
168
  }
169
-
170
- // Fix event bubbling bug on wrapper
171
- document.querySelector(`#${pickerId}`).parentElement.addEventListener('click', (e) => e.stopPropagation())
172
169
  }
173
170
 
174
171
  export default datePickerHelper
@@ -1,6 +1,6 @@
1
1
  /* @flow */
2
2
 
3
- import React, { forwardRef } from 'react'
3
+ import React from 'react'
4
4
  import classnames from 'classnames'
5
5
  import { buildCss } from '../utilities/props'
6
6
  import { globalProps } from '../utilities/globalProps.js'
@@ -22,12 +22,11 @@ type FlexProps = {
22
22
  wrap?: boolean,
23
23
  }
24
24
 
25
- const Flex = (props: FlexProps, ref: React.ElementRef<"div">) => {
25
+ const Flex = (props: FlexProps) => {
26
26
  const {
27
27
  align = 'none',
28
28
  children,
29
29
  className,
30
- id,
31
30
  inline = false,
32
31
  horizontal = 'left',
33
32
  justify = 'none',
@@ -71,12 +70,10 @@ const Flex = (props: FlexProps, ref: React.ElementRef<"div">) => {
71
70
  globalProps(props),
72
71
  className
73
72
  )}
74
- id={id}
75
- ref={ref}
76
73
  >
77
74
  {children}
78
75
  </div>
79
76
  )
80
77
  }
81
78
 
82
- export default forwardRef(Flex)
79
+ export default Flex
@@ -0,0 +1,205 @@
1
+
2
+ /* @flow */
3
+
4
+ import React, { useCallback, useEffect, useMemo, useState } from 'react'
5
+ import classnames from 'classnames'
6
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
7
+ import { globalProps } from '../utilities/globalProps.js'
8
+ import { Body, Caption, Flex, Icon, PbReactPopover, ProgressSimple, TextInput } from '../'
9
+ import { zxcvbnPasswordScore } from './passwordStrength.js'
10
+
11
+ type PassphraseProps = {
12
+ aria?: object,
13
+ averageThreshold?: number,
14
+ common?: boolean,
15
+ confirmation?: boolean,
16
+ className?: string,
17
+ data?: object,
18
+ dark?: boolean,
19
+ id?: string,
20
+ inputProps?: {},
21
+ label?: string,
22
+ minLength?: number,
23
+ onChange: (String) => void,
24
+ showTipsBelow?: 'always' | 'xs' | 'sm' | 'md' | 'lg' | 'xl',
25
+ onStrengthChange?: (number) => void,
26
+ strongThreshold?: number,
27
+ tips?: Array<string>,
28
+ uncontrolled?: boolean,
29
+ value: string,
30
+ }
31
+
32
+ const Passphrase = (props: PassphraseProps) => {
33
+ const {
34
+ aria = {},
35
+ averageThreshold = 2,
36
+ className,
37
+ common = false,
38
+ confirmation = false,
39
+ dark = false,
40
+ data = {},
41
+ id,
42
+ inputProps = {},
43
+ label = confirmation ? 'Confirm Passphrase' : 'Passphrase',
44
+ minLength,
45
+ onChange = () => {},
46
+ showTipsBelow = 'always',
47
+ onStrengthChange,
48
+ strongThreshold = 3,
49
+ tips = [],
50
+ uncontrolled = false,
51
+ value = '',
52
+ } = props
53
+
54
+ const [uncontrolledValue, setUncontrolledValue] = useState('')
55
+
56
+ const handleChange = useCallback(
57
+ (e) => uncontrolled ? setUncontrolledValue(e.target.value) : onChange(e),
58
+ [uncontrolled, onChange]
59
+ )
60
+
61
+ const displayValue = useMemo(
62
+ () => (uncontrolled ? uncontrolledValue : value),
63
+ [value, uncontrolledValue, uncontrolled],
64
+ )
65
+
66
+ const [showPopover, setShowPopover] = useState(false)
67
+ const toggleShowPopover = () => setShowPopover(!showPopover)
68
+ const [showPassphrase, setShowPassphrase] = useState(false)
69
+ const toggleShowPassphrase = () => setShowPassphrase(!showPassphrase)
70
+
71
+ const ariaProps = buildAriaProps(aria)
72
+ const dataProps = buildDataProps(data)
73
+ const classes = classnames(buildCss('pb_passphrase'), globalProps(props), className)
74
+
75
+ const calculator = useMemo(
76
+ () => confirmation ? { test: () => ({}) } : zxcvbnPasswordScore({ averageThreshold, strongThreshold, minLength }),
77
+ [averageThreshold, confirmation, strongThreshold, minLength]
78
+ )
79
+
80
+ const { percent: progressPercent, variant: progressVariant, text: strengthLabel, strength } = calculator.test(displayValue, common)
81
+
82
+ useEffect(() => {
83
+ if (typeof onStrengthChange === 'function') {
84
+ onStrengthChange(strength)
85
+ }
86
+ }, [strength])
87
+
88
+ const tipClass = classnames(
89
+ (dark ? 'dark' : null),
90
+ (showTipsBelow === 'always' ? null : `show-below-${showTipsBelow}`),
91
+ )
92
+
93
+ const popoverReference = (
94
+ <a
95
+ className={tipClass}
96
+ onClick={toggleShowPopover}
97
+ >
98
+ <Icon
99
+ dark={dark}
100
+ icon="info-circle"
101
+ size="xs"
102
+ variant="link"
103
+ />
104
+ </a>
105
+ )
106
+
107
+ return (
108
+ <div
109
+ {...ariaProps}
110
+ {...dataProps}
111
+ className={classes}
112
+ id={id}
113
+ >
114
+ <label>
115
+ <Flex align="baseline">
116
+ <Caption
117
+ className="passphrase-label"
118
+ text={label}
119
+ />
120
+ <If condition={tips.length > 0 && !confirmation}>
121
+ <PbReactPopover
122
+ placement="right"
123
+ reference={popoverReference}
124
+ show={showPopover}
125
+ >
126
+ <Flex
127
+ align="center"
128
+ orientation="column"
129
+ >
130
+ <Caption
131
+ marginBottom="xs"
132
+ text="Tips for a good passphrase"
133
+ />
134
+ <div>
135
+ {
136
+ tips.map((tip, i) => (
137
+ <Caption
138
+ key={i}
139
+ marginBottom="xs"
140
+ size="xs"
141
+ >
142
+ <Icon
143
+ icon="shield-check"
144
+ marginRight="xs"
145
+ />
146
+ {tip}
147
+ </Caption>
148
+ ))
149
+ }
150
+ </div>
151
+ </Flex>
152
+ </PbReactPopover>
153
+ </If>
154
+ </Flex>
155
+ <div className="passphrase-text-input-wrapper">
156
+ <TextInput
157
+ className="passphrase-text-input"
158
+ dark={dark}
159
+ marginBottom="xs"
160
+ onChange={handleChange}
161
+ placeholder="Enter a passphrase..."
162
+ type={showPassphrase ? 'text' : 'password'}
163
+ value={displayValue}
164
+ {...inputProps}
165
+ />
166
+ <span
167
+ className="show-passphrase-icon"
168
+ dark={dark}
169
+ onClick={toggleShowPassphrase}
170
+ >
171
+ <Body
172
+ className={showPassphrase ? 'hide-icon' : ''}
173
+ color="light"
174
+ dark={dark}
175
+ >
176
+ <Icon icon="eye-slash" />
177
+ </Body>
178
+ <Body
179
+ className={showPassphrase ? '' : 'hide-icon'}
180
+ color="light"
181
+ dark={dark}
182
+ >
183
+ <Icon icon="eye" />
184
+ </Body>
185
+ </span>
186
+ </div>
187
+ </label>
188
+ <If condition={!confirmation}>
189
+ <ProgressSimple
190
+ className={displayValue.length === 0 ? 'progress-empty-input' : null}
191
+ dark={dark}
192
+ percent={progressPercent}
193
+ variant={progressVariant}
194
+ />
195
+ <Caption
196
+ dark={dark}
197
+ size="xs"
198
+ text={strengthLabel}
199
+ />
200
+ </If>
201
+ </div>
202
+ )
203
+ }
204
+
205
+ export default Passphrase
@@ -0,0 +1,63 @@
1
+ @import "../tokens/colors";
2
+ @import "../tokens/spacing";
3
+ @import "../tokens/screen_sizes";
4
+
5
+ .pb_passphrase {
6
+ margin-bottom: $space_sm;
7
+
8
+ a.dark {
9
+ color: $white;
10
+ }
11
+
12
+ a {
13
+
14
+ &[class*=show-below-] {
15
+ display: none;
16
+ }
17
+ @each $breakpoint_name, $breakpoint in $breakpoints {
18
+ &.show-below-#{$breakpoint_name} {
19
+ @include break_at($breakpoint) {
20
+ display: inline;
21
+ }
22
+ }
23
+ }
24
+ }
25
+
26
+ .passphrase-label{
27
+ margin-right: 4px;
28
+ }
29
+
30
+ .passphrase-text-input-wrapper {
31
+ position: relative;
32
+
33
+ .pb_text_input_kit_label {
34
+ margin-bottom: 4px;
35
+ }
36
+
37
+ .passphrase-text-input input{
38
+ padding-right: 42px;
39
+ }
40
+
41
+ .passphrase-text-input .text_input_wrapper {
42
+ margin-bottom: 0;
43
+ }
44
+
45
+ .show-passphrase-icon {
46
+ position: absolute;
47
+ right: 11px;
48
+ top: 11px;
49
+
50
+ .hide-icon {
51
+ display: none;
52
+ }
53
+ }
54
+ }
55
+
56
+ .pb_progress_simple_wrapper, .pb_progress_simple_wrapper_dark {
57
+ margin-bottom: 4px;
58
+
59
+ &.progress-empty-input {
60
+ visibility: hidden;
61
+ }
62
+ }
63
+ }