playbook_ui 9.3.0.pre.alpha.password.strength.1 → 9.4.0.alpha.user.kit.bug

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +0 -1
  3. data/app/pb_kits/playbook/data/menu.yml +0 -1
  4. data/app/pb_kits/playbook/index.js +3 -4
  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_nav/_vertical_nav.scss +1 -1
  9. data/app/pb_kits/playbook/pb_nav/docs/_block_nav.html.erb +41 -5
  10. data/app/pb_kits/playbook/pb_nav/docs/_block_nav.jsx +44 -6
  11. data/app/pb_kits/playbook/react_rails_kits.js +0 -1
  12. data/lib/playbook/version.rb +1 -1
  13. metadata +3 -27
  14. data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +0 -205
  15. data/app/pb_kits/playbook/pb_passphrase/_passphrase.scss +0 -63
  16. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +0 -33
  17. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +0 -3
  18. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +0 -31
  19. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +0 -1
  20. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +0 -16
  21. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +0 -56
  22. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.md +0 -1
  23. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +0 -10
  24. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +0 -68
  25. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +0 -9
  26. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +0 -33
  27. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +0 -3
  28. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.html.erb +0 -26
  29. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.jsx +0 -54
  30. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.md +0 -1
  31. data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +0 -15
  32. data/app/pb_kits/playbook/pb_passphrase/docs/index.js +0 -6
  33. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +0 -1
  34. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +0 -41
  35. data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +0 -123
  36. data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f2f364f3ddeeb9deedacb265c4740dc30e2ee30674ffac2b201a83a7ab04dfe
4
- data.tar.gz: 34ba1be5b7fb2c41b49c4942239f365ea13793e34ed1195894d5172ca5cfca61
3
+ metadata.gz: 0d58bd43051948ed88cd448d6a1af339b38f5b53ec707cd6d49b10cb227cc8d5
4
+ data.tar.gz: 33d5becc70eebf7f7ed08f452ff2b3422d1891d93829e529ef59e2425dca64a7
5
5
  SHA512:
6
- metadata.gz: d03d13b429587603b894ad28a093ac0e0ff27c47dda184f0f655ba017405e7fcf6b14c2f75907b6c57c47156639fb9c5eba0d232bcf535bfbde2ba8fca9d0dcf
7
- data.tar.gz: 989a00fe0377210d658918ebf38ef93f49621a9c4bdfd6c87c87f8914d09aa7f40ec58eaa1a46ddaaef52aca55d30662bf63049c4638352ec8705d684e19777c
6
+ metadata.gz: d7731ea2e841c7520aaed03654f9983fff519785df5622292b5a47be9ebfd0de6119c7d47378e3c35a5077ca576b68c26cb4bf5967847f6a89e6dd530a8093bb
7
+ data.tar.gz: 3c118b92821665486442b8eb870d2807f9bf64ed6cbfd62d017c667e8b6df11b76fb173e70fdc0551fd2bb54f82b5572ae33527748d3ad09dff88c96ee9865c1
@@ -55,7 +55,6 @@
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';
59
58
  @import 'pb_person/person';
60
59
  @import 'pb_person_contact/person_contact';
61
60
  @import 'pb_pill/pill';
@@ -26,7 +26,6 @@ kits:
26
26
  - form
27
27
  - form_group
28
28
  - form_pill
29
- - passphrase
30
29
  - radio
31
30
  - rich_text_editor
32
31
  - select
@@ -61,7 +61,6 @@ 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'
65
64
  export PbReactPopover from './pb_popover/_popover.jsx'
66
65
  export Person from './pb_person/_person.jsx'
67
66
  export PersonContact from './pb_person_contact/_person_contact.jsx'
@@ -85,13 +84,13 @@ export StatChange from './pb_stat_change/_stat_change.jsx'
85
84
  export StatValue from './pb_stat_value/_stat_value.jsx'
86
85
  export Table from './pb_table/_table.jsx'
87
86
  export TableRow from './pb_table/_table_row.jsx'
88
- export TextInput from './pb_text_input/_text_input.jsx'
89
87
  export Textarea from './pb_textarea/_textarea.jsx'
88
+ export TextInput from './pb_text_input/_text_input.jsx'
90
89
  export Time from './pb_time/_time.jsx'
