playbook_ui 9.4.0.pre.alpha2 → 9.6.1.pre.deps1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) 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_checkbox/_checkbox.jsx +2 -1
  6. data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +3 -2
  7. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.jsx +67 -9
  8. data/app/pb_kits/playbook/pb_date_stacked/_date_stacked.jsx +11 -45
  9. data/app/pb_kits/playbook/pb_date_stacked/date_stacked.html.erb +6 -17
  10. data/app/pb_kits/playbook/pb_date_stacked/date_stacked.rb +5 -12
  11. data/app/pb_kits/playbook/pb_date_stacked/docs/example.yml +1 -3
  12. data/app/pb_kits/playbook/pb_date_stacked/docs/index.js +0 -1
  13. data/app/pb_kits/playbook/pb_date_time_stacked/_date_time_stacked.jsx +16 -32
  14. data/app/pb_kits/playbook/pb_date_time_stacked/_date_time_stacked.scss +4 -23
  15. data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.html.erb +8 -12
  16. data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.rb +2 -9
  17. data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_default.html.erb +1 -8
  18. data/app/pb_kits/playbook/pb_date_time_stacked/docs/_date_time_stacked_default.jsx +1 -19
  19. data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +1 -1
  20. data/app/pb_kits/playbook/pb_flex/_flex.jsx +1 -6
  21. data/app/pb_kits/playbook/pb_icon/_icon.jsx +20 -5
  22. data/app/pb_kits/playbook/pb_icon/icon.html.erb +4 -2
  23. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.jsx +1 -0
  24. data/app/pb_kits/playbook/pb_loading_inline/loading_inline.html.erb +1 -1
  25. data/app/pb_kits/playbook/pb_nav/_item.jsx +0 -2
  26. data/app/pb_kits/playbook/pb_nav/item.html.erb +2 -2
  27. data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +205 -0
  28. data/app/pb_kits/playbook/pb_passphrase/_passphrase.scss +73 -0
  29. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +33 -0
  30. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +3 -0
  31. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +31 -0
  32. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +1 -0
  33. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +16 -0
  34. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +56 -0
  35. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.md +1 -0
  36. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +10 -0
  37. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +68 -0
  38. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +9 -0
  39. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +33 -0
  40. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +3 -0
  41. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.html.erb +26 -0
  42. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.jsx +54 -0
  43. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.md +1 -0
  44. data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +15 -0
  45. data/app/pb_kits/playbook/pb_passphrase/docs/index.js +6 -0
  46. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -0
  47. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +36 -0
  48. data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +123 -0
  49. data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +55 -0
  50. data/app/pb_kits/playbook/pb_section_separator/_section_separator.jsx +3 -7
  51. data/app/pb_kits/playbook/pb_time_stacked/time_stacked.html.erb +2 -2
  52. data/app/pb_kits/playbook/react_rails_kits.js +1 -0
  53. data/lib/playbook/version.rb +1 -1
  54. metadata +35 -16
  55. data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_bold.html.erb +0 -5
  56. data/app/pb_kits/playbook/pb_date_stacked/docs/_date_stacked_bold.jsx +0 -38
  57. data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.test.js +0 -35
@@ -1,17 +1,13 @@
1
1
  <%= content_tag(:div,
2
2
  id: object.id,
3
3
  data: object.data,
4
- class: object.classname,
5
- aria: object.aria) do %>
6
-
7
- <%= pb_rails("flex", props: {classname: "flex-container", vertical: "stretch"}) do %>
8
- <%= pb_rails("body", props: {classname: "flex-item"}) do %>
9
- <%= pb_rails("date_stacked", props: { date: object.date_time_value, size: "sm", align: "right", bold: true, dark: object.dark }) %>
4
+ class: object.classname) do %>
5
+ <%= pb_rails("flex", props: { orientation: "row", vertical: "center" }) do %>
6
+ <%= pb_rails("flex/flex_item") do %>
7
+ <%= pb_rails("date_stacked", props: { align: "right", date: object.date, reverse: true, size: "sm", dark: object.dark }) %>
10
8
  <% end %>
11
- <%= pb_rails("section_separator", props: { orientation: "vertical", classname: "date-time-padding" }) %>
12
- <%= pb_rails("body", props: {classname: "flex-item"}) do %>
13
- <%= pb_rails("time_stacked", props: { time: object.date_time_value, dark: object.dark, timezone: object.timezone }) %>
9
+ <%= pb_rails("flex/flex_item") do %>
10
+ <%= pb_rails("time_stacked", props: { classname: "pb_date_time_stacked_kit", time: object.date, tag: "caption" }) %>
14
11
  <% end %>
