playbook_ui 8.2.1.alpha.iconacc → 8.2.1.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +18 -1
  3. data/app/pb_kits/playbook/_playbook.scss +1 -0
  4. data/app/pb_kits/playbook/data/menu.yml +1 -0
  5. data/app/pb_kits/playbook/index.js +1 -0
  6. data/app/pb_kits/playbook/pb_badge/_badge.jsx +26 -1
  7. data/app/pb_kits/playbook/pb_date_picker/_date_picker.jsx +6 -0
  8. data/app/pb_kits/playbook/pb_icon/_icon.jsx +5 -20
  9. data/app/pb_kits/playbook/pb_icon/icon.html.erb +2 -4
  10. data/app/pb_kits/playbook/pb_inline/_inline.jsx +83 -0
  11. data/app/pb_kits/playbook/pb_inline/_inline.scss +58 -0
  12. data/app/pb_kits/playbook/pb_inline/docs/_inline_default.jsx +36 -0
  13. data/app/pb_kits/playbook/pb_inline/docs/_inline_input_options.jsx +58 -0
  14. data/app/pb_kits/playbook/pb_inline/docs/_inline_text_options.jsx +99 -0
  15. data/app/pb_kits/playbook/pb_inline/docs/example.yml +5 -0
  16. data/app/pb_kits/playbook/pb_inline/docs/index.js +3 -0
  17. data/app/pb_kits/playbook/pb_inline/inline.test.jsx +21 -0
  18. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.jsx +0 -1
  19. data/app/pb_kits/playbook/pb_loading_inline/loading_inline.html.erb +1 -1
  20. data/app/pb_kits/playbook/pb_nav/_item.jsx +2 -0
  21. data/app/pb_kits/playbook/pb_nav/item.html.erb +2 -2
  22. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.jsx +4 -3
  23. data/app/pb_kits/playbook/pb_text_input/_text_input.jsx +3 -0
  24. data/app/pb_kits/playbook/pb_textarea/_textarea.jsx +3 -0
  25. data/app/pb_kits/playbook/pb_typeahead/_typeahead.jsx +9 -1
  26. data/app/pb_kits/playbook/pb_typeahead/components/Input.jsx +24 -0
  27. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx +25 -2
  28. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_default.jsx +1 -0
  29. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills.jsx +8 -3
  30. data/lib/playbook/version.rb +1 -1
  31. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7526c42c57c64b2f20becc559569747cda234e5478190b62e170ad5be74ac4a
4
- data.tar.gz: c2167d4d617d1fa829b96ee32d6b8ca490734b416dabd261806756868b6b4431
3
+ metadata.gz: 8cbf51b2d7235622879cdc471204d3becf81ea6002ea3c7951c3d5ffd7edc09a
4
+ data.tar.gz: 515a63cbc2842c17b189a127e5efb8920c0ebd046e43a1c549fb85e1141bd3b5
5
5
  SHA512:
6
- metadata.gz: 61791c852673487ced56bfa3eb2e47c336017172b79ecb447ff48fb02d5b800ce85cb335f93347d7771c7e5dbe5ce2c92ba8ddf4d4dc07d776516de703d47e77
7
- data.tar.gz: af3ccf64210ecba24d6898579f51333f3b9be8e8f85d6d4feb6cf1ca5002e927f63e70eb2c51188270dde52b85f228c1f789acda840a7931b7b39327e6c23539
6
+ metadata.gz: 5512cbf48886764a35bbef6252f89d6472ec869232f8ff628e015ee9f2c78884443bcd0fee4cda2d6063bd6ee714936b9b1d535d8e52e58d60a08246460843d9
7
+ data.tar.gz: 32e359b3596106cc2ee242cb4a7cf390f5a575b13713397351568ccc75d56bdb796b29e5e5cbc030ead10766a1893c4118f6d69eb4c6065ace18e12f092fff29
data/Rakefile CHANGED
@@ -4,12 +4,29 @@ rescue LoadError
4
4
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
5
  end
6
6
 
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Playbook'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
7
17
  APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
8
18
  load 'rails/tasks/engine.rake'
19
+
9
20
  load 'rails/tasks/statistics.rake'
10
21
 
11
22
  require 'bundler/gem_tasks'
12
23
 