91
- export TimeRangeInline from './pb_time_range_inline/_time_range_inline.jsx'
92
- export TimeStacked from './pb_time_stacked/_time_stacked.jsx'
93
90
  export Timeline from './pb_timeline/_timeline.jsx'
91
+ export TimeStacked from './pb_time_stacked/_time_stacked.jsx'
94
92
  export Timestamp from './pb_timestamp/_timestamp.jsx'
93
+ export TimeRangeInline from './pb_time_range_inline/_time_range_inline.jsx'
95
94
  export Title from './pb_title/_title.jsx'
96
95
  export TitleCount from './pb_title_count/_title_count.jsx'
97
96
  export TitleDetail from './pb_title_detail/_title_detail.jsx'
@@ -53,9 +53,10 @@ const Checkbox = (props: CheckboxProps) => {
53
53
 
54
54
  useEffect(() => {
55
55
  if (checkRef.current) {
56
+ checkRef.current.checked = checked
56
57
  checkRef.current.indeterminate = indeterminate
57
58
  }
58
- }, [indeterminate])
59
+ }, [indeterminate, checked])
59
60
 
60
61
  return (
61
62
  <label
@@ -4,12 +4,13 @@
4
4
  $transition: $transition_cubic;
5
5
 
6
6
  [class^=pb_checkbox_kit] {
7
- display: inline-flex;
8
7
  cursor: pointer;
8
+ display: inline-flex;
9
+ vertical-align: middle;
9
10
  .pb_checkbox_label {
10
- padding-left: $space_xs;
11
11
  cursor: pointer;
12
12
  font-size: $text_lt_default;
13
+ padding-left: $space_xs;
13
14
  user-select: none;
14
15
  }
15
16
 
@@ -1,15 +1,73 @@
1
- import React from 'react'
2
- import { Checkbox } from '../..'
1
+ import React, { useState } from 'react'
2
+ import { Checkbox, Table } from '../..'
3
3
 
4
4
  const CheckboxIndeterminate = (props) => {
5
+ const [checkboxes, setCheckboxes] = useState([
6
+ { name: 'Coffee', checked: false },
7
+ { name: 'Ice Cream', checked: false },
8
+ { name: 'Chocolate', checked: true },
9
+ ])
10
+
11
+ const isAllChecked = !checkboxes.find((checkbox) => !checkbox.checked)
12
+ const isNoneChecked = !checkboxes.find((checkbox) => checkbox.checked)
13
+
14
+ const processCheckboxes = (checked) =>
15
+ checkboxes.slice(0).map((checkbox) => {
16
+ checkbox.checked = checked
17
+ return checkbox
18
+ })
19
+
20
+ const onToggleAll = () => {
21
+ setCheckboxes(
22
+ isNoneChecked ? processCheckboxes(true) : processCheckboxes(false)
23
+ )
24
+ }
25
+
26
+ const updateCheckboxes = (checkbox, index) => {
27
+ const newCheckboxes = checkboxes.slice(0)
28
+ newCheckboxes[index].checked = !checkbox.checked
29
+ setCheckboxes(newCheckboxes)
30
+ }
31
+
5
32
  return (
6
- <Checkbox
7
- indeterminate
8
- name="checkbox-name"
9
- text="Indeterminate State"
10
- value="check-box value"
11
- {...props}
12
- />
33
+ <Table
34
+ container={false}
35
+ size="md"
36
+ >
37
+ <thead>
38
+ <tr>
39
+ <th>
40
+ <Checkbox
41
+ checked={isAllChecked}
42
+ indeterminate={!isAllChecked && !isNoneChecked}
43
+ name="checkbox-name"
44
+ onChange={onToggleAll}
45
+ text={isNoneChecked ? 'Check All' : 'Uncheck All'}
46
+ value="check-box value"
47
+ {...props}
48
+ />
49
+ </th>
50
+ </tr>
51
+ </thead>
52
+ <tbody>
53
+ {checkboxes.map((checkbox, index) => (
54
+ <tr key={index}>
55
+ <td>
56
+ <Checkbox
57
+ checked={checkbox.checked}
58
+ name={checkbox.name}
59
+ onChange={() => {
60
+ updateCheckboxes(checkbox, index)
61
+ }}
62
+ text={checkbox.name}
63
+ value="check-box value"
64
+ {...props}
65
+ />
66
+ </td>
67
+ </tr>
68
+ ))}
69
+ </tbody>
70
+ </Table>
13
71
  )
14
72
  }
15
73
 
@@ -16,7 +16,7 @@ $selector: ".pb_nav_list";
16
16
  list-style: none;
17
17
  }
18
18
 
19
- [class*=_title] {
19
+ [class*=pb_nav_list_title] {
20
20
  padding: 0 $space_md $space_sm;
21
21
  }
22
22
 
@@ -1,6 +1,42 @@
1
- <%= pb_rails("nav", props: {title: "Menu", link: "#"}) do %>
2
- <%= pb_rails("nav/item", props: { link: "#", active: true }) do%>Photos<% end %>
3
- <%= pb_rails("nav/item", props: { link: "#" }) do%>Music<% end %>
4
- <%= pb_rails("nav/item", props: { link: "#" }) do%>Video<% end %>
5
- <%= pb_rails("nav/item", props: { link: "#" }) do%>Files<% end %>
1
+ <%= pb_rails("nav", props: {title: "Users", link: "#"}) do %>
2
+ <%= pb_rails("nav/item", props: { link: "#", active: true }) do%>
3
+ <%= pb_rails("user", props: {
4
+ name: "Anna Black",
5
+ territory: "PHL",
6
+ title: "Remodeling Consultant",
7
+ orientation: "horizontal",
8
+ align: "left",
9
+ avatar_url: "https://randomuser.me/api/portraits/women/44.jpg"
10
+ }) %>
11
+ <% end %>
12
+ <%= pb_rails("nav/item", props: { link: "#" }) do%>
13
+ <%= pb_rails("user", props: {
14
+ name: "Julie Hamilton",
15
+ territory: "PHL",
16
+ title: "Inside Sales Agent",
17
+ orientation: "horizontal",
18
+ align: "left",
19
+ avatar_url: "https://randomuser.me/api/portraits/women/45.jpg"
20
+ }) %>
21
+ <% end %>
22
+ <%= pb_rails("nav/item", props: { link: "#" }) do%>
23
+ <%= pb_rails("user", props: {
24
+ name: "Dennis Wilks",
25
+ territory: "PHL",
26
+ title: "Senior Remodeling Consultant",
27
+ orientation: "horizontal",
28
+ align: "left",
29
+ avatar_url: "https://randomuser.me/api/portraits/men/44.jpg"
30
+ }) %>
31
+ <% end %>
32
+ <%= pb_rails("nav/item", props: { link: "#" }) do%>
33
+ <%= pb_rails("user", props: {
34
+ name: "Ronnie Martin",
35
+ territory: "PHL",
36
+ title: "Customer Development Representative",
37
+ orientation: "horizontal",
38
+ align: "left",
39
+ avatar_url: "https://randomuser.me/api/portraits/men/46.jpg"
40
+ }) %>
41
+ <% end %>
6
42
  <% end %>
@@ -1,12 +1,12 @@
1
1
  import React from 'react'
2
- import { Nav } from '../../'
2
+ import { Nav, User } from '../../'
3
3
  import NavItem from '../_item.jsx'
4
4
 
5
5
  const BlockNav = (props) => {
6
6
  return (
7
7
  <Nav
8
8
  link="#"
9
- title="Menu"
9
+ title="Users"
10
10
  {...props}
11
11
  >
12
12
  <NavItem
@@ -14,11 +14,49 @@ const BlockNav = (props) => {
14
14
  link="#"
15
15
  {...props}
16
16
  >
17
- {'Photos'}
17
+ <User
18
+ align="left"
19
+ avatarUrl="https://randomuser.me/api/portraits/women/44.jpg"
20
+ name="Anna Black"
21
+ orientation="horizontal"
22
+ territory="PHL"
23
+ title="Remodeling Consultant"
24
+ {...props}
25
+ />
26
+ </NavItem>
27
+ <NavItem link="#">
28
+ <User
29
+ align="left"
30
+ avatarUrl="https://randomuser.me/api/portraits/women/45.jpg"
31
+ name="Julie Hamilton"
32
+ orientation="horizontal"
33
+ territory="PHL"
34
+ title="Inside Sales Agent"
35
+ {...props}
36
+ />
37
+ </NavItem>
38
+ <NavItem link="#">
39
+ <User
40
+ align="left"
41
+ avatarUrl="https://randomuser.me/api/portraits/men/44.jpg"
42
+ name="Dennis Wilks"
43
+ orientation="horizontal"
44
+ territory="PHL"
45
+ title="Senior Remodeling Consultant"
46
+ {...props}
47
+ />
48
+ </NavItem>
49
+ <NavItem link="#">
50
+ <User
51
+ align="left"
52
+ avatarUrl="https://randomuser.me/api/portraits/men/46.jpg"
53
+ name="Ronnie Martin"
54
+ orientation="horizontal"
55
+ territory="PHL"
56
+ title="Customer Development Representative"
57
+ {...props}
58
+ />
18
59
  </NavItem>
19
- <NavItem link="#">{'Music'}</NavItem>
20
- <NavItem link="#">{'Video'}</NavItem>
21
- <NavItem link="#">{'Files'}</NavItem>
22
60
  </Nav>
23
61
  )
24
62
  }
@@ -3,7 +3,6 @@ export { default as BarGraph } from './pb_bar_graph/_bar_graph.jsx'
3
3
  export { default as DistributionBar } from './pb_distribution_bar/_distribution_bar.jsx'
4
4
  export { default as Legend } from './pb_legend/_legend.jsx'
5
5
  export { default as LineGraph } from './pb_line_graph/_line_graph.jsx'
6
- export { default as Passphrase } from './pb_passphrase/_passphrase.jsx'
7
6
  export { default as Typeahead } from './pb_typeahead/_typeahead.jsx'
8
7
  export { default as RichTextEditor } from './pb_rich_text_editor/_rich_text_editor.jsx'
9
8
  export { default as Dialog } from './pb_dialog/_dialog.jsx'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- VERSION = "9.3.0.pre.alpha.password.strength.1"
4
+ VERSION = "9.4.0.alpha.user.kit.bug"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playbook_ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.3.0.pre.alpha.password.strength.1
4
+ version: 9.4.0.alpha.user.kit.bug
5
5
  platform: ruby
6
6
  authors:
7
7
  - Power UX
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-04-09 00:00:00.000000000 Z
12
+ date: 2021-04-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -1378,29 +1378,6 @@ files:
1378
1378
  - app/pb_kits/playbook/pb_online_status/docs/index.js
1379
1379
  - app/pb_kits/playbook/pb_online_status/online_status.html.erb
1380
1380
  - app/pb_kits/playbook/pb_online_status/online_status.rb
1381
- - app/pb_kits/playbook/pb_passphrase/_passphrase.jsx
1382
- - app/pb_kits/playbook/pb_passphrase/_passphrase.scss
1383
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx
1384
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb
1385
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx
1386
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md
1387
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb
1388
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx
1389
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.md
1390
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb
1391
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx
1392
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md
1393
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx
1394
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md
1395
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.html.erb
1396
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.jsx
1397
- - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_tips.md
1398
- - app/pb_kits/playbook/pb_passphrase/docs/example.yml
1399
- - app/pb_kits/playbook/pb_passphrase/docs/index.js
1400
- - app/pb_kits/playbook/pb_passphrase/passphrase.html.erb
1401
- - app/pb_kits/playbook/pb_passphrase/passphrase.rb
1402
- - app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx
1403
- - app/pb_kits/playbook/pb_passphrase/passwordStrength.js
1404
1381
  - app/pb_kits/playbook/pb_person/_person.jsx
1405
1382
  - app/pb_kits/playbook/pb_person/_person.scss
1406
1383
  - app/pb_kits/playbook/pb_person/docs/_description.md
@@ -2130,8 +2107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
2130
2107
  - !ruby/object:Gem::Version
2131
2108
  version: 1.3.1
2132
2109
  requirements: []
2133
- rubyforge_project:
2134
- rubygems_version: 2.7.3
2110
+ rubygems_version: 3.1.4
2135
2111
  signing_key:
2136
2112
  specification_version: 4
2137
2113
  summary: Playbook Design System
@@ -1,205 +0,0 @@
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
@@ -1,63 +0,0 @@
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
- }
@@ -1,33 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Body, Passphrase } from '../../'
3
-
4
- const PassphraseCommon = (props) => {
5
- const [input, setInput] = useState('')
6
-
7
- const handleChange = (e) => setInput(e.target.value)
8
-
9
- const COMMON_PASSPHRASES = ['passphrase', 'apple', 'password', 'p@55w0rd']
10
-
11
- const commonCheck = (passphrase) => {
12
- if (COMMON_PASSPHRASES.includes(passphrase))
13
- return true
14
- return false
15
- }
16
-
17
- return (
18
- <>
19
- <div>
20
- <Body text={`Try typing any of the following: ${COMMON_PASSPHRASES.join(' ')}`} />
21
- <br />
22
- <Passphrase
23
- common={commonCheck(input)}
24
- onChange={handleChange}
25
- value={input}
26
- {...props}
27
- />
28
- </div>
29
- </>
30
- )
31
- }
32
-
33
- export default PassphraseCommon
@@ -1,3 +0,0 @@
1
- <%= pb_rails("passphrase") %>
2
-
3
- <%= pb_rails("passphrase", props: { confirmation: true}) %>
@@ -1,31 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Passphrase } from '../../'
3
-
4
- const PassphraseDefault = (props) => {
5
- const [input, setInput] = useState('')
6
- const handleChange = (e) => setInput(e.target.value)
7
-
8
- const [confoInput, setConfoInput] = useState('')
9
- const handleConfoChange = (e) => setConfoInput(e.target.value)
10
-
11
- return (
12
- <>
13
- <div>
14
- <Passphrase
15
- onChange={handleChange}
16
- value={input}
17
- {...props}
18
- />
19
- <Passphrase
20
- confirmation
21
- onChange={handleConfoChange}
22
- value={confoInput}
23
- {...props}
24
- />
25
- <span>{input === confoInput ? 'They match!' : 'They don\'t match!'}</span>
26
- </div>
27
- </>
28
- )
29
- }
30
-
31
- export default PassphraseDefault
@@ -1 +0,0 @@
1
- Use the `confirmation` prop to only include the label and show/hide icon.
@@ -1,16 +0,0 @@
1
- <%= pb_rails("passphrase", props: {
2
- input_props: {
3
- disabled: true,
4
- id: "my-disabled-passphrase",
5
- name: "my-disabled-field",
6
- },
7
- label: "Input props passed directly to input kit"
8
- }) %>
9
-
10
- <%= pb_rails("passphrase", props: {
11
- input_props: {
12
- id: "my-custome-id",
13
- name: "my-value-name",
14
- },
15
- label: "Set name, id, etc for use in forms"
16
- }) %>
@@ -1,56 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Passphrase } from '../../'
3
-
4
- const PassphraseInputProps = (props) => {
5
- const [input, setInput] = useState('')
6
-
7
- const handleChange = (e) => setInput(e.target.value)
8
-
9
- return (
10
- <>
11
- <div>
12
- <Passphrase
13
- inputProps={{
14
- name: 'my-disabled-field',
15
- id: 'my-value-id',
16
- disabled: true,
17
- }}
18
- label="Pass props directly to input kit"
19
- onChange={handleChange}
20
- value={input}
21
- {...props}
22
- />
23
- <Passphrase
24
- inputProps={{
25
- children: (
26
- <input
27
- onChange={handleChange}
28
- type="password"
29
- value={input}
30
- />),
31
- }}
32
- label="Custom input"
33
- onChange={handleChange}
34
- value={input}
35
- {...props}
36
- />
37
- <Passphrase
38
- inputProps={{ name: 'my-value-name', id: 'my-value-id' }}
39
- label="Set name and ID for use in form libraries"
40
- onChange={handleChange}
41
- value={input}
42
- {...props}
43
- />
44
- <Passphrase
45
- confirmation
46
- inputProps={{ name: 'my-value-confirmation-name', id: 'my-value-confirmation-id' }}
47
- onChange={handleChange}
48
- value={input}
49
- {...props}
50
- />
51
- </div>
52
- </>
53
- )
54
- }
55
-
56
- export default PassphraseInputProps
@@ -1 +0,0 @@
1
- `inputProps` is passed directly to an underlying Text Input kit. See the specific docs <a href="/kits/text_input/react" target="_blank">here</a> for more details.
@@ -1,10 +0,0 @@
1
-
2
- <%= pb_rails("passphrase", props: { label: "Default Settings"}) %>
3
-
4
- <%= pb_rails("passphrase", props: { label: "Min length = 5", min_length: 5}) %>
5
-
6
- <%= pb_rails("passphrase", props: { label: "Min length = 30", min_length: 30}) %>
7
-
8
- <%= pb_rails("passphrase", props: { average_threshold: 1, label: "Average Threshold = 1"}) %>
9
-
10
- <%= pb_rails("passphrase", props: { label: "Strong Threshold = 4", strong_threshold: 4}) %>
@@ -1,68 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Body, Passphrase, TextInput } from '../../'
3
-
4
- const PassphraseMeterSettings = (props) => {
5
- const [input, setInput] = useState('')
6
-
7
- const handleChange = (e) => setInput(e.target.value)
8
-
9
- const [strength, setStrength] = useState(0)
10
- const handleStrengthChange = (str) => setStrength(str)
11
- return (
12
- <>
13
- <div>
14
- <Body>
15
- {'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.'}
16
- </Body>
17
- <br />
18
- <TextInput
19
- disabled
20
- label="Calculated Strength"
21
- readOnly
22
- value={strength}
23
- />
24
-
25
- <Passphrase
26
- label="Default settings"
27
- onChange={handleChange}
28
- onStrengthChange={handleStrengthChange}
29
- value={input}
30
- {...props}
31
- />
32
-
33
- <Passphrase
34
- label="Min length = 5"
35
- minLength={5}
36
- onChange={handleChange}
37
- value={input}
38
- {...props}
39
- />
40
- <Passphrase
41
- label="Min length = 30"
42
- minLength={30}
43
- onChange={handleChange}
44
- value={input}
45
- {...props}
46
- />
47
-
48
- <Passphrase
49
- averageThreshold={1}
50
- label="Average threshold = 1"
51
- onChange={handleChange}
52
- value={input}
53
- {...props}
54
- />
55
-
56
- <Passphrase
57
- label="Strong Threshold = 4"
58
- onChange={handleChange}
59
- strongThreshold={4}
60
- value={input}
61
- {...props}
62
- />
63
- </div>
64
- </>
65
- )
66
- }
67
-
68
- export default PassphraseMeterSettings
@@ -1,9 +0,0 @@
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.
3
-
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.
7
-
8
- 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.
@@ -1,33 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Passphrase, TextInput } from '../../'
3
-
4
- const PassphraseStrengthChange = (props) => {
5
- const [input, setInput] = useState('')
6
-
7
- const handleChange = (e) => setInput(e.target.value)
8
-
9
- const [strength, setStrength] = useState(0)
10
- const handleStrengthChange = (str) => setStrength(str)
11
-
12
- return (
13
- <>
14
- <div>
15
- <Passphrase
16
- label="Passphrase"
17
- onChange={handleChange}
18
- onStrengthChange={handleStrengthChange}
19
- value={input}
20
- {...props}
21
- />
22
- <TextInput
23
- disabled
24
- label="Passphrase Strength"
25
- readOnly
26
- value={strength}
27
- />
28
- </div>
29
- </>
30
- )
31
- }
32
-
33
- export default PassphraseStrengthChange
@@ -1,3 +0,0 @@
1
- As the strength of the entered passphrase changes, the optional `onStrengthChange` callback is called with the new strength value. This exposes the calculated strength.
2
-
3
- Strength is calculated on a 0-4 scale by the <a href="https://github.com/dropbox/zxcvbn" target="_blank"> Zxcvbn package</a>
@@ -1,26 +0,0 @@
1
- <%= pb_rails("passphrase", props: {
2
- label: "Pass an array of strings to the tips prop",
3
- tips: ['And the info icon will appear.', 'Each string will be displayed as its own tip'],
4
- }) %>
5
-
6
- <%= pb_rails("passphrase", props: {
7
- label: "Omit the prop to hide the icon"
8
- }) %>
9
-
10
- <%= pb_rails("passphrase", props: {
11
- label: "Only show tips at small screen size",
12
- show_tips_below: "sm",
13
- tips: ['Make the password longer', 'Type more things', 'Use something else'],
14
- }) %>
15
-
16
- <%= pb_rails("passphrase", props: {
17
- label: "Only show tips at medium screen size",
18
- show_tips_below: "md",
19
- tips: ['Make the password longer', 'Type more things', 'Use something else'],
20
- }) %>
21
-
22
- <%= pb_rails("passphrase", props: {
23
- label: "Only show tips at large screen size",
24
- show_tips_below: "lg",
25
- tips: ['Make the password longer', 'Type more things', 'Use something else'],
26
- }) %>
@@ -1,54 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Passphrase } from '../../'
3
-
4
- const PassphraseTips = (props) => {
5
- const [input, setInput] = useState('')
6
-
7
- const handleChange = (e) => setInput(e.target.value)
8
-
9
- return (
10
- <>
11
- <div>
12
- <Passphrase
13
- label="Pass an array of strings to the tips prop"
14
- onChange={handleChange}
15
- tips={['And the info icon will appear.', 'Each string will be displayed as its own tip']}
16
- value={input}
17
- {...props}
18
- />
19
- <Passphrase
20
- label="Omit the prop to hide the icon"
21
- onChange={handleChange}
22
- value={input}
23
- {...props}
24
- />
25
- <Passphrase
26
- label="Only show tips at small screen size"
27
- onChange={handleChange}
28
- showTipsBelow="xs"
29
- tips={['Make the password longer', 'Type more things', 'Use something else']}
30
- value={input}
31
- {...props}
32
- />
33
- <Passphrase
34
- label="Only show tips at medium screen size"
35
- onChange={handleChange}
36
- showTipsBelow="md"
37
- tips={['Make the password longer', 'Type more things', 'Use something else']}
38
- value={input}
39
- {...props}
40
- />
41
- <Passphrase
42
- label="Only show tips at large screen size"
43
- onChange={handleChange}
44
- showTipsBelow="lg"
45
- tips={['Make the password longer', 'Type more things', 'Use something else']}
46
- value={input}
47
- {...props}
48
- />
49
- </div>
50
- </>
51
- )
52
- }
53
-
54
- export default PassphraseTips
@@ -1 +0,0 @@
1
- `showTipsBelow`(react) / `show_tips_below`(rails) takes 'xs', 'sm', 'md', 'lg', 'xl' and only show the tips below the given screen size. Similar to the <a href="/kits/table/react" target="_blank">responsive table breakpoints.</a> Omit this prop to always show.
@@ -1,15 +0,0 @@
1
- examples:
2
-
3
- rails:
4
- - passphrase_default: Default
5
- - passphrase_meter_settings: Meter Settings
6
- - passphrase_input_props: Input Props
7
- - passphrase_tips: Tips
8
-
9
- react:
10
- - passphrase_default: Default
11
- - passphrase_meter_settings: Meter Settings
12
- - passphrase_input_props: Input Props
13
- - passphrase_tips: Tips
14
- - passphrase_strength_change: Strength Change
15
- - passphrase_common: Common Passphrases
@@ -1,6 +0,0 @@
1
- export { default as PassphraseDefault } from './_passphrase_default.jsx'
2
- export { default as PassphraseMeterSettings } from './_passphrase_meter_settings'
3
- export { default as PassphraseInputProps } from './_passphrase_input_props'
4
- export { default as PassphraseTips } from './_passphrase_tips'
5
- export { default as PassphraseStrengthChange } from './_passphrase_strength_change'
6
- export { default as PassphraseCommon } from './_passphrase_common'
@@ -1 +0,0 @@
1
- <%= react_component('Passphrase', object.passphrase_options) %>
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Playbook
4
- module PbPassphrase
5
- class Passphrase < Playbook::KitBase
6
- prop :average_threshold
7
- prop :confirmation, type: Playbook::Props::Boolean, default: false
8
- prop :input_props, type: Playbook::Props::Hash, default: {}
9
- prop :label
10
- prop :min_length
11
- prop :show_tips_below
12
- prop :strong_threshold
13
- prop :tips, type: Playbook::Props::Array, default: []
14
-
15
- # prop :on_strength_change
16
- # might not need these?
17
- # prop :common
18
- # prop :on_change
19
-
20
- def classname
21
- generate_classname("pb_passphrase")
22
- end
23
-
24
- def passphrase_options
25
- {
26
- dark: dark,
27
- id: id,
28
- averageThreshold: average_threshold,
29
- confirmation: confirmation,
30
- inputProps: input_props,
31
- label: label,
32
- minLength: min_length,
33
- showTipsBelow: show_tips_below,
34
- strongThreshold: strong_threshold,
35
- tips: tips,
36
- uncontrolled: true,
37
- }.compact
38
- end
39
- end
40
- end
41
- end
@@ -1,123 +0,0 @@
1
- import React from 'react'
2
- import { render, screen } from '../utilities/test-utils'
3
- import { Passphrase } from '../'
4
-
5
- const testId = 'text-input1',
6
- kitClass = 'pb_passphrase'
7
-
8
- /* See these resources for more testing info:
9
- - https://github.com/testing-library/jest-dom#usage for useage and examples
10
- - https://jestjs.io/docs/en/using-matchers
11
- */
12
-
13
- test('returns namespaced class name', () => {
14
- render(
15
- <Passphrase
16
- data={{ testid: testId }}
17
- />
18
- )
19
-
20
- const kit = screen.getByTestId(testId)
21
- expect(kit).toHaveClass(kitClass)
22
- })
23
-
24
- test('returns additional class name', () => {
25
- render(
26
- <Passphrase
27
- className="additional_class"
28
- data={{ testid: testId }}
29
- />
30
- )
31
-
32
- const kit = screen.getByTestId(testId)
33
- expect(kit).toHaveClass(`${kitClass} additional_class`)
34
- })
35
-
36
- test('returns dark class name', () => {
37
- render(
38
- <Passphrase
39
- dark
40
- data={{ testid: testId }}
41
- />
42
- )
43
-
44
- const kit = screen.getByTestId(testId)
45
- expect(kit).toHaveClass(`${kitClass} dark`)
46
- })
47
-
48
- test('passes input props to input element', () => {
49
- render(
50
- <Passphrase
51
- data={{ testid: testId }}
52
- inputProps={{
53
- name: 'test-name',
54
- id: 'test-input-id',
55
- disabled: true,
56
- }}
57
- />
58
- )
59
-
60
- const kit = screen.getByTestId(testId)
61
- const input = kit.getElementsByTagName('input')[0]
62
- expect(input).toHaveAttribute('name', 'test-name')
63
- expect(input).toHaveAttribute('id', 'test-input-id')
64
- expect(input).toBeDisabled()
65
- })
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
- test('popover target shows when tips are given', () => {
103
- render(
104
- <Passphrase
105
- data={{ testid: testId }}
106
- tips={['some helpful tips']}
107
- />
108
- )
109
-
110
- const kit = screen.getByTestId(testId)
111
- expect(kit.querySelector('[class^=pb_popover_reference_wrapper]')).toBeDefined()
112
- })
113
-
114
- test('popover target does not show when tips are not given', () => {
115
- render(
116
- <Passphrase
117
- data={{ testid: testId }}
118
- />
119
- )
120
-
121
- const kit = screen.getByTestId(testId)
122
- expect(kit.querySelector('[class^=pb_popover_reference_wrapper]')).toBeNull()
123
- })
@@ -1,55 +0,0 @@
1
- import zxcvbn from 'zxcvbn'
2
-
3
- export const zxcvbnPasswordScore = (options) => {
4
- const {
5
- calculate = zxcvbn,
6
- averageThreshold = 2,
7
- strongThreshold = 3,
8
- minLength = 12,
9
- } = options
10
-
11
- return {
12
- minLength,
13
- averageThreshold,
14
- strongThreshold,
15
- test: function (password = '', common = false) {
16
- const feedbackValues = (str) => {
17
- let percent, variant, text
18
-
19
- if (password.length <= 0) {
20
- percent = '0'
21
- variant = 'negative'
22
- text = '\u00A0' //nbsp to keep form from jumping when typing beings
23
- } else if (common) {
24
- percent = '25'
25
- variant = 'negative'
26
- text = 'This passphrase is too common'
27
- } else if (password.length < this.minLength || str < this.averageThreshold) {
28
- percent = '25'
29
- variant = 'negative'
30
- text = 'Too weak'
31
- } else if (str < this.strongThreshold){
32
- percent = '50'
33
- variant = 'warning'
34
- text = 'Almost there, keep going!'
35
- } else if (str >= this.strongThreshold) {
36
- percent = '100'
37
- variant = 'positive'
38
- text = 'Success! Strong passphrase'
39
- }
40
- return { percent, variant, text }
41
- }
42
-
43
- const result = calculate(password)
44
-
45
- return (
46
- {
47
- suggestions: result.feedback.suggestions,
48
- warning: result.feedback.warning,
49
- strength: result.score,
50
- ...feedbackValues(result.score),
51
- }
52
- )
53
- },
54
- }
55
- }