playbook_ui 7.15.1 → 7.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/index.js +2 -2
  3. data/app/pb_kits/playbook/pb_avatar/_avatar.html.erb +4 -6
  4. data/app/pb_kits/playbook/pb_avatar/_avatar.jsx +6 -2
  5. data/app/pb_kits/playbook/pb_avatar/avatar.rb +4 -0
  6. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_no_image.html.erb +5 -0
  7. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_no_image.jsx +41 -0
  8. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_no_image.md +2 -0
  9. data/app/pb_kits/playbook/pb_avatar/docs/example.yml +2 -0
  10. data/app/pb_kits/playbook/pb_avatar/docs/index.js +1 -0
  11. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.jsx +1 -0
  12. data/app/pb_kits/playbook/pb_date_time/_date_time.jsx +2 -2
  13. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_default.jsx +2 -2
  14. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.jsx +5 -1
  15. data/app/pb_kits/playbook/pb_flex/_flex_item.jsx +4 -2
  16. data/app/pb_kits/playbook/pb_flex/_flex_item.scss +9 -0
  17. data/app/pb_kits/playbook/pb_flex/flex_item.rb +8 -1
  18. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_sizing.html.erb +4 -4
  19. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_sizing.jsx +12 -1
  20. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_sizing.md +2 -1
  21. data/app/pb_kits/playbook/pb_gauge/docs/example.yml +4 -5
  22. data/app/pb_kits/playbook/pb_image/_image.html.erb +3 -1
  23. data/app/pb_kits/playbook/pb_image/_image.jsx +4 -1
  24. data/app/pb_kits/playbook/pb_image/docs/_custom_error_image.html.erb +75 -0
  25. data/app/pb_kits/playbook/pb_image/docs/_custom_error_image.jsx +55 -0
  26. data/app/pb_kits/playbook/pb_image/docs/example.yml +2 -0
  27. data/app/pb_kits/playbook/pb_image/docs/index.js +1 -0
  28. data/app/pb_kits/playbook/pb_image/image.rb +2 -0
  29. data/app/pb_kits/playbook/pb_layout/_item.html.erb +6 -0
  30. data/app/pb_kits/playbook/pb_layout/_layout.jsx +19 -1
  31. data/app/pb_kits/playbook/pb_layout/_layout.scss +33 -1
  32. data/app/pb_kits/playbook/pb_layout/docs/_layout_collection_detail.jsx +1 -1
  33. data/app/pb_kits/playbook/pb_layout/docs/_layout_masonry.html.erb +48 -0
  34. data/app/pb_kits/playbook/pb_layout/docs/_layout_masonry.jsx +61 -0
  35. data/app/pb_kits/playbook/pb_layout/docs/example.yml +3 -0
  36. data/app/pb_kits/playbook/pb_layout/docs/index.js +1 -0
  37. data/app/pb_kits/playbook/pb_layout/item.rb +25 -0
  38. data/app/pb_kits/playbook/pb_layout/layout.rb +15 -15
  39. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.html.erb +1 -1
  40. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.jsx +9 -2
  41. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +20 -1
  42. data/app/pb_kits/playbook/pb_selectable_card/docs/_selectable_card_error.html.erb +36 -0
  43. data/app/pb_kits/playbook/pb_selectable_card/docs/_selectable_card_error.jsx +58 -0
  44. data/app/pb_kits/playbook/pb_selectable_card/docs/example.yml +2 -0
  45. data/app/pb_kits/playbook/pb_selectable_card/docs/index.js +1 -0
  46. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.rb +11 -0
  47. data/app/pb_kits/playbook/pb_table/docs/_table_alignment_shift_data.jsx +0 -1
  48. data/lib/playbook/version.rb +1 -1
  49. metadata +18 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 314da7ed0bc2cb7982bfaf10af7826efbb8822ad5ab5030433daf1bde9267398