15
- <% end %>
16
-
17
- <% end %>
12
+ <% end %>
13
+ <% end %>
@@ -3,17 +3,10 @@
3
3
  module Playbook
4
4
  module PbDateTimeStacked
5
5
  class DateTimeStacked < Playbook::KitBase
6
- prop :date, deprecated: true
7
- prop :date_time, type: Playbook::Props::Date,
6
+ prop :date, type: Playbook::Props::Date,
8
7
  default: ::DateTime.current
9
8
  prop :dark, type: Playbook::Props::Boolean,
10
9
  default: false
11
- prop :timezone, type: Playbook::Props::String,
12
- default: "America/New_York"
13
-
14
- def date_time_value
15
- date || date_time
16
- end
17
10
  end
18
11
  end
19
- end
12
+ end
@@ -1,8 +1 @@
1
- <%= pb_rails("date_time_stacked", props: { date_time: DateTime.now }) %>
2
- <br>
3
- <%= pb_rails("date_time_stacked", props: { date_time: Date.new(2018, 03, 20) }) %>
4
- <br>
5
- <%= pb_rails("date_time_stacked", props: { date_time: DateTime.now, timezone: "Asia/Tokyo" }) %>
6
- <br>
7
- <%= pb_rails("date_time_stacked", props: { date_time: DateTime.now, timezone: "America/Denver" }) %>
8
-
1
+ <%= pb_rails("date_time_stacked") %>
@@ -4,28 +4,10 @@ import { DateTimeStacked } from '../../'
4
4
  const DateTimeStackedDefault = (props) => (
5
5
  <div>
6
6
  <DateTimeStacked
7
- datetime={new Date()}
7
+ date={new Date()}
8
8
  {...props}
9
9
  />
10
- <br />
11
- <DateTimeStacked
12
- datetime={new Date()}
13
- timeZone="Asia/Tokyo"
14
-
15
- {...props}
16
- />
17
- <br />
18
- <DateTimeStacked
19
- datetime={new Date()}
20
- timeZone="America/Denver"
21
-
22
- {...props}
23
- />
24
-
25
10
  </div>
26
11
  )
27
12
 
28
13
  export default DateTimeStackedDefault
29
-
30
- // *Development Note* - We are reviewing this kit for a potential name change due to naming collisions when `new Date()` is used.
31
- // To avoid this bug, please use name spacing as shown in the code examples. ie `import { Date as AliasedComponentName } from '../../'
@@ -9,7 +9,7 @@ import { Dialog } from '../'
9
9
  - https://jestjs.io/docs/en/using-matchers
10
10
  */
11
11
 