13
- Dir["private/tasks/*.rake"].each(&method(:load))
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'spec/**/*_spec.rb'
29
+ t.verbose = false
30
+ end
14
31
 
15
32
  task default: :test
@@ -43,6 +43,7 @@
43
43
  @import 'pb_icon_stat_value/icon_stat_value';
44
44
  @import 'pb_icon_value/icon_value';
45
45
  @import 'pb_image/image';
46
+ @import 'pb_inline/inline';
46
47
  @import 'pb_label_pill/label_pill';
47
48
  @import 'pb_label_value/label_value';
48
49
  @import 'pb_layout/layout';
@@ -42,6 +42,7 @@ kits:
42
42
  - icon_stat_value
43
43
  - icon_value
44
44
  - image
45
+ - inline
45
46
  - layout
46
47
  - list
47
48
  - loading_inline
@@ -47,6 +47,7 @@ export IconCircle from './pb_icon_circle/_icon_circle.jsx'
47
47
  export IconStatValue from './pb_icon_stat_value/_icon_stat_value.jsx'
48
48
  export IconValue from './pb_icon_value/_icon_value.jsx'
49
49
  export Image from './pb_image/_image.jsx'
50
+ export Inline from './pb_inline/_inline.jsx'
50
51
  export LabelPill from './pb_label_pill/_label_pill.jsx'
51
52
  export LabelValue from './pb_label_value/_label_value.jsx'
52
53
  export Layout from './pb_layout/_layout.jsx'
@@ -3,6 +3,7 @@
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
5
  import { globalProps } from '../utilities/globalProps.js'
6
+ import { Icon } from '../'
6
7
 
