playbook_ui 7.11.0.pre.alpha1 → 7.11.0

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.jsx +20 -3
  3. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.jsx +51 -32
  4. data/app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.jsx +3 -4
  5. data/app/pb_kits/playbook/pb_filter/Filter/index.jsx +17 -16
  6. data/app/pb_kits/playbook/pb_filter/_filter.html.erb +1 -1
  7. data/app/pb_kits/playbook/pb_filter/docs/_filter_min_width.html.erb +41 -0
  8. data/app/pb_kits/playbook/pb_filter/docs/_filter_min_width.jsx +57 -0
  9. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_sort.html.erb +2 -2
  10. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_sort.md +1 -0
  11. data/app/pb_kits/playbook/pb_filter/docs/_filter_only.html.erb +1 -1
  12. data/app/pb_kits/playbook/pb_filter/docs/example.yml +2 -0
  13. data/app/pb_kits/playbook/pb_filter/docs/index.js +1 -0
  14. data/app/pb_kits/playbook/pb_filter/filter.rb +1 -0
  15. data/app/pb_kits/playbook/pb_filter/templates/_core.html.erb +3 -1
  16. data/app/pb_kits/playbook/pb_filter/templates/_default.html.erb +1 -1
  17. data/app/pb_kits/playbook/pb_radio/_radio.jsx +4 -3
  18. data/app/pb_kits/playbook/pb_radio/docs/_radio_default.jsx +3 -0
  19. data/app/pb_kits/playbook/pb_radio/docs/index.js +1 -0
  20. data/app/pb_kits/playbook/pb_radio/radio.test.js +71 -0
  21. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_preview.html.erb +25 -0
  22. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_preview.jsx +45 -0
  23. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +3 -1
  24. data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +1 -0
  25. data/app/pb_kits/playbook/pb_select/_select.jsx +4 -3
  26. data/app/pb_kits/playbook/pb_select/select.test.js +51 -0
  27. data/app/pb_kits/playbook/pb_text_input/_text_input.jsx +8 -4
  28. data/app/pb_kits/playbook/pb_text_input/docs/_description.md +2 -1
  29. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_custom.jsx +7 -1
  30. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.jsx +78 -56
  31. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.jsx +19 -11
  32. data/app/pb_kits/playbook/pb_text_input/text_input.test.js +77 -0
  33. data/app/pb_kits/playbook/pb_textarea/_textarea.jsx +5 -5
  34. data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +10 -6
  35. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_default.html.erb +4 -4
  36. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_selectors.html.erb +17 -0
  37. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_selectors.md +3 -0
  38. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -0
  39. data/app/pb_kits/playbook/pb_tooltip/index.js +87 -37
  40. data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +3 -1
  41. data/lib/playbook.rb +0 -1
  42. data/lib/playbook/version.rb +1 -1
  43. metadata +14 -5
  44. data/lib/playbook/markdown/template_handler.rb +0 -45
@@ -1,2 +1,3 @@
1
1
  export { default as RadioDefault } from './_radio_default.jsx'
2
2
  export { default as RadioCustom } from './_radio_custom.jsx'