4
- data.tar.gz: 4ee326fa35a415359b0633ce7138526ce1c1346a0991ad079fb3307f350c432f
3
+ metadata.gz: ba7ca0e1a8dbb832e4553d4ca3c0c8c328ead105c57d691a0181ca169197b53a
4
+ data.tar.gz: a8c51729b2dfcfb7dc54d448abc6a305cb89fb367933b4a01893a8a455dd0fcb
5
5
  SHA512:
6
- metadata.gz: 25a9b84de3294b16d92378e48d5192ba6b444623a5161f3e64d0a68b52637cbef1949334d6cc72852dd4f85e414e827b413857afea83a0d1092c6331d79928ee
7
- data.tar.gz: c565fd03afa4505e9e0126a868d1acd67baa86fe293f9c84db4248ebd417b8da4c3ab8042092d6130ed9353343f79c87ef59066ce5a699807624dce1c129bd93
6
+ metadata.gz: e2ff1660024fbfc09a674433414caf39bc8b1c50220f51dc642c76d5de7d11f2b8056ae70ab924944c2828ee362f7b9986d1e5226672e9feda680606fc4ba7c2
7
+ data.tar.gz: 01b2ae4f1a7abed5972b1394f9a2b13ac31de8814050adef4f78ca81cab284c82fab7b966a88428b94c326f6319b72774443f00894c29e273773279d97388696
@@ -108,8 +108,8 @@ export dashboardValueSettings from './pb_dashboard_value/dashboardValueSettings'
108
108
  // Other JS/Plugins
109
109
  export pbChart from './plugins/pb_chart.js'
110
110
  export datePickerHelper from './pb_date_picker/date_picker_helper.js'
111
- export PbTypeahead from './pb_typeahead'
112
111
  export PbPopover from './pb_popover'
113
112
  export PbTable from './pb_table'
114
- export PbTooltip from './pb_tooltip'
115
113
  export PbTextarea from './pb_textarea'
114
+ export PbTooltip from './pb_tooltip'
115
+ export PbTypeahead from './pb_typeahead'
@@ -3,10 +3,8 @@
3
3
  data: object.data.merge(initials: object.initials),
4
4
  class: object.classname,
5
5
  aria: object.aria) do %>
6
- <%= content_tag(:div,
7
- data: { initials: object.initials },
8
- class: "avatar_wrapper") do %>
9
- <%= pb_rails("image", props: { url: object.image_url }) if object.image_url.present? %>
10
- <% end %>
11
- <%= pb_rails("online_status", props: object.online_status_props) if object.status %>
6
+ <%= content_tag(:div, data: { initials: object.initials }, class: "avatar_wrapper") do %>
7
+ <%= pb_rails("image", props: { url: object.image_url, on_error: object.handle_img_error }) if object.image_url.present? %>
8
+ <% end %>
9
+ <%= pb_rails("online_status", props: object.online_status_props) if object.status %>
12
10
  <% end %>
@@ -1,6 +1,6 @@
1
1
  /* @flow */
2
2
 
3
- import React from 'react'
3
+ import React, { useState } from 'react'
4
4
  import classnames from 'classnames'
5
5
  import { map } from 'lodash'
6
6
 