12
- test('Kit renders Dialog', () => {
12
+ test('generated scaffold test - update me', () => {
13
13
  const testId = 'test1'
14
14
 
15
15
  render(
@@ -2,12 +2,11 @@
2
2
 
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
- import { buildCss, buildDataProps } from '../utilities/props'
5
+ import { buildCss } from '../utilities/props'
6
6
  import { globalProps } from '../utilities/globalProps.js'
7
7
  type FlexProps = {
8
8
  children: array<React.ReactNode> | React.ReactNode,
9
9
  className?: string,
10
- data?: object,
11
10
  horizontal?: "left" | "center" | "right" | "stretch" | "none",
12
11
  justify?: "start" | "center" | "end" | "around" | "between" | "evenly" | "none",
13
12
  id?: string,
@@ -28,7 +27,6 @@ const Flex = (props: FlexProps) => {
28
27
  align = 'none',
29
28
  children,
30
29
  className,
31
- data = {},
32
30
  inline = false,
33
31
  horizontal = 'left',
34
32
  justify = 'none',
@@ -53,8 +51,6 @@ const Flex = (props: FlexProps) => {
53
51
  const columnGapClass = columnGap !== 'none' ? `columnGap_${columnGap}` : ''
54
52
  const wrapClass = wrap === true ? 'wrap' : ''
55
53
  const reverseClass = reverse === true ? 'reverse' : ''
56
- const dataProps = buildDataProps(data)
57
-
58
54
  return (
59
55
  <div
60
56
  className={classnames(
@@ -74,7 +70,6 @@ const Flex = (props: FlexProps) => {
74
70
  globalProps(props),
75
71
  className
76
72
  )}
77
- {...dataProps}
78
73
  >
79
74
  {children}
80
75
  </div>
@@ -2,12 +2,14 @@
2
2
 
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
+ import { buildAriaProps, buildDataProps } from '../utilities/props'
5
6
  import { globalProps } from '../utilities/globalProps.js'
6
7
 
7
8
  type IconProps = {
8
- aria?: Object,
9
+ aria?: object,
9
10
  border?: boolean,
10
11
  className?: string,
12
+ data?: object,
11
13
  fixedWidth?: boolean,
12
14
  flip?: "horizontal" | "vertical" | "both" | "none",
13
15
  icon: string,
@@ -41,8 +43,10 @@ const flipMap = {
41
43
 
42
44
  const Icon = (props: IconProps) => {
43
45
  const {
46
+ aria = {},
44
47
  border = false,
45
48
  className,
49
+ data = {},
46
50
  fixedWidth = true,
47
51
  flip = false,
48
52
  icon,
@@ -75,11 +79,22 @@ const Icon = (props: IconProps) => {
75
79
  className
76
80
  )
77
81
 
82
+ aria.label ? null : aria.label = `${icon} icon`
83
+ const ariaProps = buildAriaProps(aria)
84
+ const dataProps = buildDataProps(data)
85
+
78
86
  return (
79
- <i
80
- className={classes}
81
- id={id}
82
- />
87
+ <>
88
+ <i
89
+ {...dataProps}
90
+ className={classes}
91
+ id={id}
92
+ />
93
+ <span
94
+ {...ariaProps}
95
+ hidden
96
+ />
97
+ </>
83
98
  )
84
99
  }
85
100
 
@@ -1,5 +1,7 @@
1
1
  <%= content_tag(:i, nil,
2
2
  id: object.id,
3
3
  data: object.data,
4
- class: object.classname,
5
- aria: object.aria) %>
4
+ class: object.classname ) %>
5
+ <%= content_tag(:span, nil,
6
+ aria: { label: "#{object.icon} icon" }.merge(object.aria),
7
+ hidden: true ) %>
@@ -22,6 +22,7 @@ const LoadingInline = (props: LoadingInlineProps) => {
22
22
  >
23
23
  <Body color="light">
24
24
  <Icon
25
+ aria={{ label: 'loading icon' }}
25
26
  fixedWidth
26
27
  icon="spinner"
27
28
  pulse
@@ -4,6 +4,6 @@
4
4
  class: object.classname) do %>
5
5
 
6
6
  <%= pb_rails("body", props: { color: "light", dark: object.dark }) do %>
7
- <%= pb_rails("icon", props: { fixed_width: true, icon: "spinner", pulse: true }) %> Loading
7
+ <%= pb_rails("icon", props: { aria: { label: "loading icon" }, fixed_width: true, icon: "spinner", pulse: true }) %> Loading
8
8
  <% end %>
9
9
  <% end %>
@@ -75,7 +75,6 @@ const NavItem = (props: NavItemProps) => {
75
75
  key={iconLeft}
76
76
  >
77
77
  <Icon
78
- aria={{ label: iconLeft }}
79
78
  className="pb_nav_list_item_icon_left"
80
79
  fixedWidth
81
80
  icon={iconLeft}
@@ -91,7 +90,6 @@ const NavItem = (props: NavItemProps) => {
91
90
  key={iconRight}
92
91
  >
93
92
  <Icon
94
- aria={{ label: iconRight }}
95
93
  className="pb_nav_list_item_icon_right"
96
94
  fixedWidth
97
95
  icon={iconRight}
@@ -9,13 +9,13 @@
9
9
  <%= pb_rails("image", props: { url: object.image_url, classname: "pb_nav_img_wrapper" }) %>
10
10
  <% end %>
11
11
  <% if object.icon_left %>
12
- <%= pb_rails("icon", props: { aria: { label: object.icon_left }, icon: object.icon_left, classname: "pb_nav_list_item_icon_left", fixed_width: true}) %>
12
+ <%= pb_rails("icon", props: { icon: object.icon_left, classname: "pb_nav_list_item_icon_left", fixed_width: true}) %>
13
13
  <% end %>
14
14
  <span class="pb_nav_list_item_text">
15
15
  <%= object.text %><%= content.presence %>
16
16
  </span>
17
17
  <% if object.icon_right %>
18
- <%= pb_rails("icon", props: { aria: { label: object.icon_right }, icon: object.icon_right, classname: "pb_nav_list_item_icon_right", fixed_width: true}) %>
18
+ <%= pb_rails("icon", props: { icon: object.icon_right, classname: "pb_nav_list_item_icon_right", fixed_width: true}) %>
19
19
  <% end %>
20
20
  <% end %>
21
21
  <% end %>
@@ -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 { zxcvbnPasswordScore } from './passwordStrength.js'
9
+ import { Body, Caption, Flex, Icon, PbReactPopover, ProgressSimple, TextInput } from '../'
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