3
+ export { default as RadioError } from './_radio_error.jsx'
@@ -0,0 +1,71 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import Radio from './_radio'
5
+
6
+ const testId = 'radio1',
7
+ kitClass = 'pb_radio_kit'
8
+
9
+ test('returns namespaced class name', () => {
10
+ render(
11
+ <Radio
12
+ data={{ testid: testId }}
13
+ defaultChecked
14
+ label="Power"
15
+ name="Group2"
16
+ value="Power"
17
+ />
18
+ )
19
+
20
+ const kit = screen.getByTestId(testId)
21
+ expect(kit).toHaveClass(kitClass)
22
+ })
23
+
24
+ test('returns dark class name', () => {
25
+ render(
26
+ <Radio
27
+ dark
28
+ data={{ testid: testId }}
29
+ defaultChecked
30
+ label="Power"
31
+ name="Group2"
32
+ value="Power"
33
+ />
34
+ )
35
+
36
+ const kit = screen.getByTestId(testId)
37
+ expect(kit).toHaveClass(`${kitClass} dark`)
38
+ })
39
+
40
+ test('returns error class name', () => {
41
+ render(
42
+ <Radio
43
+ data={{ testid: testId }}
44
+ defaultChecked
45
+ error
46
+ label="Power"
47
+ name="Group2"
48
+ value="Power"
49
+ />
50
+ )
51
+
52
+ const kit = screen.getByTestId(testId)
53
+ expect(kit).toHaveClass(`${kitClass} error`)
54
+ })
55
+
56
+ test('returns dark + error class name', () => {
57
+ render(
58
+ <Radio
59
+ dark
60
+ data={{ testid: testId }}
61
+ defaultChecked
62
+ error
63
+ label="Power"
64
+ name="Group2"
65
+ value="Power"
66
+ />
67
+ )
68
+
69
+ const kit = screen.getByTestId(testId)
70
+ expect(kit).toHaveClass(`${kitClass} dark error`)
71
+ })
@@ -0,0 +1,25 @@
1
+
2
+ <%= pb_rails("rich_text_editor", props: { id: "content-preview-editor" }) %>
3
+ <div id="card-obfuscation" style="display:none">
4
+ <%= pb_rails("card", props: { margin_top: "md" }) do %>
5
+ <div id="content-preview" class="trix-content">
6
+ </div>
7
+ <% end %>
8
+ </div>
9
+ <%= pb_rails("button", props: { id: "preview-button", variant: "secondary", margin_top: "md" }) do %>
10
+ <span>Preview Output</span>
11
+ <% end %>
12
+
13
+ <script>
14
+ // Button event handler
15
+ const button = document.getElementById('preview-button');
16
+ button.addEventListener('click', function() {
17
+ const content = document.getElementById('content-preview-editor');
18
+ const previewArea = document.getElementById('content-preview');
19
+ const cardDiv = document.getElementById('card-obfuscation');
20
+
21
+ previewArea.innerHTML = content.value;
22
+ cardDiv.classList.add('mt_md');
23
+ cardDiv.style.display = 'block';
24
+ });
25
+ </script>
@@ -0,0 +1,45 @@
1
+ import React, { useState } from 'react'
2
+ import {
3
+ Button,
4
+ Card,
5
+ RichTextEditor,
6
+ } from '../../'
7
+
8
+ const RichTextEditorPreview = () => {
9
+ const [showPreview, setShowPreview] = useState(false)
10
+ const [previewText, setPreviewText] = useState(<div />)
11
+
12
+ const handleChange = (event) => setPreviewText(event)
13
+ const handleClick = () => {
14
+ setShowPreview(true)
15
+ }
16
+
17
+ return (
18
+ <div>
19
+ <RichTextEditor
20
+ id="content-preview-editor"
21
+ onChange={handleChange}
22
+ />
23
+ <If condition={showPreview}>
24
+ <Card marginTop="md">
25
+ <div
26
+ className="trix-content"
27
+ // eslint-disable-next-line react/no-danger
28
+ dangerouslySetInnerHTML={{ __html: previewText }}
29
+ id="preview-content"
30
+ />
31
+ </Card>
32
+ <Else />
33
+ <div />
34
+ </If>
35
+ <Button
36
+ id="preview-button"
37
+ marginTop="md"
38
+ onClick={handleClick}
39
+ text="Preview Output"
40
+ variant="secondary"
41
+ />
42
+ </div>
43
+ )
44
+ }
45
+ export default RichTextEditorPreview
@@ -1,11 +1,12 @@
1
1
  examples:
2
-
2
+
3
3
  rails:
4
4
  - rich_text_editor_default: Default
5
5
  - rich_text_editor_simple: Simple
6
6
  - rich_text_editor_focus: Focus
7
7
  - rich_text_editor_sticky: Sticky
8
8
  - rich_text_editor_templates: Templates
9
+ - rich_text_editor_preview: Preview
9
10
 
10
11
  react:
11
12
  - rich_text_editor_default: Default
@@ -13,3 +14,4 @@ examples:
13
14
  - rich_text_editor_focus: Focus
14
15
  - rich_text_editor_sticky: Sticky
15
16
  - rich_text_editor_templates: Templates
17
+ - rich_text_editor_preview: Preview
@@ -3,3 +3,4 @@ export { default as RichTextEditorSimple } from './_rich_text_editor_simple.jsx'
3
3
  export { default as RichTextEditorFocus } from './_rich_text_editor_focus.jsx'
4
4
  export { default as RichTextEditorSticky } from './_rich_text_editor_sticky.jsx'
5
5
  export { default as RichTextEditorTemplates } from './_rich_text_editor_templates.jsx'
6
+ export { default as RichTextEditorPreview } from './_rich_text_editor_preview.jsx'
@@ -1,6 +1,6 @@
1
1
  /* @flow */
2
2
 
3
- import React from 'react'
3
+ import React, { forwardRef } from 'react'
4
4
  import classnames from 'classnames'