7
8
  import {
8
9
  buildAriaProps,
@@ -13,8 +14,15 @@ import {
13
14
  type BadgeProps = {
14
15
  aria?: object,
15
16
  className?: string,
17
+ closeProps?: {
18
+ onClick?: EventHandler,
19
+ onMouseDown?: EventHandler,
20
+ onTouchEnd?: EventHandler,
21
+ },
16
22
  data?: object,
17
23
  id?: string,
24
+ removeIcon?: Boolean,
25
+ removeOnClick?: EventHandler,
18
26
  rounded?: boolean,
19
27
  text?: string,
20
28
  variant?: "error" | "info" | "neutral" | "primary" | "success" | "warning",
@@ -23,8 +31,11 @@ const Badge = (props: BadgeProps) => {
23
31
  const {
24
32
  aria = {},
25
33
  className,
34
+ closeProps = {},
26
35
  data = {},
27
36
  id,
37
+ removeIcon = false,
38
+ removeOnClick = () => {},
28
39
  rounded = false,
29
40
  text,
30
41
  variant = 'neutral',
@@ -44,7 +55,21 @@ const Badge = (props: BadgeProps) => {
44
55
  className={css}
45
56
  id={id}
46
57
  >
47
- <span>{text}</span>
58
+ <span>
59
+ <If condition={removeIcon}>
60
+ <span
61
+ onClick={removeOnClick}
62
+ style={{ cursor: 'pointer' }}
63
+ {...closeProps}
64
+ >
65
+ <Icon
66
+ fixedWidth
67
+ icon="times"
68
+ />
69
+ </span>
70
+ </If>
71
+ {text}
72
+ </span>
48
73
  </div>
49
74
  )
50
75
  }
@@ -25,6 +25,8 @@ type DatePickerProps = {
25
25
  id?: String,
26
26
  inputAria?: object,
27
27
  inputData?: object,
28
+ inputOnChange?: (String) => void,
29
+ inputValue?: any,
28
30
  label?: String,
29
31
  maxDate: String,
30
32
  minDate: String,
@@ -55,6 +57,8 @@ const DatePicker = (props: DatePickerProps) => {
55
57
  id,
56
58
  inputAria,
57
59
  inputData,
60
+ inputOnChange,
61
+ inputValue,
58
62
  label = 'Date Picker',
59
63
  maxDate,
60
64
  minDate,
@@ -126,7 +130,9 @@ const DatePicker = (props: DatePickerProps) => {
126
130
  id={pickerId}
127
131
  label={hideLabel ? null : label}
128
132
  name={name}
133
+ onChange={inputOnChange}
129
134
  placeholder={placeholder}
135
+ value={inputValue}
130
136
  />
131
137
  <If condition={!hideIcon}>
132
138
  <div
@@ -2,14 +2,12 @@
2
2
 
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
- import { buildAriaProps, buildDataProps } from '../utilities/props'
6
5
  import { globalProps } from '../utilities/globalProps.js'
7
6
 
8
7
  type IconProps = {
9
- aria?: object,
8
+ aria?: Object,
10
9
  border?: boolean,
11
10
  className?: string,
12
- data?: object,
13
11
  fixedWidth?: boolean,
14
12
  flip?: "horizontal" | "vertical" | "both" | "none",
15
13
  icon: string,
@@ -43,10 +41,8 @@ const flipMap = {
43
41
 
44
42
  const Icon = (props: IconProps) => {
45
43
  const {
46
- aria = {},
47
44
  border = false,
48
45
  className,
49
- data = {},
50
46
  fixedWidth = true,
51
47
  flip = false,
52
48
  icon,
@@ -79,22 +75,11 @@ const Icon = (props: IconProps) => {
79
75
  className
80
76
  )
81
77
 
82
- aria.label ? null : aria.label = `${icon} icon`
83
- const ariaProps = buildAriaProps(aria)
84
- const dataProps = buildDataProps(data)
85
-
86
78
  return (
87
- <>
88
- <i
89
- {...dataProps}
90
- className={classes}
91
- id={id}
92
- />
93
- <span
94
- {...ariaProps}
95
- hidden="true"
96
- />
97
- </>
79
+ <i
80
+ className={classes}
81
+ id={id}
82
+ />
98
83
  )
99
84
  }
100
85
 
@@ -1,7 +1,5 @@
1
1
  <%= content_tag(:i, nil,
2
2
  id: object.id,
3
3
  data: object.data,
4
- class: object.classname ) %>
5
- <%= content_tag(:span, nil,
6
- aria: { label: "#{object.icon} icon" }.merge(object.aria),
7
- hidden: true ) %>
4
+ class: object.classname,
5
+ aria: object.aria) %>
@@ -0,0 +1,83 @@
1
+ /* @flow */
2
+
3
+ import React, { useEffect, useRef, useState } from 'react'
4
+ import classnames from 'classnames'
5
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
6
+ import { globalProps } from '../utilities/globalProps.js'
7
+ import './_inline.scss'
8
+
9
+ type InlineProps = {
10
+ aria?: object,
11
+ className?: string,
12
+ data?: object,
13
+ displayKit?: React.Node,
14
+ formInput?: React.Node,
15
+ id?: string,
16
+ }
17
+
18
+ const Inline = (props: InlineProps) => {
19
+ const {
20
+ aria = {},
21
+ className,
22
+ data = {},
23
+ displayKit,
24
+ id,
25
+ formInput,
26
+ } = props
27
+
28
+ const ariaProps = buildAriaProps(aria)
29
+ const dataProps = buildDataProps(data)
30
+ const classes = classnames(buildCss('pb_inline'), globalProps(props), className)
31
+
32
+ const [editing, setEditing] = useState(false)
33
+
34
+ const ToggleClickHandler = () => {
35
+ setEditing(!editing)
36
+ }
37
+
38
+ useEffect(() => {
39
+ if (editing) {
40
+ modifiedInput.ref.current.focus()
41
+
42
+ modifiedInput.ref.current.addEventListener('keydown', (e) => {
43
+ if (e.key === 'Escape' || e.key === 'Enter') {
44
+ setEditing(!editing)
45
+ }
46
+ })
47
+ }
48
+ }, [editing])
49
+
50
+ const { kitType, size } = displayKit.props
51
+ const textInputClassName = kitType ? (kitType.toLowerCase() + (size ? `_${size}` : '')) : ''
52
+
53
+ const modifiedInput = React.cloneElement(formInput, {
54
+ className: textInputClassName,
55
+ onBlur: () => setEditing(!editing),
56
+ ref: useRef(null),
57
+ })
58
+
59
+ return (
60
+ <div
61
+ {...ariaProps}
62
+ {...dataProps}
63
+ className={classes}
64
+ id={id}
65
+ >
66
+ <If condition={editing}>
67
+ {modifiedInput}
68
+ </If>
69
+ <If condition={!editing}>
70
+ <div
71
+ onClick={() => ToggleClickHandler()}
72
+ onFocus={() => ToggleClickHandler()}
73
+ tabIndex="0"
74
+ >
75
+ {displayKit}
76
+ </div>
77
+ </If>
78
+
79
+ </div>
80
+ )
81
+ }
82
+
83
+ export default Inline
@@ -0,0 +1,58 @@
1
+ @import "../pb_title/title_mixin";
2
+ @import "../pb_body/body_mixins";
3
+ @import "../pb_caption/caption_mixin";
4
+
5
+ .pb_inline {
6
+ .pb_text_input_kit {
7
+ &.title_1 {
8
+ .text_input_wrapper input {
9
+ @include pb_title_1;
10
+ }
11
+ &.dark .text_input_wrapper input {
12
+ @include pb_title_1;
13
+ @include pb_title_dark;
14
+ }
15
+ }
16
+ &.title_2 {
17
+ .text_input_wrapper input {
18
+ @include pb_title_2;
19
+ }
20
+ &.dark .text_input_wrapper input {
21
+ @include pb_title_2;
22
+ @include pb_title_dark;
23
+ }
24
+ }
25
+ &.title_3 {
26
+ .text_input_wrapper input {
27
+ @include pb_title_3;
28
+ }
29
+ &.dark .text_input_wrapper input {
30
+ @include pb_title_3;
31
+ @include pb_title_dark;
32
+ }
33
+ }
34
+ &.body {
35
+ .text_input_wrapper input {
36
+ @include pb_body;
37
+ }
38
+ &.dark .text_input_wrapper input {
39
+ @include pb_body_dark;
40
+ }
41
+ }
42
+ &.caption {
43
+ .text_input_wrapper input {
44
+ @include caption;
45
+ }
46
+ &.dark .text_input_wrapper input {
47
+ @include caption;
48
+ @include caption_dark;
49
+ }
50
+ }
51
+ .text_input_wrapper input {
52
+ padding: 8px 5px;
53
+ }
54
+ .text_input_wrapper, .pb_textarea_kit {
55
+ margin-bottom: 0;
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,36 @@
1
+ import React, { useState } from 'react'
2
+ import { Inline, TextInput, Title } from '../../'
3
+
4
+ const InlineDefault = (props) => {
5
+ const [formValue, setFormValue] = useState('Default Value')
6
+
7
+ const handleInputChange = (event) => {
8
+ setFormValue(event.target.value)
9
+ }
10
+
11
+ return (
12
+ <div>
13
+ <Inline
14
+ {...props}
15
+ displayKit={
16
+ <Title
17
+ {...props}
18
+ kitType="Title"
19
+ size={4}
20
+ tag="h4"
21
+ text={formValue}
22
+ />
23
+ }
24
+ formInput={
25
+ <TextInput
26
+ {...props}
27
+ onChange={handleInputChange}
28
+ value={formValue}
29
+ />
30
+ }
31
+ />
32
+ </div>
33
+ )
34
+ }
35
+
36
+ export default InlineDefault
@@ -0,0 +1,58 @@
1
+ import React, { useState } from 'react'
2
+ import { Body, Inline, Textarea, TextInput } from '../../'
3
+
4
+ const InlineInputOptions = (props) => {
5
+ const [formFields, setFormFields] = useState({
6
+ inputOne: 'Input One',
7
+ inputTwo: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
8
+ })
9
+
10
+ const handleChange = ({ target }) => {
11
+ const { name, value } = target
12
+ setFormFields({ ...formFields, [name]: value })
13
+ }
14
+
15
+ return (
16
+ <div>
17
+ <Inline
18
+ {...props}
19
+ displayKit={
20
+ <Body
21
+ {...props}
22
+ kitType="Body"
23
+ text={formFields.inputOne}
24
+ />
25
+ }
26
+ formInput={
27
+ <TextInput
28
+ {...props}
29
+ name="inputOne"
30
+ onChange={handleChange}
31
+ value={formFields.inputOne}
32
+ />
33
+ }
34
+ />
35
+ <Inline
36
+ {...props}
37
+ displayKit={
38
+ <Body
39
+ {...props}
40
+ kitType="Body"
41
+ text={formFields.inputTwo}
42
+ />
43
+ }
44
+ formInput={
45
+ <Textarea
46
+ {...props}
47
+ name="inputTwo"
48
+ onChange={handleChange}
49
+ resize="auto"
50
+ value={formFields.inputTwo}
51
+ />
52
+ }
53
+ />
54
+ </div>
55
+ )
56
+ }
57
+
58
+ export default InlineInputOptions
@@ -0,0 +1,99 @@
1
+ import React, { useState } from 'react'
2
+ import { Body, Caption, Inline, TextInput, Title } from '../../'
3
+
4
+ const InlineTextOptions = (props) => {
5
+ const [formFields, setFormFields] = useState({
6
+ inputOne: 'Input One',
7
+ inputTwo: 'Input Two',
8
+ inputThree: 'Input Three',
9
+ inputFour: 'Input Four',
10
+ })
11
+
12
+ const handleChange = ({ target }) => {
13
+ const { name, value } = target
14
+ setFormFields({ ...formFields, [name]: value })
15
+ }
16
+
17
+ return (
18
+ <div>
19
+ <Inline
20
+ {...props}
21
+ displayKit={
22
+ <Title
23
+ {...props}
24
+ kitType="Title"
25
+ size={1}
26
+ tag="h1"
27
+ text={formFields.inputOne}
28
+ />
29
+ }
30
+ formInput={
31
+ <TextInput
32
+ {...props}
33
+ name="inputOne"
34
+ onChange={handleChange}
35
+ value={formFields.inputOne}
36
+ />
37
+ }
38
+ />
39
+ <Inline
40
+ {...props}
41
+ displayKit={
42
+ <Title
43
+ {...props}
44
+ kitType="Title 4"
45
+ size={4}
46
+ tag="h4"
47
+ text={formFields.inputTwo}
48
+ />
49
+ }
50
+ formInput={
51
+ <TextInput
52
+ {...props}
53
+ name="inputTwo"
54
+ onChange={handleChange}
55
+ value={formFields.inputTwo}
56
+ />
57
+ }
58
+ />
59
+ <Inline
60
+ {...props}
61
+ displayKit={
62
+ <Body
63
+ {...props}
64
+ kitType="Body"
65
+ text={formFields.inputThree}
66
+ />
67
+ }
68
+ formInput={
69
+ <TextInput
70
+ {...props}
71
+ name="inputThree"
72
+ onChange={handleChange}
73
+ value={formFields.inputThree}
74
+ />
75
+ }
76
+ />
77
+ <Inline
78
+ {...props}
79
+ displayKit={
80
+ <Caption
81
+ {...props}
82
+ kitType="Caption"
83
+ text={formFields.inputFour}
84
+ />
85
+ }
86
+ formInput={
87
+ <TextInput
88
+ {...props}
89
+ name="inputFour"
90
+ onChange={handleChange}
91
+ value={formFields.inputFour}
92
+ />
93
+ }
94
+ />
95
+ </div>
96
+ )
97
+ }
98
+
99
+ export default InlineTextOptions
@@ -0,0 +1,5 @@
1
+ examples:
2
+ react:
3
+ - inline_default: Default
4
+ - inline_text_options: Text Options
5
+ - inline_input_options: Input Options
@@ -0,0 +1,3 @@
1
+ export { default as InlineDefault } from './_inline_default.jsx'
2
+ export { default as InlineTextOptions } from './_inline_text_options.jsx'
3
+ export { default as InlineInputOptions } from './_inline_input_options.jsx'
@@ -0,0 +1,21 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+ import { Inline } from '../'
4
+
5
+ /* See these resources for more testing info:
6
+ - https://github.com/testing-library/jest-dom#usage for useage and examples
7
+ - https://jestjs.io/docs/en/using-matchers
8
+ */
9
+
10
+ test('generated scaffold test - update me', () => {
11
+ const testId = "test1"
12
+
13
+ render(
14
+ <Inline
15
+ data={{ testid: testId }}
16
+ />
17
+ )
18
+
19
+ const kit = screen.getByTestId(testId)
20
+ expect(kit).toBeInTheDocument()
21
+ })
@@ -22,7 +22,6 @@ const LoadingInline = (props: LoadingInlineProps) => {
22
22
  >
23
23
  <Body color="light">
24
24
  <Icon
25
- aria={{ label: 'loading icon' }}
26
25
  fixedWidth
27
26
  icon="spinner"
28
27
  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: { aria: { label: "loading icon" }, fixed_width: true, icon: "spinner", pulse: true }) %> Loading
7
+ <%= pb_rails("icon", props: { fixed_width: true, icon: "spinner", pulse: true }) %> Loading
8
8
  <% end %>
9
9
  <% end %>
@@ -75,6 +75,7 @@ const NavItem = (props: NavItemProps) => {
75
75
  key={iconLeft}
76
76
  >
77
77
  <Icon
78
+ aria={{ label: iconLeft }}
78
79
  className="pb_nav_list_item_icon_left"
79
80
  fixedWidth
80
81
  icon={iconLeft}
@@ -90,6 +91,7 @@ const NavItem = (props: NavItemProps) => {
90
91
  key={iconRight}
91
92
  >
92
93
  <Icon
94
+ aria={{ label: iconRight }}
93
95
  className="pb_nav_list_item_icon_right"
94
96
  fixedWidth
95
97
  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: { icon: object.icon_left, classname: "pb_nav_list_item_icon_left", fixed_width: true}) %>
12
+ <%= pb_rails("icon", props: { aria: { label: object.icon_left }, 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: { icon: object.icon_right, classname: "pb_nav_list_item_icon_right", fixed_width: true}) %>
18
+ <%= pb_rails("icon", props: { aria: { label: object.icon_right }, icon: object.icon_right, classname: "pb_nav_list_item_icon_right", fixed_width: true}) %>
19
19
  <% end %>
20
20
  <% end %>
21
21
  <% end %>
@@ -1,6 +1,6 @@
1
1
  /* @flow */
2
2
 
3
- import React, { useEffect, useRef } from 'react'
3
+ import React, { forwardRef, useEffect, useRef } from 'react'
4
4
  import classnames from 'classnames'
5
5
  import useFocus from './useFocus.js'
6
6
  import Trix from 'trix'
@@ -22,7 +22,7 @@ type RichTextEditorProps = {
22
22
  value?: string,
23
23
  }
24
24
 
25
- const RichTextEditor = (props: RichTextEditorProps) => {
25
+ const RichTextEditor = (props: RichTextEditorProps, ref: React.ElementRef<"input">) => {
26
26
  const {
27
27
  aria = {},
28
28
  className,
@@ -120,6 +120,7 @@ const RichTextEditor = (props: RichTextEditorProps) => {
120
120
  <input
121
121
  id={id}
122
122
  name={name}
123
+ ref={ref}
123
124
  type="hidden"
124
125
  value={value}
125
126
  />
@@ -133,4 +134,4 @@ const RichTextEditor = (props: RichTextEditorProps) => {
133
134
  )
134
135
  }
135
136
 
136
- export default RichTextEditor
137
+ export default forwardRef(RichTextEditor)
@@ -19,6 +19,7 @@ type TextInputProps = {
19
19
  id?: string,
20
20
  name: string,
21
21
  label: string,
22
+ onBlur: (String) => void,
22
23
  onChange: (String) => void,
23
24
  placeholder: string,
24
25
  required?: boolean,
@@ -41,6 +42,7 @@ const TextInput = (
41
42
  id,
42
43
  name,
43
44
  label,
45
+ onBlur = () => {},
44
46
  onChange = () => {},
45
47
  placeholder,
46
48
  required,
@@ -79,6 +81,7 @@ const TextInput = (
79
81
  disabled={disabled}
80
82
  id={id}
81
83
  name={name}
84
+ onBlur={onBlur}
82
85
  onChange={onChange}
83
86
  placeholder={placeholder}
84
87
  ref={ref}
@@ -24,6 +24,7 @@ type TextareaProps = {
24
24
  required?: boolean,
25
25
  rows?: number,
26
26
  resize: 'none' | 'both' | 'horizontal' | 'vertical' | 'auto',
27
+ onBlur?: InputCallback<HTMLTextAreaElement>,
27
28
  onChange?: InputCallback<HTMLTextAreaElement>,
28
29
  }
29
30
 
@@ -37,6 +38,7 @@ const Textarea = ({
37
38
  label,
38
39
  maxCharacters,
39
40
  name,
41
+ onBlur = () => {},
40
42
  onChange = () => {},
41
43
  placeholder,
42
44
  required,
@@ -75,6 +77,7 @@ const Textarea = ({
75
77
  className="pb_textarea_kit"
76
78
  disabled={disabled}
77
79
  name={name}
80
+ onBlur={onBlur}
78
81
  onChange={onChange}
79
82
  placeholder={placeholder}
80
83
  ref={ref}
@@ -3,12 +3,14 @@
3
3
  import React from 'react'
4
4
  import Select from 'react-select'
5
5
  import AsyncSelect from 'react-select/async'
6
+ import CreateableSelect from 'react-select/creatable'
6
7
  import { get } from 'lodash'
7
8
  import { globalProps } from '../utilities/globalProps.js'
8
9
 
9
10
  import Control from './components/Control'
10
11
  import ClearIndicator from './components/ClearIndicator'
11
12
  import IndicatorsContainer from './components/IndicatorsContainer'
13
+ import Input from './components/Input'
12
14
  import MenuList from './components/MenuList'
13
15
  import MultiValue from './components/MultiValue'
14
16
  import Option from './components/Option'
@@ -26,6 +28,7 @@ import { noop } from '../utilities/props'
26
28
 
27
29
  type Props = {
28
30
  async?: boolean,
31
+ createable?: boolean,
29
32
  dark?: boolean,
30
33
  label?: string,
31
34
  loadOptions?: noop | string,
@@ -41,12 +44,14 @@ type Props = {
41
44
 
42
45
  const Typeahead = (props: Props) => {
43
46
  const selectProps = {
47
+ badges: false,
44
48
  cacheOptions: true,
45
49
  components: {
46
50
  Control,
47
51
  ClearIndicator,
48
52
  IndicatorsContainer,
49
53
  IndicatorSeparator: null,
54
+ Input,
50
55
  MenuList,
51
56
  MultiValue,
52
57
  Option,
@@ -58,6 +63,8 @@ const Typeahead = (props: Props) => {
58
63
  isClearable: true,
59
64
  isSearchable: true,
60
65
  name,
66
+ onCreate: () => {},
67
+ plusIcon: false,
61
68
  ...props,
62
69
  }
63
70
 
@@ -65,7 +72,8 @@ const Typeahead = (props: Props) => {
65
72
  if (typeof(props.getOptionLabel) === 'string') selectProps.getOptionLabel = get(window, props.getOptionLabel)
66
73
  if (typeof(props.getOptionValue) === 'string') selectProps.getOptionValue = get(window, props.getOptionValue)
67
74
 
68
- const Tag = props.async ? AsyncSelect : Select
75
+ let Tag = props.async ? AsyncSelect : Select
76
+ if (props.createable) Tag = CreateableSelect
69
77
 
70
78
  const handleOnChange = (data, { action, option, removedValue }) => {
71
79
  if (action === 'select-option') {
@@ -0,0 +1,24 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import { components } from 'react-select'
5
+ import { Flex, Icon } from '../../'
6
+
7
+ const Input = (props: any) => (
8
+ <Flex
9
+ align="center"
10
+ >
11
+ <If condition={props.selectProps.plusIcon}>
12
+ <Icon
13
+ className="typeahead-plus-icon"
14
+ icon="plus"
15
+ />
16
+ </If>
17
+ <components.Input
18
+ className="input"
19
+ {...props}
20
+ />
21
+ </Flex>
22
+ )
23
+
24
+ export default Input
@@ -3,7 +3,7 @@
3
3
  import React from 'react'
4
4
  import { components } from 'react-select'
5
5
 
6
- import { FormPill } from '../../'
6
+ import { FormPill, Badge } from '../../'
7
7
 
8
8
  type Props = {
9
9
  data: object,
@@ -28,7 +28,7 @@ const MultiValue = (props: Props) => {
28
28
  className="text_input_multivalue_container"
29
29
  {...props}
30
30
  >
31
- <If condition={imageUrl}>
31
+ {/* <If condition={imageUrl}>
32
32
  <FormPill
33
33
  avatarUrl={imageUrl}
34
34
  closeProps={removeProps}
@@ -41,6 +41,29 @@ const MultiValue = (props: Props) => {
41
41
  marginRight="xs"
42
42
  text={label}
43
43
  />
44
+ </If> */}
45
+ <If condition={props.selectProps.badges}>
46
+ <Badge
47
+ closeProps={removeProps}
48
+ removeIcon
49
+ text={label}
50
+ variant="primary"
51
+ />
52
+ <Else />
53
+ <If condition={imageUrl}>
54
+ <FormPill
55
+ avatarUrl={imageUrl}
56
+ closeProps={removeProps}
57
+ marginRight="xs"
58
+ name={label}
59
+ />
60
+ <Else />
61
+ <FormPill
62
+ closeProps={removeProps}
63
+ marginRight="xs"
64
+ text={label}
65
+ />
66
+ </If>
44
67
  </If>
45
68
  </components.MultiValueContainer>
46
69
  )
@@ -13,6 +13,7 @@ const options = [
13
13
  const TypeaheadDefault = (props) => {
14
14
  return (
15
15
  <Typeahead
16
+ // badges
16
17
  label="Colors"
17
18
  options={options}
18
19
  {...props}
@@ -1,9 +1,9 @@
1
1
  /* @flow */
2
2
 
3
- import React from 'react'
3
+ import React, { useState } from 'react'
4
4
  import { Typeahead } from '../..'
5
5
 
6
- const options = [
6
+ const initOptions = [
7
7
  { label: 'Windows', value: '#FFA500' },
8
8
  { label: 'Siding', value: '#FF0000' },
9
9
  { label: 'Doors', value: '#00FF00' },
@@ -11,13 +11,18 @@ const options = [
11
11
  ]
12
12
 
13
13
  const TypeaheadWithPills = (props) => {
14
+ const [values, setValues] = useState([])
14
15
  return (
15
16
  <>
16
17
  <Typeahead
18
+ badges
19
+ createable
17
20
  isMulti
18
21
  label="Colors"
19
- options={options}
22
+ onChange={(value) => console.log(value)}
23
+ options={initOptions}
20
24
  placeholder=""
25
+ plusIcon
21
26
  {...props}
22
27
  />
23
28
  </>
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- VERSION = "8.2.1.alpha.iconacc"
4
+ VERSION = "8.2.1.pre.alpha1"
5
5
  end
6
6
 
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: 8.2.1.alpha.iconacc
4
+ version: 8.2.1.pre.alpha1
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-03-31 00:00:00.000000000 Z
12
+ date: 2021-03-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -1187,6 +1187,14 @@ files:
1187
1187
  - app/pb_kits/playbook/pb_image/image.html.erb
1188
1188
  - app/pb_kits/playbook/pb_image/image.rb
1189
1189
  - app/pb_kits/playbook/pb_image/image.test.js
1190
+ - app/pb_kits/playbook/pb_inline/_inline.jsx
1191
+ - app/pb_kits/playbook/pb_inline/_inline.scss
1192
+ - app/pb_kits/playbook/pb_inline/docs/_inline_default.jsx
1193
+ - app/pb_kits/playbook/pb_inline/docs/_inline_input_options.jsx
1194
+ - app/pb_kits/playbook/pb_inline/docs/_inline_text_options.jsx
1195
+ - app/pb_kits/playbook/pb_inline/docs/example.yml
1196
+ - app/pb_kits/playbook/pb_inline/docs/index.js
1197
+ - app/pb_kits/playbook/pb_inline/inline.test.jsx
1190
1198
  - app/pb_kits/playbook/pb_kit/dateTime.js
1191
1199
  - app/pb_kits/playbook/pb_kit/pb_date_time.rb
1192
1200
  - app/pb_kits/playbook/pb_label_pill/_label_pill.jsx
@@ -1961,6 +1969,7 @@ files:
1961
1969
  - app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.jsx
1962
1970
  - app/pb_kits/playbook/pb_typeahead/components/Control.jsx
1963
1971
  - app/pb_kits/playbook/pb_typeahead/components/IndicatorsContainer.jsx
1972
+ - app/pb_kits/playbook/pb_typeahead/components/Input.jsx
1964
1973
  - app/pb_kits/playbook/pb_typeahead/components/MenuList.jsx
1965
1974
  - app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx
1966
1975
  - app/pb_kits/playbook/pb_typeahead/components/Option.jsx