playbook_ui 12.10.0 → 12.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 (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +1 -1
  3. data/app/pb_kits/playbook/pb_button/_button.tsx +15 -3
  4. data/app/pb_kits/playbook/pb_button/button.rb +10 -1
  5. data/app/pb_kits/playbook/pb_button/button.test.js +92 -61
  6. data/app/pb_kits/playbook/pb_button/docs/_button_link.html.erb +3 -2
  7. data/app/pb_kits/playbook/pb_button/docs/_button_link.jsx +12 -2
  8. data/app/pb_kits/playbook/pb_button/docs/_button_link.md +1 -0
  9. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_day_styles.scss +1 -1
  10. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +13 -1
  11. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close.jsx +68 -0
  12. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close.md +1 -0
  13. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/example.yml +1 -0
  14. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/index.js +1 -0
  15. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.rb +6 -1
  16. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/index.js +17 -0
  17. data/app/pb_kits/playbook/pb_rich_text_editor/{_rich_text_editor.jsx → _rich_text_editor.tsx} +40 -32
  18. data/app/pb_kits/playbook/pb_rich_text_editor/{inlineFocus.js → inlineFocus.ts} +1 -1
  19. data/app/pb_kits/playbook/pb_rich_text_editor/{useFocus.js → useFocus.ts} +1 -1
  20. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.tsx +1 -0
  21. data/app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.test.js +67 -0
  22. data/app/pb_kits/playbook/pb_selectable_card_icon/{_selectable_card_icon.jsx → _selectable_card_icon.tsx} +26 -28
  23. data/app/pb_kits/playbook/pb_source/{_source.jsx → _source.tsx} +33 -29
  24. data/app/pb_kits/playbook/pb_source/source.test.js +82 -0
  25. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +4 -1
  26. data/lib/playbook/version.rb +2 -2
  27. metadata +12 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9e1489462a3801b52dfe684f47a206bd828e7acef14d05c33d0f82fc2338cee
4
- data.tar.gz: 01d894ce63d37e36d7ba7cac5e6469c51f280b06d43a736046899300b3c6b230
3
+ metadata.gz: 53d5eae6427aba5ae9de4053e2069de8cf8a669c0f082c8a00066da74180be1d
4
+ data.tar.gz: 5d16ee2b64c60cbede34f42ad67e25a397f908c98f5a3fc1a3d3fa9edd1234a7
5
5
  SHA512:
6
- metadata.gz: 4ce7e5fa512dfe372904d822f263888f05557305935ff171c48582aa1d80a67ddbfb772a92598ecffce4d39a6399a6b34e27b754b4f11f46da116cb5db358030
7
- data.tar.gz: 47eccdf4be23394775ab3ebd74e0797d0b49290906dd0ae7da66d289b04702f374152cbc1180963ee5a0c9d8c31988d61a7421d00adeb34aa55ca1c150a81671
6
+ metadata.gz: 304866b64d95656b79835f2f7264f409b71a583ac6ac2e54870b6a19c3413815b162b39215eb849e92d9e045b4fc6f203b30ba065e82f4a60fd73befd7676244
7
+ data.tar.gz: 931c9aeeb4f9a0e317b3fe226ddcf3d1ec1b5ff52de4dcad9fb456e7a4c237f45f66b9b695adfdad63706f71519c40b14b4362fea2e83197f6c0737788375ee9
@@ -7,7 +7,7 @@ import { globalProps, GlobalProps } from '../utilities/globalProps'
7
7
  import Image from '../pb_image/_image'
8
8
  import OnlineStatus from '../pb_online_status/_online_status'
9
9
 
10
- type AvatarProps = {
10
+ export type AvatarProps = {
11
11
  aria?: {[key: string]: string},
12
12
  className?: string,
13
13
  data?: {[key: string]: string},
@@ -25,6 +25,7 @@ type ButtonPropTypes = {
25
25
  onClick?: EventHandler,
26
26
  tabIndex?: number,
27
27
  size?: 'sm' | 'md' | 'lg',
28
+ target?: string,
28
29
  text?: string,
29
30
  type?: 'inline' | null,
30
31
  htmlType?: 'submit' | 'reset' | 'button' | undefined,
@@ -70,6 +71,7 @@ const Button = (props: ButtonPropTypes) => {
70
71
  tabIndex,
71
72
  link = null,
72
73
  newWindow = false,
74
+ target = '',
73
75
  text,
74
76
  htmlType = 'button',
75
77
  value,
@@ -119,7 +121,17 @@ const Button = (props: ButtonPropTypes) => {
119
121
  }
120
122
  }
121
123
 
122
- const displayButton = () => {
124
+ const getTargetAttribute = () => {
125
+ if (target && link) {
126
+ return target
127
+ } else if (newWindow) {
128
+ return '_blank'
129
+ }
130
+
131
+ return null
132
+ }
133
+
134
+ const displayButton = () => {
123
135
  if (link)
124
136
  return (
125
137
  <a
@@ -128,10 +140,10 @@ const Button = (props: ButtonPropTypes) => {
128
140
  className={css}
129
141
  href={link}
130
142
  id={id}
131
- rel="noreferrer"
143
+ rel={target !== 'child' ? 'noreferrer' : null}
132
144
  role="link"
133
145
  tabIndex={tabIndex}
134
- target={newWindow ? '_blank' : null}
146
+ target={getTargetAttribute()}
135
147
  >
136
148
  {ifLoading()}
137
149
  </a>
@@ -18,6 +18,7 @@ module Playbook
18
18
  prop :variant, type: Playbook::Props::Enum,
19
19
  values: %w[primary secondary link],
20
20
  default: "primary"
21
+ prop :target
21
22
  prop :text
22
23
  prop :type
23
24
  prop :value
@@ -41,11 +42,19 @@ module Playbook
41
42
  }.compact
42
43
  end
43
44
 
45
+ def target_attribute
46
+ if target && link
47
+ target
48
+ elsif new_window
49
+ "_blank"
50
+ end
51
+ end
52
+
44
53
  def link_options
45
54
  options.tap do |option|
46
55
  option[:href] = link
47
56
  option[:role] = "link"
48
- option[:target] = "_blank" if new_window
57
+ option[:target] = target_attribute if target_attribute.present?
49
58
  option[:tabindex] = 0
50
59
  end
51
60
  end
@@ -6,97 +6,128 @@ import Button from './_button'
6
6
 
7
7
  // Primary Test Variables
8
8
  const htmlType = 'submit',
9
- text = 'Button Text',
10
- value = '1234'
9
+ text = 'Button Text',
10
+ value = '1234'
11
11
 
12
12
  test('passes type, text, and value props to button', () => {
13
- render(
14
- <Button
15
- data={{ testid: 'primary-test' }}
16
- htmlType={htmlType}
17
- text={text}
18
- value={value}
19
- />
20
- )
21
-
22
- const kit = screen.getByTestId('primary-test')
23
- const content = screen.getByText(text)
24
-
25
- expect(kit).toHaveClass('pb_button_kit_primary_inline_enabled')
26
- expect(kit).toHaveAttribute('type', htmlType)
27
- expect(kit).toHaveAttribute('value', value)
28
- expect(content).toHaveTextContent(text)
13
+ render(
14
+ <Button
15
+ data={{ testid: 'primary-test' }}
16
+ htmlType={htmlType}
17
+ text={text}
18
+ value={value}
19
+ />
20
+ )
21
+
22
+ const kit = screen.getByTestId('primary-test')
23
+ const content = screen.getByText(text)
24
+
25
+ expect(kit).toHaveClass('pb_button_kit_primary_inline_enabled')
26
+ expect(kit).toHaveAttribute('type', htmlType)
27
+ expect(kit).toHaveAttribute('value', value)
28
+ expect(content).toHaveTextContent(text)
29
29
  })
30
30
 
31
31
  // Link Test Variables
32
32
  const link = 'https://www.google.com'
33
33
 
34
34
  test('adds link to button', () => {
35
- render(
36
- <Button
37
- data={{ testid: 'link-test' }}
38
- link={link}
39
- />
40
- )
35
+ render(
36
+ <Button
37
+ data={{ testid: 'link-test' }}
38
+ link={link}
39
+ />
40
+ )
41
41
 
42
- const kit = screen.getByTestId('link-test')
42
+ const kit = screen.getByTestId('link-test')
43
43
 
44
- expect(kit).toHaveAttribute('href', link)
44
+ expect(kit).toHaveAttribute('href', link)
45
45
  })
46
46
 
47
47
  test('button with secondary variant', () => {
48
- render(
49
- <Button
50
- data={{ testid: 'variant-test' }}
51
- variant="secondary"
52
- />
53
- )
48
+ render(
49
+ <Button
50
+ data={{ testid: 'variant-test' }}
51
+ variant="secondary"
52
+ />
53
+ )
54
54
 
55
- const kit = screen.getByTestId('variant-test')
55
+ const kit = screen.getByTestId('variant-test')
56
56
 
57
- expect(kit).toHaveClass('pb_button_kit_secondary_inline_enabled')
58
- expect(kit).toHaveAttribute('type', 'button')
57
+ expect(kit).toHaveClass('pb_button_kit_secondary_inline_enabled')
58
+ expect(kit).toHaveAttribute('type', 'button')
59
59
  })
60
60
 
61
61
  test('disable prop', () => {
62
- render(
63
- <Button
64
- data={{ testid: 'disable-test' }}
65
- disabled
66
- />
67
- )
62
+ render(
63
+ <Button
64
+ data={{ testid: 'disable-test' }}
65
+ disabled
66
+ />
67
+ )
68
68
 
69
- const kit = screen.getByTestId('disable-test')
69
+ const kit = screen.getByTestId('disable-test')
70
70
 
71
- expect(kit).toBeDisabled()
71
+ expect(kit).toBeDisabled()
72
72
  })
73
73
 
74
74
  test('click event', async () => {
75
- render(
76
- <Button
77
- data={{ testid: 'click-test' }}
78
- onClick={() => appendAlert('clicked button!')}
79
- />
80
- )
75
+ render(
76
+ <Button
77
+ data={{ testid: 'click-test' }}
78
+ onClick={() => appendAlert('clicked button!')}
79
+ />
80
+ )
81
81
 
82
- const kit = screen.getByTestId('click-test')
82
+ const kit = screen.getByTestId('click-test')
83
83
 
84
- fireEvent.click(kit)
84
+ fireEvent.click(kit)
85
85
 
86
- await waitFor(() => screen.getByText('clicked button!'))
86
+ await waitFor(() => screen.getByText('clicked button!'))
87
87
 
88
- expect(screen.getByText('clicked button!')).toBeInTheDocument()
88
+ expect(screen.getByText('clicked button!')).toBeInTheDocument()
89
89
  })
90
90
 
91
91
  test('size prop', () => {
92
- render(
93
- <Button
94
- data={{ testid: 'size-test' }}
95
- size="sm"
96
- />
97
- )
92
+ render(
93
+ <Button
94
+ data={{ testid: 'size-test' }}
95
+ size="sm"
96
+ />
97
+ )
98
98
 
99
- const kit = screen.getByTestId('size-test')
99
+ const kit = screen.getByTestId('size-test')
100
100
 
101
- expect(kit).toHaveClass('pb_button_kit_primary_inline_enabled size_sm')
101
+ expect(kit).toHaveClass('pb_button_kit_primary_inline_enabled size_sm')
102
+ })
103
+
104
+ test('should render target prop', () => {
105
+ render(
106
+ <Button
107
+ data={{ testid: 'variant-test' }}
108
+ link="https://google.com"
109
+ target="_parent"
110
+ variant="secondary"
111
+ />
112
+ )
113
+
114
+ const kit = screen.getByTestId('variant-test')
115
+ expect(kit).toHaveAttribute('target', '_parent')
116
+ expect(kit).toHaveAttribute('rel', 'noreferrer')
117
+ })
118
+
119
+ test('should render child target prop', () => {
120
+ render(
121
+ <Button
122
+ data={{ testid: 'variant-test' }}
123
+ link="https://google.com"
124
+ newWindow
125
+ target="child"
126
+ variant="secondary"
127
+ />
128
+ )
129
+
130
+ const kit = screen.getByTestId('variant-test')
131
+ expect(kit).toHaveAttribute('target', 'child')
132
+ expect(kit).not.toHaveAttribute('rel')
102
133
  })
@@ -1,3 +1,4 @@
1
1
  <%= pb_rails("button", props: { text: "A Tag Button", aria: { label: "Link to Google" }, tag: "a", link: "http://google.com", margin_right: "lg" }) %>
2
- <%= pb_rails("button", props: { text: "Open in new Window", aria: { label: "Link to Google in new window" }, new_window: true, link: "http://google.com",margin_right: "lg" }) %>
3
- <%= pb_rails("button", props: { text: "A Tag Button Disabled", aria: { label: "Disabled link to Google" }, disabled: true, link: "http://google.com",margin_right: "lg" }) %>
2
+ <%= pb_rails("button", props: { text: "Open in new Window", aria: { label: "Link to Google in new window" }, new_window: true, link: "http://google.com", margin_right: "lg" }) %>
3
+ <%= pb_rails("button", props: { text: "Open in a Child Tab", aria: { label: "Link to Playbook in new window" }, link: "https://playbook.powerapp.cloud/", margin_right: "lg", target: "child"}) %>
4
+ <%= pb_rails("button", props: { text: "A Tag Button Disabled", aria: { label: "Disabled link to Google" }, disabled: true, link: "http://google.com", margin_right: "lg" }) %>
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import { Button } from '../../'
3
3
 
4
4
  const ButtonLink = (props) => (
5
- <div>
5
+ <>
6
6
  <Button
7
7
  aria={{ label: 'Link to Google' }}
8
8
  link="https://google.com"
@@ -22,6 +22,16 @@ const ButtonLink = (props) => (
22
22
  {...props}
23
23
  />
24
24
  {' '}
25
+ <Button
26
+ aria={{ label: 'Link to Playbook in new window' }}
27
+ link="https://playbook.powerapp.cloud/"
28
+ marginRight='lg'
29
+ tabIndex={0}
30
+ target='child'
31
+ text="Open in a Child Tab"
32
+ {...props}
33
+ />
34
+ {' '}
25
35
  <Button
26
36
  aria={{ label: 'Disabled link to Google' }}
27
37
  disabled
@@ -31,7 +41,7 @@ const ButtonLink = (props) => (
31
41
  text="A Tag Button Disabled"
32
42
  {...props}
33
43
  />
34
- </div>
44
+ </>
35
45
  )
36
46
 
37
47
  export default ButtonLink
@@ -0,0 +1 @@
1
+ The `link` prop accepts a string that is used as an href value and causes the button to act as a link. The default behavior of a link is to open in the current window. You can optionally alter the link behavior by adding the `newWindow` prop (boolean), which will open the link in a new window, or by calling the `target` prop, which accepts `_self`, `_blank`, `_parent`, `_top`, `child`, or any string, allowing you to specify any link target.
@@ -34,7 +34,7 @@
34
34
  }
35
35
  .flatpickr-day.inRange {
36
36
  background-color: #F7FBFF;
37
- border: 2px;
37
+ border-color: transparent;
38
38
  box-shadow: -$space_xs + 4 0 0 #F7FBFF, $space_xs - 3 0 0 #F7FBFF;
39
39
  }
40
40
  /*
@@ -14,6 +14,7 @@ const iconMap = {
14
14
  };
15
15
 
16
16
  type FixedConfirmationToastProps = {
17
+ autoClose?: number;
17
18
  className?: string;
18
19
  closeable?: boolean;
19
20
  data?: string;
@@ -30,11 +31,12 @@ type FixedConfirmationToastProps = {
30
31
  const FixedConfirmationToast = (props: FixedConfirmationToastProps) => {
31
32
  const [showToast, toggleToast] = useState(true);
32
33
  const {
34
+ autoClose = 0,
33
35
  className,
34
36
  closeable = false,
35
37
  horizontal,
36
38
  multiLine = false,
37
- onClose = () => {},
39
+ onClose = () => { },
38
40
  open = true,
39
41
  status = "neutral",
40
42
  text,
@@ -49,8 +51,18 @@ const FixedConfirmationToast = (props: FixedConfirmationToastProps) => {
49
51
  );
50
52
  const icon = iconMap[status];
51
53
 
54
+ const autoCloseToast = () => {
55
+ if (autoClose && open) {
56
+ setTimeout(() => {
57
+ toggleToast(false);
58
+ onClose();
59
+ }, autoClose);
60
+ }
61
+ }
62
+
52
63
  useEffect(() => {
53
64
  toggleToast(open);
65
+ autoCloseToast();
54
66
  }, [open]);
55
67
 
56
68
  const handleClick = () => {
@@ -0,0 +1,68 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import Button from '../../pb_button/_button'
4
+ import FixedConfirmationToast from '../_fixed_confirmation_toast'
5
+
6
+ const FixedConfirmationToastAutoClose = (props) => {
7
+
8
+ const [open, setOpen] = useState(false)
9
+ const [openCloseable, setOpenCloseable] = useState(false)
10
+
11
+ const handleClick = () => {
12
+ setOpen(true)
13
+ }
14
+ const handleClickCloseable = () => {
15
+ setOpenCloseable(true)
16
+ }
17
+
18
+ const handleClose = () => {
19
+ setOpen(false)
20
+ }
21
+
22
+ const handleCloseCloseable = () => {
23
+ setOpenCloseable(false)
24
+ }
25
+
26
+ return (
27
+ <>
28
+ <Button
29
+ onClick={handleClick}
30
+ text="Show Auto Close Toast"
31
+ variant="secondary"
32
+ {...props}
33
+ />
34
+ {' '}
35
+ <Button
36
+ onClick={handleClickCloseable}
37
+ text="Show Closeable Auto Close Toast"
38
+ variant="secondary"
39
+ {...props}
40
+ />
41
+
42
+ <FixedConfirmationToast
43
+ autoClose={3000}
44
+ horizontal='center'
45
+ onClose={handleClose}
46
+ open={open}
47
+ status='tip'
48
+ text='I will disappear in 3 seconds.'
49
+ vertical='top'
50
+ {...props}
51
+ />
52
+
53
+ <FixedConfirmationToast
54
+ autoClose={10000}
55
+ closeable
56
+ horizontal='center'
57
+ onClose={handleCloseCloseable}
58
+ open={openCloseable}
59
+ status='tip'
60
+ text='I will disappear in 10 seconds.'
61
+ vertical='top'
62
+ {...props}
63
+ />
64
+ </>
65
+ )
66
+ }
67
+
68
+ export default FixedConfirmationToastAutoClose
@@ -0,0 +1 @@
1
+ Auto close is used when you want the confirmation toast to close automatically after a certain time. `autoClose` property will be a delay number in ms.
@@ -11,3 +11,4 @@ examples:
11
11
  - fixed_confirmation_toast_multi_line: Multi Line
12
12
  - fixed_confirmation_toast_close: Click to Close
13
13
  - fixed_confirmation_toast_positions: Click to Show Positions
14
+ - fixed_confirmation_toast_auto_close: Click to Show Auto Close
@@ -2,3 +2,4 @@ export { default as FixedConfirmationToastDefault } from './_fixed_confirmation_
2
2
  export { default as FixedConfirmationToastMultiLine } from './_fixed_confirmation_toast_multi_line.jsx'
3
3
  export { default as FixedConfirmationToastClose } from './_fixed_confirmation_toast_close.jsx'
4
4
  export { default as FixedConfirmationToastPositions } from './_fixed_confirmation_toast_positions.jsx'
5
+ export { default as FixedConfirmationToastAutoClose } from './_fixed_confirmation_toast_auto_close.jsx'
@@ -19,6 +19,7 @@ module Playbook
19
19
  prop :vertical, type: Playbook::Props::Enum,
20
20
  values: [nil, "top", "bottom"],
21
21
  default: nil
22
+ prop :auto_close, type: Playbook::Props::Number
22
23
 
23
24
  def show_text?
24
25
  text.present?
@@ -28,6 +29,10 @@ module Playbook
28
29
  closeable.present? ? " remove_toast" : ""
29
30
  end
30
31
 
32
+ def auto_close_class
33
+ auto_close.present? ? " auto_close_#{auto_close}" : ""
34
+ end
35
+
31
36
  def position_class
32
37
  horizontal && vertical ? " positioned_toast #{vertical} #{horizontal}" : ""
33
38
  end
@@ -50,7 +55,7 @@ module Playbook
50
55
  end
51
56
 
52
57
  def classname
53
- generate_classname("pb_fixed_confirmation_toast_kit", status, multi_line_class) + close_class + position_class
58
+ generate_classname("pb_fixed_confirmation_toast_kit", status, multi_line_class) + close_class + position_class + auto_close_class
54
59
  end
55
60
  end
56
61
  end
@@ -7,6 +7,8 @@ export default class PbFixedConfirmationToast extends PbEnhancedElement {
7
7
 
8
8
  connect() {
9
9
  this.self = this.element
10
+ this.autoCloseToast(this.self)
11
+
10
12
  this.self.addEventListener('click', () => {
11
13
  this.removeToast(this.self)
12
14
  })
@@ -15,4 +17,19 @@ export default class PbFixedConfirmationToast extends PbEnhancedElement {
15
17
  removeToast(elem) {
16
18
  elem.parentNode.removeChild(elem)
17
19
  }
20
+
21
+ autoCloseToast(element) {
22
+ const classListValues = element.classList.value
23
+ const hasAutoCloseClass = classListValues.includes('auto_close')
24
+
25
+ if (hasAutoCloseClass) {
26
+ const classList = classListValues.split(' ')
27
+ const autoCloseValue = classList[classList.length - 1].split('_')[2]
28
+ const autoCloseIntValue = parseInt(autoCloseValue)
29
+
30
+ setTimeout(() => {
31
+ this.removeToast(element)
32
+ }, autoCloseIntValue)
33
+ }
34
+ }
18
35
  }
@@ -1,6 +1,3 @@
1
- /* @flow */
2
- /* eslint-disable react-hooks/rules-of-hooks */
3
-
4
1
  import React, { useEffect, useState } from 'react'
5
2
  import classnames from 'classnames'
6
3
  import inlineFocus from './inlineFocus'
@@ -18,11 +15,21 @@ try {
18
15
 
19
16
  import { TrixEditor } from "react-trix"
20
17
 
18
+ type Editor = {
19
+ attributeIsActive?: Function,
20
+ element?: HTMLElement,
21
+ getSelectedDocument?: Function,
22
+ getSelectedRange?: () => Array<number>,
23
+ insertHTML?: Function,
24
+ loadHTML?: Function,
25
+ setSelectedRange?: (range: Array<number>) => void,
26
+ }
27
+
21
28
  type RichTextEditorProps = {
22
- aria?: object,
29
+ aria?: { [key: string]: string },
23
30
  toolbarBottom?: Boolean,
24
31
  className?: string,
25
- data?: object,
32
+ data?: { [key: string]: string },
26
33
  focus?: boolean,
27
34
  id?: string,
28
35
  inline?: boolean,
@@ -53,19 +60,19 @@ const RichTextEditor = (props: RichTextEditorProps) => {
53
60
  } = props
54
61
 
55
62
  const ariaProps = buildAriaProps(aria),
56
- dataProps = buildDataProps(data),
57
- [editor, setEditor] = useState()
63
+ dataProps = buildDataProps(data),
64
+ [editor, setEditor] = useState<Editor>()
58
65
 
59
- const handleOnEditorReady = (editorInstance) => setEditor(editorInstance),
60
- element = editor?.element
66
+ const handleOnEditorReady = (editorInstance: Editor) => setEditor(editorInstance),
67
+ element = editor?.element
61
68
 
62
69
  // DOM manipulation must wait for editor to be ready
63
70
  if (editor) {
64
- const toolbarElement = element.parentElement.querySelector('trix-toolbar'),
65
- blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]')
71
+ const toolbarElement = element.parentElement.querySelector('trix-toolbar') as HTMLElement,
72
+ blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]') as HTMLElement
66
73
 
67
- let inlineCodeButton = toolbarElement.querySelector('[data-trix-attribute=inlineCode]')
68
- if (!inlineCodeButton) inlineCodeButton = blockCodeButton.cloneNode(true)
74
+ let inlineCodeButton = toolbarElement.querySelector('[data-trix-attribute=inlineCode]') as HTMLElement
75
+ if (!inlineCodeButton) inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
69
76
 
70
77
  // set button attributes
71
78
  inlineCodeButton.dataset.trixAttribute = 'inlineCode'
@@ -93,8 +100,8 @@ const RichTextEditor = (props: RichTextEditorProps) => {
93
100
 
94
101
  focus
95
102
  ? (document.addEventListener('trix-focus', useFocus),
96
- document.addEventListener('trix-blur', useFocus),
97
- useFocus())
103
+ document.addEventListener('trix-blur', useFocus),
104
+ useFocus())
98
105
  : null
99
106
 
100
107
  document.addEventListener('trix-focus', inlineFocus)
@@ -110,11 +117,11 @@ const RichTextEditor = (props: RichTextEditorProps) => {
110
117
 
111
118
  useEffect(() => {
112
119
  if (!element) return
113
- element.addEventListener('click', ({target}) => {
114
- const trixEditorContainer = target.closest('.pb_rich_text_editor_kit')
120
+ element.addEventListener('click', ({ target }: Event) => {
121
+ const trixEditorContainer = (target as Element).closest('.pb_rich_text_editor_kit')
115
122
  if (!trixEditorContainer) return
116
123
 
117
- const anchorElement = target.closest('a')
124
+ const anchorElement = (target as Element).closest('a')
118
125
  if (!anchorElement) return
119
126
 
120
127
  if (anchorElement.hasAttribute('href')) window.open(anchorElement.href)
@@ -122,11 +129,11 @@ const RichTextEditor = (props: RichTextEditorProps) => {
122
129
  }, [element])
123
130
 
124
131
  const richTextEditorClass = 'pb_rich_text_editor_kit',
125
- simpleClass = simple ? 'simple' : '',
126
- focusClass = focus ? 'focus-editor-targets' : '',
127
- stickyClass = sticky ? 'sticky' : '',
128
- inlineClass = inline ? 'inline' : '',
129
- toolbarBottomClass = toolbarBottom ? 'toolbar-bottom' : ''
132
+ simpleClass = simple ? 'simple' : '',
133
+ focusClass = focus ? 'focus-editor-targets' : '',
134
+ stickyClass = sticky ? 'sticky' : '',
135
+ inlineClass = inline ? 'inline' : '',
136
+ toolbarBottomClass = toolbarBottom ? 'toolbar-bottom' : ''
130
137
 
131
138
  let css = classnames(globalProps(props), className)
132
139
  css = classnames(
@@ -141,17 +148,18 @@ const RichTextEditor = (props: RichTextEditorProps) => {
141
148
 
142
149
  return (
143
150
  <div
144
- {...ariaProps}
145
- {...dataProps}
146
- className={css}
151
+ {...ariaProps}
152
+ {...dataProps}
153
+ className={css}
147
154
  >
148
155
  <TrixEditor
149
- className=""
150
- fileParamName={name}
151
- onChange={onChange}
152
- onEditorReady={handleOnEditorReady}
153
- placeholder={placeholder}
154
- value={value}
156
+ className=""
157
+ fileParamName={name}
158
+ mergeTags={[]}
159
+ onChange={onChange}
160
+ onEditorReady={handleOnEditorReady}
161
+ placeholder={placeholder}
162
+ value={value}
155
163
  />
156
164
  </div>
157
165
  )
@@ -1,5 +1,5 @@
1
1
  const inlineFocus = () => {
2
- const trixEditorElement = event.target
2
+ const trixEditorElement = event.target as Element
3
3
  const trixEditorContainer = trixEditorElement.closest('.pb_rich_text_editor_kit')
4
4
 
5
5
  if (!trixEditorContainer.classList.contains('inline')) return
@@ -2,7 +2,7 @@ const useFocus = () => {
2
2
  const allTrixEditors = document.querySelectorAll(
3
3
  '.focus-editor-targets trix-editor'
4
4
  )
5
- allTrixEditors.forEach((editorElement) => {
5
+ allTrixEditors.forEach((editorElement: any) => {
6
6
  const toolbarElement = editorElement.toolbarElement
7
7
  if (editorElement == document.activeElement) {
8
8
  editorElement.classList.add('focused-editor')
@@ -102,6 +102,7 @@ const SelectableCard = (props: SelectableCardProps) => {
102
102
  delete filteredProps?.error
103
103
  delete filteredProps?.dark
104
104
  delete filteredProps?.multi
105
+ delete filteredProps?.customIcon
105
106
  const labelProps: GlobalProps = variant === 'displayInput' ? { ...filteredProps, padding: 'none' } : { ...filteredProps }
106
107
 
107
108
  return (
@@ -0,0 +1,67 @@
1
+ import React, { useState } from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import SelectableCardIcon from './_selectable_card_icon'
5
+
6
+ const testId = 'selectableCardIcon'
7
+ const className = 'custom-class-name'
8
+
9
+ const SelectableCardIconDefault = () => {
10
+ const [selected, setSelected] = useState(true)
11
+
12
+ return (
13
+ <SelectableCardIcon
14
+ aria={{ label: testId }}
15
+ bodyText="Export"
16
+ checked={selected}
17
+ className={className}
18
+ data={{ testid: testId }}
19
+ icon="chart-line"
20
+ inputId={1}
21
+ onChange={() => setSelected(!selected)}
22
+ titleText="Quarterly Report"
23
+ />
24
+ )
25
+ }
26
+
27
+ test('should pass data prop', () => {
28
+ render(<SelectableCardIconDefault />)
29
+ const kit = screen.getByTestId(testId)
30
+ expect(kit).toBeInTheDocument()
31
+ })
32
+
33
+ test('should pass className prop', () => {
34
+ render(<SelectableCardIconDefault />)
35
+ const kit = screen.getByTestId(testId)
36
+ expect(kit).toHaveClass(className)
37
+ })
38
+
39
+ test('should pass aria prop', () => {
40
+ render(<SelectableCardIconDefault />)
41
+ const kit = screen.getByTestId(testId)
42
+ expect(kit).toHaveAttribute('aria-label', testId)
43
+ })
44
+
45
+ test('should be checked', () => {
46
+ render(<SelectableCardIconDefault />)
47
+ const kit = screen.getByTestId(testId)
48
+ expect(kit).toHaveClass('pb_selectable_card_icon_kit_checked_enabled')
49
+ })
50
+
51
+ test('should not be disabled', () => {
52
+ render(<SelectableCardIconDefault />)
53
+ const kit = screen.getByTestId(testId)
54
+ expect(kit).toHaveClass('pb_selectable_card_icon_kit_checked_enabled')
55
+ })
56
+
57
+ test('should render body text prop', () => {
58
+ render(<SelectableCardIconDefault />)
59
+ const kit = screen.getByText("Export")
60
+ expect(kit).toBeInTheDocument()
61
+ })
62
+
63
+ test('should render title text prop', () => {
64
+ render(<SelectableCardIconDefault />)
65
+ const kit = screen.getByText("Quarterly Report")
66
+ expect(kit).toBeInTheDocument()
67
+ })
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import classnames from 'classnames'
5
3
 
@@ -15,13 +13,13 @@ import SelectableCard from '../pb_selectable_card/_selectable_card'
15
13
  import SelectableIcon from '../pb_selectable_icon/_selectable_icon'
16
14
 
17
15
  type SelectableCardIconProps = {
18
- aria?: Object,
16
+ aria?: { [key: string]: string },
19
17
  checked?: boolean,
20
18
  checkmark: boolean,
21
19
  className?: string,
22
- customIcon?: SVGElement,
20
+ customIcon?: { [key: string]: SVGElement },
23
21
  dark?: boolean,
24
- data?: Object,
22
+ data?: { [key: string]: string },
25
23
  disabled?: boolean,
26
24
  icon?: string,
27
25
  inputId?: string,
@@ -30,7 +28,7 @@ type SelectableCardIconProps = {
30
28
  titleText?: string,
31
29
  bodyText?: string,
32
30
  value?: string,
33
- onChange?: (e) => void,
31
+ onChange?: (event: React.FormEvent<HTMLInputElement>) => void,
34
32
  }
35
33
 
36
34
  const SelectableCardIcon = (props: SelectableCardIconProps) => {
@@ -68,35 +66,35 @@ const SelectableCardIcon = (props: SelectableCardIconProps) => {
68
66
 
69
67
  return (
70
68
  <div
71
- {...ariaProps}
72
- {...dataProps}
73
- className={classes}
69
+ {...ariaProps}
70
+ {...dataProps}
71
+ className={classes}
74
72
  >
75
73
  <SelectableCard
76
- checked={checked}
77
- customIcon={customIcon}
78
- dark={dark}
79
- disabled={disabled}
80
- icon={checkmark}
81
- inputId={inputId}
82
- multi={multi}
83
- name={name}
84
- onChange={onChange}
85
- value={value}
74
+ checked={checked}
75
+ customIcon={customIcon}
76
+ dark={dark}
77
+ disabled={disabled}
78
+ icon={checkmark}
79
+ inputId={inputId}
80
+ multi={multi}
81
+ name={name}
82
+ onChange={onChange}
83
+ value={value}
86
84
  >
87
85
  {
88
86
  <>
89
87
  <SelectableIcon
90
- customIcon={customIcon}
91
- icon={icon}
92
- inputs="disabled"
93
- size="2x"
94
- text={titleText}
95
- />
88
+ customIcon={customIcon}
89
+ icon={icon}
90
+ inputId={''}
91
+ inputs="disabled"
92
+ name={''}
93
+ text={titleText} />
96
94
  <Body
97
- color="light"
98
- dark={dark}
99
- text={bodyText}
95
+ color="light"
96
+ dark={dark}
97
+ text={bodyText}
100
98
  />
101
99
  </>
102
100
  }
@@ -1,28 +1,28 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import classnames from 'classnames'
5
3
 
6
- import { buildDataProps } from '../utilities/props'
4
+ import { buildDataProps, buildAriaProps } from '../utilities/props'
7
5
  import { titleize } from '../utilities/text'
8
6
 
9
- import Avatar from '../pb_avatar/_avatar'
7
+ import Avatar, { AvatarProps } from '../pb_avatar/_avatar'
10
8
  import Body from '../pb_body/_body'
11
9
  import Caption from '../pb_caption/_caption'
12
10
  import IconCircle from '../pb_icon_circle/_icon_circle'
13
11
  import Title from '../pb_title/_title'
14
12
 
15
13
  type SourceProps = {
14
+ aria?: {[key: string]: string},
16
15
  className?: string,
17
- data?: object,
16
+ data?: { [key: string]: string },
18
17
  hideIcon: boolean,
19
18
  id?: string,
20
19
  source?: string,
21
20
  type: "events" | "inbound" | "outbound" | "prospecting" | "referral" | "retail" | "user",
22
- user: object,
21
+ user: AvatarProps,
23
22
  }
24
23
 
25
24
  const Source = ({
25
+ aria = {},
26
26
  className,
27
27
  data = {},
28
28
  hideIcon = false,
@@ -32,6 +32,7 @@ const Source = ({
32
32
  user = {},
33
33
  }: SourceProps) => {
34
34
  const dataProps = buildDataProps(data)
35
+ const ariaProps = buildAriaProps(aria)
35
36
 
36
37
  const css = classnames([
37
38
  'pb_source_kit',
@@ -40,7 +41,7 @@ const Source = ({
40
41
 
41
42
  const avatar = () => {
42
43
  if ((type === 'user' || type === 'referral') && user.name !== undefined) {
43
- const avatarProps = { ...user }
44
+ const avatarProps: AvatarProps = { ...user }
44
45
  avatarProps.size = 'sm'
45
46
  delete avatarProps.userId
46
47
  return avatarProps
@@ -55,7 +56,7 @@ const Source = ({
55
56
  }
56
57
  }
57
58
 
58
- const typeIconNames = {
59
+ const typeIconNames: { [key: string]: string } = {
59
60
  events: 'calendar-alt',
60
61
  outbound: 'sign-out',
61
62
  prospecting: 'binoculars',
@@ -68,47 +69,50 @@ const Source = ({
68
69
 
69
70
  return (
70
71
  <div
71
- {...dataProps}
72
- className={css}
73
- id={id}
72
+ {...ariaProps}
73
+ {...dataProps}
74
+ className={css}
75
+ id={id}
74
76
  >
75
77
 
76
78
  <div className="pb__source_layout">
77
- <If condition={hideIcon === false}>
78
- <If condition={showIcon()}>
79
- <IconCircle
79
+ {hideIcon === false &&
80
+ <>
81
+ {showIcon() &&
82
+ <IconCircle
80
83
  icon={typeIconNames[type]}
81
84
  size="sm"
82
- />
83
- <Else />
84
- <Avatar
85
+ />
86
+ }
87
+ {!showIcon() &&
88
+ <Avatar
85
89
  {...avatar()}
86
- />
87
- </If>
88
- </If>
90
+ />
91
+ }
92
+ </>
93
+ }
89
94
 
90
95
  <div className="pb__source_content">
91
96
  <Title
92
- size={4}
93
- tag="h4"
94
- text={source}
97
+ size={4}
98
+ tag="h4"
99
+ text={source}
95
100
  />
96
101
 
97
102
  <div className="pb__source_value">
98
103
  <Body
99
- color="light"
100
- text={typeText()}
104
+ color="light"
105
+ text={typeText()}
101
106
  />
102
107
 
103
- <If condition={user.userId}>
108
+ {user.userId &&
104
109
  <Caption
105
- text={user.userId}
110
+ text={user.userId}
106
111
  />
107
- </If>
112
+ }
108
113
  </div>
109
114
  </div>
110
115
  </div>
111
-
112
116
  </div>
113
117
  )
114
118
  }
@@ -0,0 +1,82 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+
4
+ import Source from './_source'
5
+
6
+ const testId = 'source'
7
+ const className = 'custom-class-name'
8
+
9
+ const SourceDefault = (props) => (
10
+ <>
11
+ <Source
12
+ aria={{ label: testId }}
13
+ className={className}
14
+ data={{ testid: testId }}
15
+ source="BJ's Johnston-208"
16
+ type='retail'
17
+ {...props}
18
+ />
19
+ </>
20
+ )
21
+
22
+ test('should pass data prop', () => {
23
+ render(<SourceDefault />)
24
+ const kit = screen.getByTestId(testId)
25
+ expect(kit).toBeInTheDocument()
26
+ })
27
+
28
+ test('should pass className prop', () => {
29
+ render(<SourceDefault />)
30
+ const kit = screen.getByTestId(testId)
31
+ expect(kit).toHaveClass(className)
32
+ })
33
+
34
+ test('should pass aria prop', () => {
35
+ render(<SourceDefault />)
36
+ const kit = screen.getByTestId(testId)
37
+ expect(kit).toHaveAttribute('aria-label', testId)
38
+ })
39
+
40
+ test('should pass type prop', () => {
41
+ render(<SourceDefault />)
42
+ const kit = screen.getByText('Retail')
43
+ expect(kit).toBeInTheDocument()
44
+ })
45
+
46
+ test('should pass source prop', () => {
47
+ render(<SourceDefault />)
48
+ const kit = screen.getByText("BJ's Johnston-208")
49
+ expect(kit).toBeInTheDocument()
50
+ })
51
+
52
+ test('should not hide icon by default', () => {
53
+ render(<SourceDefault />)
54
+ const kit = screen.getByTestId(testId)
55
+ expect(kit.querySelector('.pb_icon_circle_kit_sm_default')).toBeTruthy()
56
+ })
57
+
58
+ test('should hide icon', () => {
59
+ render(<SourceDefault hideIcon />)
60
+ const kit = screen.getByTestId(testId)
61
+ expect(kit.querySelector('.pb_icon_circle_kit_sm_default')).toBeFalsy()
62
+ })
63
+
64
+ test('should pass user prop', () => {
65
+ const user = {
66
+ name: 'Anna Black',
67
+ userId: '48582',
68
+ }
69
+
70
+ render(
71
+ <SourceDefault
72
+ type='user'
73
+ user={user}
74
+ />
75
+ )
76
+
77
+ let kit = screen.getByText(user.name)
78
+ expect(kit).toBeInTheDocument()
79
+
80
+ kit = screen.getByText(user.userId)
81
+ expect(kit).toBeInTheDocument()
82
+ })
@@ -10,13 +10,16 @@ import {
10
10
  useFloating,
11
11
  useHover,
12
12
  useInteractions,
13
- } from "@floating-ui/react-dom-interactions"
13
+ } from "@floating-ui/react"
14
14
 
15
15
  import classnames from "classnames"
16
16
  import { GlobalProps, globalProps } from "../utilities/globalProps"
17
17
  import { buildAriaProps, buildDataProps } from "../utilities/props"
18
18
  import Flex from "../pb_flex/_flex"
19
19
 
20
+
21
+
22
+
20
23
  type TooltipProps = {
21
24
  aria?: { [key: string]: string },
22
25
  className?: string | string[],
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- PREVIOUS_VERSION = "12.9.1"
5
- VERSION = "12.10.0"
4
+ PREVIOUS_VERSION = "12.10.0"
5
+ VERSION = "12.11.0"
6
6
  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: 12.10.0
4
+ version: 12.11.0
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: 2023-03-22 00:00:00.000000000 Z
12
+ date: 2023-03-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -457,6 +457,7 @@ files:
457
457
  - app/pb_kits/playbook/pb_button/docs/_button_icon_options.md
458
458
  - app/pb_kits/playbook/pb_button/docs/_button_link.html.erb
459
459
  - app/pb_kits/playbook/pb_button/docs/_button_link.jsx
460
+ - app/pb_kits/playbook/pb_button/docs/_button_link.md
460
461
  - app/pb_kits/playbook/pb_button/docs/_button_loading.html.erb
461
462
  - app/pb_kits/playbook/pb_button/docs/_button_loading.jsx
462
463
  - app/pb_kits/playbook/pb_button/docs/_button_loading.md
@@ -955,6 +956,8 @@ files:
955
956
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.scss
956
957
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx
957
958
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_description.md
959
+ - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close.jsx
960
+ - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close.md
958
961
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_close.html.erb
959
962
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_close.jsx
960
963
  - app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_default.html.erb
@@ -1710,8 +1713,8 @@ files:
1710
1713
  - app/pb_kits/playbook/pb_radio/radio.html.erb
1711
1714
  - app/pb_kits/playbook/pb_radio/radio.rb
1712
1715
  - app/pb_kits/playbook/pb_radio/radio.test.js
1713
- - app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.jsx
1714
1716
  - app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.scss
1717
+ - app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx
1715
1718
  - app/pb_kits/playbook/pb_rich_text_editor/_trix_styles.scss
1716
1719
  - app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_attributes.html.erb
1717
1720
  - app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_attributes.jsx
@@ -1734,11 +1737,11 @@ files:
1734
1737
  - app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml
1735
1738
  - app/pb_kits/playbook/pb_rich_text_editor/docs/index.js
1736
1739
  - app/pb_kits/playbook/pb_rich_text_editor/docs/templates.js
1737
- - app/pb_kits/playbook/pb_rich_text_editor/inlineFocus.js
1740
+ - app/pb_kits/playbook/pb_rich_text_editor/inlineFocus.ts
1738
1741
  - app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb
1739
1742
  - app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb
1740
1743
  - app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.test.js
1741
- - app/pb_kits/playbook/pb_rich_text_editor/useFocus.js
1744
+ - app/pb_kits/playbook/pb_rich_text_editor/useFocus.ts
1742
1745
  - app/pb_kits/playbook/pb_section_separator/_section_separator.scss
1743
1746
  - app/pb_kits/playbook/pb_section_separator/_section_separator.tsx
1744
1747
  - app/pb_kits/playbook/pb_section_separator/_section_separator_mixin.scss
@@ -1811,8 +1814,9 @@ files:
1811
1814
  - app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb
1812
1815
  - app/pb_kits/playbook/pb_selectable_card/selectable_card.rb
1813
1816
  - app/pb_kits/playbook/pb_selectable_card/selectable_card.test.js
1814
- - app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.jsx
1815
1817
  - app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.scss
1818
+ - app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.test.js
1819
+ - app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.tsx
1816
1820
  - app/pb_kits/playbook/pb_selectable_card_icon/docs/_selectable_card_icon_checkmark.html.erb
1817
1821
  - app/pb_kits/playbook/pb_selectable_card_icon/docs/_selectable_card_icon_checkmark.jsx
1818
1822
  - app/pb_kits/playbook/pb_selectable_card_icon/docs/_selectable_card_icon_default.html.erb
@@ -1849,8 +1853,8 @@ files:
1849
1853
  - app/pb_kits/playbook/pb_selectable_list/selectable_list.rb
1850
1854
  - app/pb_kits/playbook/pb_selectable_list/selectable_list_item.html.erb
1851
1855
  - app/pb_kits/playbook/pb_selectable_list/selectable_list_item.rb
1852
- - app/pb_kits/playbook/pb_source/_source.jsx
1853
1856
  - app/pb_kits/playbook/pb_source/_source.scss
1857
+ - app/pb_kits/playbook/pb_source/_source.tsx
1854
1858
  - app/pb_kits/playbook/pb_source/docs/_description.md
1855
1859
  - app/pb_kits/playbook/pb_source/docs/_source_default.html.erb
1856
1860
  - app/pb_kits/playbook/pb_source/docs/_source_default.jsx
@@ -1862,6 +1866,7 @@ files:
1862
1866
  - app/pb_kits/playbook/pb_source/docs/index.js
1863
1867
  - app/pb_kits/playbook/pb_source/source.html.erb
1864
1868
  - app/pb_kits/playbook/pb_source/source.rb
1869
+ - app/pb_kits/playbook/pb_source/source.test.js
1865
1870
  - app/pb_kits/playbook/pb_star_rating/_star_rating.jsx
1866
1871
  - app/pb_kits/playbook/pb_star_rating/_star_rating.scss
1867
1872
  - app/pb_kits/playbook/pb_star_rating/docs/_description.md