5
5
  import {
6
6
  Body,
@@ -69,7 +69,7 @@ const Select = ({
69
69
  required = false,
70
70
  value,
71
71
  ...props
72
- }: SelectProps) => {
72
+ }: SelectProps, ref: React.ElementRef<"select">) => {
73
73
  const ariaProps = buildAriaProps(aria)
74
74
  const dataProps = buildDataProps(data)
75
75
  const optionsList = createOptions(options)
@@ -107,6 +107,7 @@ const Select = ({
107
107
  multiple={multiple}
108
108
  name={name}
109
109
  onChange={onChange}
110
+ ref={ref}
110
111
  required={required}
111
112
  value={value}
112
113
  >
@@ -132,4 +133,4 @@ const Select = ({
132
133
  )
133
134
  }
134
135
 
135
- export default Select
136
+ export default forwardRef(Select)
@@ -0,0 +1,51 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import Select from './_select'
5
+
6
+ const testId = 'select1',
7
+ kitClass = 'pb_select'
8
+
9
+ const options = [
10
+ {
11
+ value: '1',
12
+ text: 'Burgers',
13
+ },
14
+ {
15
+ value: '2',
16
+ text: 'Pizza',
17
+ },
18
+ {
19
+ value: '3',
20
+ text: 'Tacos',
21
+ },
22
+ ]
23
+
24
+ test('returns namespaced class name', () => {
25
+ render(
26
+ <Select
27
+ data={{ testid: testId }}
28
+ label="Favorite Food"
29
+ name="food"
30
+ options={options}
31
+ />
32
+ )
33
+
34
+ const kit = screen.getByTestId(testId)
35
+ expect(kit).toHaveClass(kitClass)
36
+ })
37
+
38
+ test('returns dark class name', () => {
39
+ render(
40
+ <Select
41
+ dark
42
+ data={{ testid: testId }}
43
+ label="Favorite Food"
44
+ name="food"
45
+ options={options}
46
+ />
47
+ )
48
+
49
+ const kit = screen.getByTestId(testId)
50
+ expect(kit).toHaveClass(`${kitClass} dark`)
51
+ })
@@ -1,5 +1,5 @@
1
1
  /* @flow */
2
- import React from 'react'
2
+ import React, { forwardRef } from 'react'
3
3
  import classnames from 'classnames'
4
4
  import { Body, Caption } from '../'
5
5
  import { globalProps } from '../utilities/globalProps.js'
@@ -27,7 +27,10 @@ type TextInputProps = {
27
27
  children: Node,
28
28
  }
29
29
 
30
- const TextInput = (props: TextInputProps) => {
30
+ const TextInput = (
31
+ props: TextInputProps,
32
+ ref: React.ElementRef<"input">
33
+ ) => {
31
34
  const {
32
35
  aria = {},
33
36
  className,
@@ -42,7 +45,7 @@ const TextInput = (props: TextInputProps) => {
42
45
  placeholder,
43
46
  required,
44
47
  type = 'text',
45
- value,
48
+ value = '',
46
49
  children = null,
47
50
  } = props
48
51
 
@@ -78,6 +81,7 @@ const TextInput = (props: TextInputProps) => {
78
81
  name={name}
79
82
  onChange={onChange}
80
83
  placeholder={placeholder}
84
+ ref={ref}
81
85
  required={required}
82
86
  type={type}
83
87
  value={value}
@@ -94,4 +98,4 @@ const TextInput = (props: TextInputProps) => {
94
98
  )
95
99
  }
96
100
 
97
- export default TextInput
101
+ export default forwardRef(TextInput)
@@ -1 +1,2 @@
1
- Area where user can enter small amount of text. Commonly used in forms.
1
+ Area where user can enter small amount of text. Commonly used in forms.<br/>
2
+ <strong>Note:</strong> This kit does not handle form validation logic.
@@ -1,7 +1,11 @@
1
- import React from 'react'
1
+ import React, { useState } from 'react'
2
2
  import { TextInput } from '../../'
3
3
 
4
4
  const TextInputCustom = () => {
5
+ const [name, setName] = useState('')
6
+ const handleUpdateName = ({ target }) => {
7
+ setName(target.value)
8
+ }
5
9
  return (
6
10
  <div>
7
11
  <TextInput
@@ -9,8 +13,10 @@ const TextInputCustom = () => {
9
13
  >
10
14
  <input
11
15
  name="custom-name"
16
+ onChange={handleUpdateName}
12
17
  placeholder="custom-placeholder"
13
18
  type="text"
19
+ value={name}
14
20
  />
15
21
  </TextInput>
16
22
  </div>
@@ -1,75 +1,97 @@
1
- import React from 'react'
1
+ import React, { useState } from 'react'
2
2
  import {
3
3
  Caption,
4
4
  TextInput,
5
5
  Title,
6
6
  } from '../../'
7
7
 
8
- class TextInputDefault extends React.Component {
9
- state = {
10
- firstName: '',
8
+ const TextInputDefault = () => {
9
+ const handleOnChangeFirstName = ({ target }) => {
10
+ setFirstName(target.value)
11
11
  }
12
+ const ref = React.createRef()
12
13
 
13
- render() {
14
- const handleOnChange = ({ target }) => this.setState({ firstName: target.value })
14
+ const [firstName, setFirstName] = useState('')
15
+ const [formFields, setFormFields] = useState({
16
+ firstName: 'Jane',
17
+ lastName: 'Doe',
18
+ phone: '8888888888',
19
+ email: 'jane@doe.com',
20
+ zip: 55555,
21
+ })
15
22
 
16
- const {
17
- firstName,
18
- } = this.state
23
+ const handleOnChangeFormField = ({ target }) => {
24
+ const { name, value } = target
25
+ setFormFields({ ...formFields, [name]: value })
26
+ }
19
27
 
20
- return (
21
- <div>
22
- <TextInput
23
- aria={{ label: 'hello' }}
24
- data={{ say: 'hi', yell: 'go' }}
25
- id="unique-id"
26
- label="First Name"
27
- placeholder="Enter first name"
28
- value="Timothy Wenhold"
29
- />
30
- <TextInput
31
- label="Last Name"
32
- placeholder="Enter last name"
33
- />
34
- <TextInput
35
- label="Phone Number"
36
- placeholder="Enter phone number"
37
- type="phone"
38
- />
39
- <TextInput
40
- label="Email Address"
41
- placeholder="Enter email address"
42
- type="email"
43
- />
44
- <TextInput
45
- label="Zip Code"
46
- placeholder="Enter zip code"
47
- type="number"
48
- />
28
+ return (
29
+ <div>
30
+ <TextInput
31
+ aria={{ label: 'hello' }}
32
+ data={{ say: 'hi', yell: 'go' }}
33
+ id="unique-id"
34
+ label="First Name"
35
+ name="firstName"
36
+ onChange={handleOnChangeFormField}
37
+ placeholder="Enter first name"
38
+ value={formFields.firstName}
39
+ />
40
+ <TextInput
41
+ label="Last Name"
42
+ name="lastName"
43
+ onChange={handleOnChangeFormField}
44
+ placeholder="Enter last name"
45
+ value={formFields.lastName}
46
+ />
47
+ <TextInput
48
+ label="Phone Number"
49
+ name="phone"
50
+ onChange={handleOnChangeFormField}
51
+ placeholder="Enter phone number"
52
+ type="phone"
53
+ value={formFields.phone}
54
+ />
55
+ <TextInput
56
+ label="Email Address"
57
+ name="email"
58
+ onChange={handleOnChangeFormField}
59
+ placeholder="Enter email address"
60
+ type="email"
61
+ value={formFields.email}
62
+ />
63
+ <TextInput
64
+ label="Zip Code"
65
+ name="zip"
66
+ onChange={handleOnChangeFormField}
67
+ placeholder="Enter zip code"
68
+ type="number"
69
+ value={formFields.zip}
70
+ />
49
71
 
50
- <br />
51
- <br />
72
+ <br />
73
+ <br />
52
74
 
53
- <Title>{'Event Handler Props'}</Title>
75
+ <Title>{'Event Handler Props'}</Title>
54
76
 
55
- <br />
56
- <Caption>{'onChange'}</Caption>
77
+ <br />
78
+ <Caption>{'onChange'}</Caption>
57
79
 
58
- <br />
80
+ <br />
59
81
 
60
- <TextInput
61
- label="First Name"
62
- onChange={handleOnChange}
63
- placeholder="Enter first name"
64
- value={firstName}
65
- />
82
+ <TextInput
83
+ label="First Name"
84
+ onChange={handleOnChangeFirstName}
85
+ placeholder="Enter first name"
86
+ ref={ref}
87
+ value={firstName}
88
+ />
66
89
 
67
- <If condition={firstName !== ''}>
68
- {`First name is: ${firstName}`}
69
- </If>
70
- </div>
71
- )
72
- }
90
+ <If condition={firstName !== ''}>
91
+ {`First name is: ${firstName}`}
92
+ </If>
93
+ </div>
94
+ )
73
95
  }
74
96
 
75
97
  export default TextInputDefault