@@ -39,6 +39,9 @@ const Avatar = (props: AvatarProps) => {
39
39
  const initials = name && firstTwoInitials(name)
40
40
  dataProps['data-initials'] = initials
41
41
 
42
+ const [error, setError] = useState(false)
43
+ const handleError = () => setError(true)
44
+
42
45
  return (
43
46
  <div
44
47
  {...ariaProps}
@@ -50,9 +53,10 @@ const Avatar = (props: AvatarProps) => {
50
53
  className="avatar_wrapper"
51
54
  data-initials={initials}
52
55
  >
53
- <If condition={imageUrl}>
56
+ <If condition={imageUrl && !error}>
54
57
  <Image
55
58
  alt={name}
59
+ onError={handleError}
56
60
  url={imageUrl}
57
61
  />
58
62
  </If>
@@ -25,6 +25,10 @@ module Playbook
25
25
  def online_status_props
26
26
  { status: status, classname: "size_#{size}" }
27
27
  end
28
+
29
+ def handle_img_error
30
+ "this.style.display = 'none'"
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -0,0 +1,5 @@
1
+ <%= pb_rails("avatar", props: { image_url: true, name: "Terry Johnson", size: "xs" }) %>
2
+ <%= pb_rails("avatar", props: { image_url: 4, name: "Terry Johnson", size: "sm" }) %>
3
+ <%= pb_rails("avatar", props: { image_url: "https://google.com", name: "Terry Johnson", size: "md" }) %>
4
+ <%= pb_rails("avatar", props: { image_url: "", name: "Terry Johnson", size: "lg" }) %>
5
+ <%= pb_rails("avatar", props: { image_url: "https://randomuser.me/api/portraits/men/notapicture.jpg", name: "Terry Johnson", size: "xl" }) %>
@@ -0,0 +1,41 @@
1
+ import React from 'react'
2
+ import { Avatar } from '../../'
3
+
4
+ const AvatarNoImage = (props) => {
5
+ return (
6
+ <div>
7
+ <Avatar
8
+ imageUrl="Just some text here"
9
+ name="Terry Johnson"
10
+ size="xs"
11
+ {...props}
12
+ />
13
+ <Avatar
14
+ imageUrl={4}
15
+ name="Terry Johnson"
16
+ size="sm"
17
+ {...props}
18
+ />
19
+ <Avatar
20
+ imageUrl="https://google.com"
21
+ name="Terry Johnson"
22
+ size="md"
23
+ {...props}
24
+ />
25
+ <Avatar
26
+ imageUrl=""
27
+ name="Terry Johnson"
28
+ size="lg"
29
+ {...props}
30
+ />
31
+ <Avatar
32
+ imageUrl="https://randomuser.me/api/portraits/men/notapicture.jpg"
33
+ name="Terry Johnson"
34
+ size="xl"
35
+ {...props}
36
+ />
37
+ </div>
38
+ )
39
+ }
40
+
41
+ export default AvatarNoImage
@@ -0,0 +1,2 @@
1
+
2
+ A monagram is used as a fallback when an invalid or missing image url is provided.
@@ -2,8 +2,10 @@ examples:
2
2
  rails:
3
3
  - avatar_default: Default
4
4
  - avatar_monogram: Monogram
5
+ - avatar_no_image: "Bad Image Link"
5
6
  - avatar_status: Status
6
7
  react:
7
8
  - avatar_default: Default
8
9
  - avatar_monogram: Monogram
10
+ - avatar_no_image: "Bad Image Link"
9
11
  - avatar_status: Status
@@ -1,3 +1,4 @@
1
1
  export { default as AvatarDefault } from './_avatar_default.jsx'
2
2
  export { default as AvatarMonogram } from './_avatar_monogram.jsx'
3
3
  export { default as AvatarStatus } from './_avatar_status.jsx'
4
+ export { default as AvatarNoImage } from './_avatar_no_image.jsx'
@@ -49,6 +49,7 @@ const DateRangeInline = (props: DateRangeInlineProps) => {
49
49
  <If condition={icon}>
50
50
  <Body
51
51
  color="light"
52
+ key={Math.random()}
52
53
  tag="span"
53
54
  >
54
55
  <Icon
@@ -53,13 +53,13 @@ const DateTime = (props: DateTimeProps) => {
53
53
  vertical="baseline"
54
54
  >
55
55
  <FormattedDate
56
- datetime={datetime}
57
56
  showDayOfWeek={showDayOfWeek}
58
57
  size={size}
59
58
  timeZone={timeZone}
59
+ value={datetime}
60
60
  />
61
61
  <Time
62
- date={new Date()}
62
+ date={datetime}
63
63
  marginLeft="sm"
64
64
  showIcon={showIcon}
65
65
  size={size}
@@ -4,7 +4,7 @@ import DateTime from '../_date_time.jsx'
4
4
  const DateTimeDefault = (props) => (
5
5
  <div>
6
6
  <DateTime
7
- datetime={new Date()}
7
+ datetime={new Date('2020-12-31 14:24:09')}
8
8
  showDayOfWeek
9
9
  showIcon
10
10
  {...props}
@@ -29,7 +29,7 @@ const DateTimeDefault = (props) => (
29
29
  <br />
30
30
 
31
31
  <DateTime
32
- datetime={new Date()}
32
+ datetime={new Date('2020-12-31 14:24:09 -0500')}
33
33
  {...props}
34
34
  />
35
35
  </div>
@@ -31,11 +31,15 @@ const FixedConfirmationToast = (props: FixedConfirmationToastProps) => {
31
31
  )
32
32
  const icon = iconMap[status]
33
33
 
34
+ const handleClick = () => {
35
+ toggleToast(!closeable)
36
+ }
37
+
34
38
  return (
35
39
  <If condition={showToast}>
36
40
  <div
37
41
  className={css}
38
- onClick={closeable && (() => toggleToast(false))}
42
+ onClick={handleClick}
39
43
  >
40
44
  <If condition={icon}>
41
45
  <Icon
@@ -10,19 +10,21 @@ type FlexItemPropTypes = {
10
10
  shrink: boolean,
11
11
  flex: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'none',
12
12
  className: string,
13
+ overflow?: "auto" | "hidden" | "initial" | "inherit" | "scroll" | "visible",
13
14
  }
14
15
 
15
16
  const FlexItem = (props: FlexItemPropTypes) => {
16
- const { children, className, fixedSize, grow, shrink, flex } = props
17
+ const { children, className, fixedSize, grow, overflow = null, shrink, flex } = props
17
18
  const growClass = grow === true ? 'grow' : ''
18
19
  const flexClass = flex !== 'none' ? `flex_${flex}` : ''
20
+ const overflowClass = overflow ? `overflow_${overflow}` : ''
19
21
  const shrinkClass = shrink === true ? 'shrink' : ''
20
22
  const fixedStyle =
21
23
  fixedSize !== undefined ? { flexBasis: `${fixedSize}` } : null
22
24
 
23
25
  return (
24
26
  <div
25
- className={classnames(buildCss('pb_flex_item_kit', growClass, shrinkClass, flexClass), globalProps(props), className)}
27
+ className={classnames(buildCss('pb_flex_item_kit', growClass, shrinkClass, flexClass), overflowClass, globalProps(props), className)}
26
28
  style={fixedStyle}
27
29
  >
28
30
  {children}
@@ -12,6 +12,15 @@
12
12
  flex-shrink: 1;
13
13
  }
14
14
 
15
+
16
+ $overflow_values: auto, hidden, inherit, initial, scroll, visible;
17
+
18
+ @each $value in $overflow_values {
19
+ &.overflow_#{$value} {
20
+ overflow: #{$value}
21
+ }
22
+ }
23
+
15
24
  @for $i from 0 through 12 {
16
25
  &[class*=_flex_#{$i}]{
17
26
  flex: $i;
@@ -15,9 +15,12 @@ module Playbook
15
15
  prop :flex, type: Playbook::Props::Enum,
16
16
  values: %w[0 1 2 3 4 5 6 7 8 9 10 11 12 none],
17
17
  default: "none"
18
+ prop :overflow, type: Playbook::Props::Enum,
19
+ values: %w[auto hidden inherit initial scroll visible] + [nil],
20
+ default: nil
18
21
 
19
22
  def classname
20
- generate_classname("pb_flex_item_kit", fixed_size_class, grow_class, shrink_class, flex_class)
23
+ generate_classname("pb_flex_item_kit", fixed_size_class, grow_class, shrink_class, flex_class) + overflow_class
21
24
  end
22
25
 
23
26
  def style_value
@@ -34,6 +37,10 @@ module Playbook
34
37
  grow ? "grow" : nil
35
38
  end
36
39
 
40
+ def overflow_class
41
+ overflow ? " overflow_#{overflow}" : ""
42
+ end
43
+
37
44
  def shrink_class
38
45
  shrink ? "shrink" : nil
39
46
  end
@@ -1,23 +1,23 @@
1
1
  <%= pb_rails("flex", props: {wrap: true}) do %>
2
- <%= pb_rails("flex/flex_item", props: {fixed_size: "400px"}) do %>
2
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "400px", overflow: "hidden", shrink: true }) do %>
3
3
  <%= pb_rails("gauge", props: {
4
4
  id: "gauge-sizing4",
5
5
  chart_data: [{ name: "Point 1", value: 100 }],
6
6
  }) %>
7
7
  <% end %>
8
- <%= pb_rails("flex/flex_item", props: {fixed_size: "300px"}) do %>
8
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "300px", overflow: "hidden", shrink: true }) do %>
9
9
  <%= pb_rails("gauge", props: {
10
10
  id: "gauge-sizing3",
11
11
  chart_data: [{ name: "Point 2", value: 75 }],
12
12
  }) %>
13
13
  <% end %>
14
- <%= pb_rails("flex/flex_item", props: {fixed_size: "200px"}) do %>
14
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "200px", overflow: "hidden", shrink: true }) do %>
15
15
  <%= pb_rails("gauge", props: {
16
16
  id: "gauge-sizing2",
17
17
  chart_data: [{ name: "Point 3", value: 50 }],
18
18
  }) %>
19
19
  <% end %>
20
- <%= pb_rails("flex/flex_item", props: {fixed_size: "125px"}) do %>
20
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "125px", overflow: "hidden", shrink: true }) do %>
21
21
  <%= pb_rails("gauge", props: {
22
22
  id: "gauge-sizing1",
23
23
  chart_data: [{ name: "Point 4", value: 25 }],
@@ -9,6 +9,8 @@ const GaugeSizing = (props) => (
9
9
  >
10
10
  <FlexItem
11
11
  fixedSize="400px"
12
+ overflow="hidden"
13
+ shrink
12
14
  {...props}
13
15
  >
14
16
  <Gauge
@@ -19,6 +21,8 @@ const GaugeSizing = (props) => (
19
21
  </FlexItem>
20
22
  <FlexItem
21
23
  fixedSize="300px"
24
+ overflow="hidden"
25
+ shrink
22
26
  {...props}
23
27
  >
24
28
  <Gauge
@@ -29,6 +33,8 @@ const GaugeSizing = (props) => (
29
33
  </FlexItem>
30
34
  <FlexItem
31
35
  fixedSize="200px"
36
+ overflow="hidden"
37
+ shrink
32
38
  {...props}
33
39
  >
34
40
  <Gauge
@@ -37,7 +43,12 @@ const GaugeSizing = (props) => (
37
43
  {...props}
38
44
  />
39
45
  </FlexItem>
40
- <FlexItem fixedSize="125px">
46
+ <FlexItem
47
+ fixedSize="125px"
48
+ overflow="hidden"
49
+ shrink
50
+ {...props}
51
+ >
41
52
  <Gauge
42
53
  chartData={[ { name: 'Point 4', value: 25 } ]}
43
54
  id="gauge-sizing1"
@@ -1 +1,2 @@
1
- ### Gauge resizes dynamically to fit whatever element it's placed within.
1
+ ### Gauge resizes dynamically to fit whatever element it's placed within.
2
+ #### Note: set `overflow` to hidden on the parent element when nesting gauges inside of a flex items to best respond to shrinking screens.
@@ -1,5 +1,5 @@
1
1
  examples:
2
-
2
+
3
3
  rails:
4
4
  - gauge_default: Default
5
5
  - gauge_disable_animation: Disable Animation
@@ -9,16 +9,15 @@ examples:
9
9
  - gauge_min_max: Min Max Labels
10
10
  - gauge_sizing: Sizing
11
11
  - gauge_height: Height
12
-
13
-
12
+
13
+
14
14
  react:
15
15
  - gauge_default: Default
16
16
  - gauge_disable_animation: Disable Animation
17
- - gauge_title: Title
17
+ - gauge_title: Title
18
18
  - gauge_units: Units
19
19
  - gauge_full_circle: Full Circle
20
20
  - gauge_min_max: Min Max Labels
21
21
  - gauge_sizing: Sizing
22
22
  - gauge_height: Height
23
23
  - gauge_live_data: Live Data
24
-
@@ -4,5 +4,7 @@
4
4
  class: object.classname,
5
5
  aria: object.aria,
6
6
  src: object.url,
7
- alt: object.alt)
7
+ alt: object.alt,
8
+ onerror: object.on_error,
9
+ )
8
10
  %>
@@ -11,6 +11,7 @@ type ImageProps = {
11
11
  className?: string,
12
12
  data?: object,
13
13
  id?: string,
14
+ onError?: () => {},
14
15
  size: "xs" | "sm" | "md" | "lg" | "xl",
15
16
  rounded?: boolean,
16
17
  url: string,
@@ -23,6 +24,7 @@ const Image = (props: ImageProps) => {
23
24
  className,
24
25
  data = {},
25
26
  id,
27
+ onError = null,
26
28
  rounded = false,
27
29
  size = '',
28
30
  url = '',
@@ -46,7 +48,8 @@ const Image = (props: ImageProps) => {
46
48
  className={classes}
47
49
  data-src={url}
48
50
  id={id}
49
- rounded={rounded}
51
+ onError={onError}
52
+ rounded={+rounded}
50
53
  src={url}
51
54
  />
52
55
  </div>
@@ -0,0 +1,75 @@
1
+ <style>
2
+ .image-error:before {
3
+ content: "Sorry, the image below seems to be broken.";
4
+ display: block;
5
+ margin-bottom: 10px;
6
+ }
7
+ .image-error {
8
+ margin: 5px;
9
+ padding: 5px;
10
+ outline: 1px solid red;
11
+ }
12
+ </style>
13
+
14
+ <%= pb_rails("body",
15
+ props: {
16
+ text: "Handle when an image fails to load or a broken link is passed. This is not neccessary most of the time."
17
+ }
18
+ ) %>
19
+
20
+ <br>
21
+ <br>
22
+
23
+ <%= pb_rails("body",
24
+ props: {
25
+ text: "Alter the display when the image fails to load:"
26
+ }
27
+ ) %>
28
+
29
+ <%= pb_rails("image",
30
+ props: {
31
+ alt: "This is the alt text!",
32
+ on_error: "this.style.color = 'red'",
33
+ rounded: true,
34
+ size: "xs",
35
+ url: "not_a_picture"
36
+ }
37
+ ) %>
38
+
39
+ <br>
40
+ <br>
41
+
42
+ <%= pb_rails("body",
43
+ props: {
44
+ text: "Give it an error class:"
45
+ }
46
+ ) %>
47
+
48
+ <%= pb_rails("image",
49
+ props: {
50
+ alt: "This is the alt text!",
51
+ on_error: "this.classList.add('image-error')",
52
+ rounded: true,
53
+ size: "xs",
54
+ url: "not_a_picture"
55
+ }
56
+ ) %>
57
+
58
+ <br>
59
+ <br>
60
+
61
+ <%= pb_rails("body",
62
+ props: {
63
+ text: "Or hide it completely:"
64
+ }
65
+ ) %>
66
+
67
+ <%= pb_rails("image",
68
+ props: {
69
+ alt: "This is the alt text!",
70
+ on_error: "this.style.display = 'none'",
71
+ rounded: true,
72
+ size: "xs",
73
+ url: "not_a_picture",
74
+ }
75
+ ) %>