playbook_ui 11.4.0 → 11.5.0.pre.alpha.pre.rubocop

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/button.test.js +6 -8
  3. data/app/pb_kits/playbook/pb_date/_date.tsx +1 -1
  4. data/app/pb_kits/playbook/pb_date_picker/_date_picker.jsx +13 -1
  5. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +24 -19
  6. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -1
  7. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +8 -0
  8. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.js +25 -3
  9. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.html.erb +44 -0
  10. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.jsx +60 -0
  11. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.md +9 -0
  12. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions_element.html.erb +33 -0
  13. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions_element.jsx +67 -0
  14. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +4 -0
  15. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +2 -0
  16. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_overrides.scss +4 -4
  17. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.tsx +142 -0
  18. data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.test.js +116 -0
  19. data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_default.jsx +1 -1
  20. data/app/pb_kits/playbook/pb_date_time/{_date_time.jsx → _date_time.tsx} +2 -5
  21. data/app/pb_kits/playbook/pb_date_time/dateTime.test.js +110 -0
  22. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_align.jsx +1 -1
  23. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_default.jsx +1 -1
  24. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_size.jsx +1 -1
  25. data/app/pb_kits/playbook/pb_date_year_stacked/{_date_year_stacked.jsx → _date_year_stacked.tsx} +6 -6
  26. data/app/pb_kits/playbook/pb_date_year_stacked/date_year_stacked.test.js +67 -0
  27. data/app/pb_kits/playbook/pb_dialog/_dialog.jsx +32 -14
  28. data/app/pb_kits/playbook/pb_dialog/_dialog.scss +5 -0
  29. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_body.jsx +2 -2
  30. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_footer.jsx +22 -4
  31. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_header.jsx +3 -3
  32. data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +79 -17
  33. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.jsx +55 -93
  34. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.jsx +79 -42
  35. data/app/pb_kits/playbook/pb_file_upload/{_file_upload.jsx → _file_upload.tsx} +6 -10
  36. data/app/pb_kits/playbook/pb_form_group/{_form_group.jsx → _form_group.tsx} +1 -4
  37. data/app/pb_kits/playbook/pb_form_group/form_group.test.js +17 -0
  38. data/app/pb_kits/playbook/pb_hashtag/_hashtag.tsx +10 -1
  39. data/app/pb_kits/playbook/pb_hashtag/docs/_hashtag_link.html.erb +5 -0
  40. data/app/pb_kits/playbook/pb_hashtag/docs/_hashtag_link.jsx +26 -0
  41. data/app/pb_kits/playbook/pb_hashtag/docs/_hashtag_link.md +1 -0
  42. data/app/pb_kits/playbook/pb_hashtag/docs/example.yml +2 -0
  43. data/app/pb_kits/playbook/pb_hashtag/docs/index.js +1 -0
  44. data/app/pb_kits/playbook/pb_hashtag/hashtag.html.erb +1 -1
  45. data/app/pb_kits/playbook/pb_hashtag/hashtag.rb +6 -0
  46. data/app/pb_kits/playbook/pb_hashtag/hashtag.test.js +54 -0
  47. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.jsx +3 -0
  48. data/app/pb_kits/playbook/pb_home_address_street/city_emphasis.html.erb +2 -1
  49. data/app/pb_kits/playbook/pb_home_address_street/city_emphasis.rb +2 -0
  50. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_link.html.erb +12 -0
  51. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_link.jsx +23 -0
  52. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_link.md +1 -0
  53. data/app/pb_kits/playbook/pb_home_address_street/docs/example.yml +3 -0
  54. data/app/pb_kits/playbook/pb_home_address_street/docs/index.js +1 -0
  55. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.rb +4 -0
  56. data/app/pb_kits/playbook/pb_home_address_street/street_emphasis.html.erb +2 -1
  57. data/app/pb_kits/playbook/pb_home_address_street/street_emphasis.rb +4 -1
  58. data/app/pb_kits/playbook/pb_layout/{_layout.jsx → _layout.tsx} +13 -19
  59. data/app/pb_kits/playbook/pb_layout/layout.test.js +98 -0
  60. data/app/pb_kits/playbook/pb_lightbox/lightbox.test.jsx +23 -15
  61. data/app/pb_kits/playbook/pb_time/_time.tsx +2 -2
  62. data/app/pb_kits/playbook/pb_timestamp/_timestamp.jsx +5 -2
  63. data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.html.erb +9 -0
  64. data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.jsx +10 -0
  65. data/app/pb_kits/playbook/pb_timestamp/timestamp.rb +4 -1
  66. data/app/pb_kits/playbook/pb_timestamp/timestamp.test.js +164 -0
  67. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +0 -4
  68. data/app/pb_kits/playbook/pb_tooltip/tooltip.test.jsx +11 -8
  69. data/app/pb_kits/playbook/tokens/_colors.scss +74 -74
  70. data/app/pb_kits/playbook/tokens/_typography.scss +8 -8
  71. data/app/pb_kits/playbook/utilities/_flexbox.scss +11 -11
  72. data/app/pb_kits/playbook/utilities/{_align_content.scss → flexbox_global_props/_align_content.scss} +0 -0
  73. data/app/pb_kits/playbook/utilities/{_align_items.scss → flexbox_global_props/_align_items.scss} +0 -0
  74. data/app/pb_kits/playbook/utilities/{_align_self.scss → flexbox_global_props/_align_self.scss} +0 -0
  75. data/app/pb_kits/playbook/utilities/{_flex.scss → flexbox_global_props/_flex.scss} +0 -0
  76. data/app/pb_kits/playbook/utilities/{_flex_direction.scss → flexbox_global_props/_flex_direction.scss} +0 -0
  77. data/app/pb_kits/playbook/utilities/{_flex_grow.scss → flexbox_global_props/_flex_grow.scss} +0 -0
  78. data/app/pb_kits/playbook/utilities/{_flex_shrink.scss → flexbox_global_props/_flex_shrink.scss} +0 -0
  79. data/app/pb_kits/playbook/utilities/{_flex_wrap.scss → flexbox_global_props/_flex_wrap.scss} +0 -0
  80. data/app/pb_kits/playbook/utilities/{_justify_content.scss → flexbox_global_props/_justify_content.scss} +0 -0
  81. data/app/pb_kits/playbook/utilities/{_justify_self.scss → flexbox_global_props/_justify_self.scss} +0 -0
  82. data/app/pb_kits/playbook/utilities/{_order.scss → flexbox_global_props/_order.scss} +0 -0
  83. data/app/pb_kits/playbook/utilities/props.ts +1 -1
  84. data/app/pb_kits/playbook/utilities/test-utils.js +2 -3
  85. data/lib/playbook/version.rb +2 -2
  86. metadata +39 -21
  87. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.jsx +0 -155
@@ -3,6 +3,8 @@
3
3
  module Playbook
4
4
  module PbHashtag
5
5
  class Hashtag < Playbook::KitBase
6
+ prop :new_window, type: Playbook::Props::Boolean,
7
+ default: false
6
8
  prop :text
7
9
  prop :type, type: Playbook::Props::Enum,
8
10
  values: %w[default project home appointment],
@@ -17,6 +19,10 @@ module Playbook
17
19
  type_text + text
18
20
  end
19
21
 
22
+ def link_option
23
+ new_window ? "_blank" : "_self"
24
+ end
25
+
20
26
  private
21
27
 
22
28
  def type_text
@@ -0,0 +1,54 @@
1
+
2
+ import React from 'react'
3
+ import { render, screen, cleanup } from "../utilities/test-utils";
4
+
5
+ import { Hashtag } from "..";
6
+
7
+
8
+ const testId = "primary-test"
9
+ const text="Open in a new window"
10
+ const type="project"
11
+ const url="https://google.com"
12
+ const typeMap = {
13
+ home: 'H#',
14
+ project: 'P#',
15
+ appointment: 'A#',
16
+ default: '#',
17
+ }
18
+
19
+ function HashtagTest(props) {
20
+ return (
21
+ <Hashtag
22
+ data={{ testid: testId }}
23
+ text={text}
24
+ type={type}
25
+ url={url}
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ test("renders the component", () => {
32
+ render(<HashtagTest/>);
33
+ const kit = screen.getByTestId("primary-test");
34
+ expect(kit).toBeInTheDocument();
35
+ expect(kit).toHaveClass("pb_hashtag_kit");
36
+
37
+ cleanup()
38
+ });
39
+
40
+ test("should pass in url property and allow links to open in a new window", () => {
41
+ const { container } = render(<HashtagTest newWindow />);
42
+ expect(container.getElementsByClassName("pb_hashtag_kit")[0].firstChild).toHaveAttribute("href", url);
43
+ expect(container.getElementsByClassName("pb_hashtag_kit")[0].firstChild).toHaveAttribute("target", "_blank");
44
+
45
+ cleanup()
46
+ });
47
+
48
+ test("renders the badge kit with appropriate text", () => {
49
+ const { container } = render(<HashtagTest />);
50
+ expect(container.getElementsByClassName("pb_badge_kit_primary")[0]).toBeInTheDocument;
51
+ expect(container.getElementsByClassName("pb_badge_kit_primary")[0]).toHaveTextContent(typeMap[type] + text);
52
+
53
+ cleanup()
54
+ });
@@ -20,6 +20,7 @@ type HomeAddressStreetProps = {
20
20
  homeId: number,
21
21
  houseStyle: string,
22
22
  homeUrl: string,
23
+ newWindow: Boolean,
23
24
  state: string,
24
25
  zipcode: string,
25
26
  territory: string,
@@ -35,6 +36,7 @@ const HomeAddressStreet = (props: HomeAddressStreetProps) => {
35
36
  emphasis = 'street',
36
37
  homeId,
37
38
  homeUrl,
39
+ newWindow,
38
40
  houseStyle,
39
41
  state,
40
42
  zipcode,
@@ -106,6 +108,7 @@ const HomeAddressStreet = (props: HomeAddressStreetProps) => {
106
108
  <Hashtag
107
109
  classname="home-hashtag"
108
110
  dark={dark}
111
+ newWindow={newWindow}
109
112
  text={homeId}
110
113
  type="home"
111
114
  url={homeUrl || '#'}
@@ -32,7 +32,8 @@
32
32
  url: object.home_url || "#",
33
33
  type: "home",
34
34
  dark: object.dark,
35
- classname: "home-hashtag"}) %>
35
+ classname: "home-hashtag",
36
+ new_window: object.new_window}) %>
36
37
  <% end %>
37
38
 
38
39
  <%= pb_rails "body", props: { color: "light", tag: "span", dark: object.dark } do %>
@@ -8,6 +8,8 @@ module Playbook
8
8
  prop :city_state
9
9
  prop :home_id, type: Playbook::Props::Number
10
10
  prop :home_url
11
+ prop :new_window, type: Playbook::Props::Boolean,
12
+ default: false
11
13
  prop :territory
12
14
  prop :zip
13
15
  prop :dark, type: Playbook::Props::Boolean, default: false
@@ -0,0 +1,12 @@
1
+ <%= pb_rails("home_address_street", props: {
2
+ address: "70 Prospect Ave",
3
+ address_cont: "Apt M18",
4
+ city: "West Chester",
5
+ home_id: 8250263,
6
+ home_url: "https://powerhrg.com/",
7
+ house_style: "Colonial",
8
+ new_window: true,
9
+ state: "PA",
10
+ zipcode: "19382",
11
+ territory: "PHL",
12
+ }) %>
@@ -0,0 +1,23 @@
1
+ import React from 'react'
2
+
3
+ import HomeAddressStreet from '../_home_address_street'
4
+
5
+ const HomeAddressStreetLink= (props) => {
6
+ return (
7
+ <HomeAddressStreet
8
+ address="70 Prospect Ave"
9
+ addressCont="Apt M18"
10
+ city="West Chester"
11
+ homeId={8250263}
12
+ homeUrl="https://powerhrg.com/"
13
+ houseStyle="Colonial"
14
+ newWindow
15
+ state="PA"
16
+ territory="PHL"
17
+ zipcode="19382"
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ export default HomeAddressStreetLink
@@ -0,0 +1 @@
1
+ Use the `newWindow` / `new_window` prop to control whether the link opens on the same page or a new tab (same page is the default behavior)
@@ -4,8 +4,11 @@ examples:
4
4
  - home_address_street_default: Default
5
5
  - home_address_street_emphasis: Emphasis
6
6
  - home_address_street_modified: Modified
7
+ - home_address_street_link: Link
7
8
 
8
9
  react:
9
10
  - home_address_street_default: Default
10
11
  - home_address_street_emphasis: Emphasis
11
12
  - home_address_street_modified: Modified
13
+ - home_address_street_link: Link
14
+
@@ -1,3 +1,4 @@
1
1
  export { default as HomeAddressStreetDefault } from './_home_address_street_default.jsx'
2
2
  export { default as HomeAddressStreetEmphasis } from './_home_address_street_emphasis.jsx'
3
3
  export { default as HomeAddressStreetModified } from './_home_address_street_modified.jsx'
4
+ export { default as HomeAddressStreetLink } from './_home_address_street_link.jsx'
@@ -12,6 +12,8 @@ module Playbook
12
12
  prop :home_id, type: Playbook::Props::Number
13
13
  prop :home_url
14
14
  prop :house_style
15
+ prop :new_window, type: Playbook::Props::Boolean,
16
+ default: false
15
17
  prop :state
16
18
  prop :zipcode
17
19
  prop :territory
@@ -53,6 +55,7 @@ module Playbook
53
55
  dark: dark,
54
56
  home_id: home_id,
55
57
  home_url: home_url,
58
+ new_window: new_window,
56
59
  territory: territory,
57
60
  zip: zip,
58
61
  }
@@ -66,6 +69,7 @@ module Playbook
66
69
  dark: dark,
67
70
  home_id: home_id,
68
71
  home_url: home_url,
72
+ new_window: new_window,
69
73
  territory: territory,
70
74
  }
71
75
  end
@@ -22,7 +22,8 @@
22
22
  url: object.home_url || "#",
23
23
  type: "home",
24
24
  dark: object.dark,
25
- classname: "home-hashtag"}) %>
25
+ classname: "home-hashtag",
26
+ new_window: object.new_window}) %>
26
27
  <% end %>
27
28
 
28
29
  <%= pb_rails "body", props: { color: "light", tag: "span", dark: object.dark } do %>
@@ -8,8 +8,11 @@ module Playbook
8
8
  prop :city_state_zip
9
9
  prop :home_id, type: Playbook::Props::Number
10
10
  prop :home_url
11
+ prop :new_window, type: Playbook::Props::Boolean,
12
+ default: false
11
13
  prop :territory
12
- prop :dark, type: Playbook::Props::Boolean, default: false
14
+ prop :dark, type: Playbook::Props::Boolean,
15
+ default: false
13
16
  end
14
17
  end
15
18
  end
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import classnames from 'classnames'
5
3
  import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
@@ -7,8 +5,8 @@ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
7
5
  import { globalProps } from '../utilities/globalProps'
8
6
 
9
7
  type LayoutPropTypes = {
10
- aria?: object,
11
- children?: array<React.ReactNode> | React.ReactNode,
8
+ aria?: {[key: string]: string},
9
+ children?: React.ReactChild[] | React.ReactChild,
12
10
  className?: string,
13
11
  collapse?: "xs" | "sm" | "md" | "lg" | "xl",
14
12
  dark?: boolean,
@@ -23,28 +21,28 @@ type LayoutPropTypes = {
23
21
  }
24
22
 
25
23
  type LayoutSideProps = {
26
- children: array<React.ReactNode> | React.ReactNode,
24
+ children: React.ReactNode[] | React.ReactNode,
27
25
  className?: string,
28
26
  }
29
27
 
30
28
  type LayoutBodyProps = {
31
- children: array<React.ReactNode> | React.ReactNode,
29
+ children: React.ReactNode[] | React.ReactNode,
32
30
  className?: string,
33
31
  }
34
32
 
35
33
  type LayoutItemProps = {
36
- children: array<React.ReactNode> | React.ReactNode,
34
+ children: React.ReactNode[] | React.ReactNode,
37
35
  className?: string,
38
36
  size?: "sm" | "md" | "lg"
39
37
  }
40
38
 
41
39
  type LayoutHeaderProps = {
42
- children: array<React.ReactNode> | React.ReactNode,
40
+ children: React.ReactNode[] | React.ReactNode,
43
41
  className?: string,
44
42
  }
45
43
 
46
44
  type LayoutFooterProps = {
47
- children: array<React.ReactNode> | React.ReactNode,
45
+ children: React.ReactNode[] | React.ReactNode,
48
46
  className?: string,
49
47
  }
50
48
 
@@ -99,8 +97,6 @@ const Footer = (props: LayoutFooterProps) => {
99
97
  )
100
98
  }
101
99
 
102
- // Main componenet
103
-
104
100
  const Layout = (props: LayoutPropTypes) => {
105
101
  const {
106
102
  aria = {},
@@ -138,25 +134,23 @@ const Layout = (props: LayoutPropTypes) => {
138
134
  ? ''
139
135
  : buildCss('layout', position, 'collapse', collapse)
140
136
 
141
- const layoutChildren =
142
- typeof children === 'object' && children.length ? children : [children]
137
+ const layoutChildren = React.Children.toArray(children)
143
138
 
144
- const subComponentTags = (tagName) => {
139
+ const subComponentTags = (tagName: string) => {
145
140
  return layoutChildren
146
- .filter((c) => {
147
- return c.type && c.type.displayName === tagName
141
+ .filter((c: React.ReactElement & {type: {displayName: string}}) => {
142
+ return c.type?.displayName === tagName
148
143
  })
149
144
  .map((child, i) => {
150
- return React.cloneElement(child, {
145
+ return React.cloneElement(child as React.ReactElement, {
151
146
  key: `${tagName.toLowerCase()}-${i}`,
152
147
  })
153
148
  })
154
149
  }
155
150
 
156
151
  const nonSideChildren = layoutChildren.filter(
157
- (child) => !child.type || child.type.displayName !== 'Side'
152
+ (child: React.ReactElement & {type: {displayName: string}}) => child.type?.displayName !== 'Side'
158
153
  )
159
-
160
154
  return (
161
155
  <div
162
156
  {...ariaProps}
@@ -0,0 +1,98 @@
1
+ import React from "react"
2
+ import { render, cleanup } from "../utilities/test-utils"
3
+ import { Layout, Card } from ".."
4
+
5
+ function LayoutTest(props) {
6
+ return (
7
+ <Layout {...props}>
8
+ <Layout.Side>{"Light"}</Layout.Side>
9
+ <Layout.Body>{"Body"}</Layout.Body>
10
+ </Layout>
11
+ )
12
+ }
13
+
14
+ test("render all color variants", () => {
15
+ const testValues = [undefined, "light", "dark", "gradient"]
16
+ testValues.forEach((variant) => {
17
+ const { getByTestId } = render(
18
+ <LayoutTest data={{ testid: `test-${variant}` }}
19
+ variant={variant} />
20
+ )
21
+ expect(getByTestId(`test-${variant}`)).toHaveClass(
22
+ `pb_layout_kit_sidebar_size_md_left_${
23
+ variant == undefined ? "light" : variant
24
+ }`
25
+ )
26
+
27
+ cleanup()
28
+ })
29
+ })
30
+
31
+ test("render transparent class", () => {
32
+ const id = "transparent"
33
+
34
+ const { getByTestId } = render(
35
+ <LayoutTest data={{ testid: `test-${id}` }}
36
+ variant={id} />
37
+ )
38
+ expect(getByTestId(`test-${id}`)).toHaveClass(
39
+ `pb_layout_kit_sidebar_size_md_left_${id}`
40
+ )
41
+
42
+ cleanup()
43
+ })
44
+
45
+ test("render all sizes variants", () => {
46
+ const testValues = ["xs", "sm", "md", "lg", "xl"]
47
+ testValues.forEach((size) => {
48
+ const { getByTestId } = render(
49
+ <LayoutTest data={{ testid: `test-${size}` }}
50
+ size={size} />
51
+ )
52
+ expect(getByTestId(`test-${size}`)).toHaveClass(
53
+ `pb_layout_kit_sidebar_size_${size}_left_light`
54
+ )
55
+
56
+ cleanup()
57
+ })
58
+ })
59
+
60
+ test("render all layout variants", () => {
61
+ const testValues = [
62
+ {
63
+ layout: "collection",
64
+ expected: "pb_layout_kit_collection",
65
+ },
66
+ {
67
+ layout: "collection_detail",
68
+ expected: "pb_layout_kit_collection_detail_size_md_left_light",
69
+ },
70
+ {
71
+ layout: "content",
72
+ expected: "pb_layout_kit_content_size_md_left_light",
73
+ },
74
+ {
75
+ layout: "kanban",
76
+ expected: "pb_layout_kit_kanban",
77
+ },
78
+ {
79
+ layout: "masonry",
80
+ expected: "pb_layout_kit_masonry_size_md_left_light",
81
+ },
82
+ ]
83
+
84
+ testValues.forEach(({ layout, expected }) => {
85
+ const { getByTestId, container } = render(
86
+ <Layout data={{ testid: `test-${layout}` }}
87
+ layout={layout}>
88
+ <Layout.Body>
89
+ <Card>{"Card content"}</Card>
90
+ </Layout.Body>
91
+ </Layout>
92
+ )
93
+ console.log(container)
94
+
95
+ expect(getByTestId(`test-${layout}`)).toHaveClass(expected)
96
+ cleanup()
97
+ })
98
+ })
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { fireEvent, render, screen, waitForElementToBeRemoved } from '../utilities/test-utils'
2
+ import { cleanup, fireEvent, render, screen } from '../utilities/test-utils'
3
3
 
4
4
  import { Lightbox } from '../'
5
5
 
@@ -27,6 +27,7 @@ test('Kit renders', () => {
27
27
  const kit = screen.getByTestId(testId)
28
28
  expect(kit).toHaveClass(`${kitClass} customClass`)
29
29
  expect(kit).toBeInTheDocument()
30
+ cleanup()
30
31
  })
31
32
 
32
33
  test('Shows selected images', () => {
@@ -67,9 +68,12 @@ test('Shows selected images', () => {
67
68
  )
68
69
 
69
70
  expect(image).toHaveAttribute('src', TEST_PHOTOS[0])
71
+ cleanup()
70
72
  })
71
73
 
72
74
  test('Closes on escape key', async () => {
75
+ const mockClose = jest.fn()
76
+
73
77
  render(
74
78
  <Lightbox
75
79
  data={{ testid: testId }}
@@ -77,25 +81,29 @@ test('Closes on escape key', async () => {
77
81
  iconSize="3x"
78
82
  id="test1"
79
83
  initialPhoto={0}
80
- onClose={() => {}}
84
+ onClose={mockClose}
81
85
  photos={TEST_PHOTOS}
82
86
  />
83
87
  )
84
88
 
85
- const kit = screen.getByTestId(testId)
86
-
87
- fireEvent(
88
- document.body,
89
- new KeyboardEvent('keydown', {
90
- keyCode: 27, //escape
91
- })
89
+ fireEvent.keyDown(
90
+ global.window,
91
+ {
92
+ bubbles: true,
93
+ key: "Escape",
94
+ code: "Escape",
95
+ keyCode: 27,
96
+ charCode: 27
97
+ }
92
98
  )
93
99
 
94
- waitForElementToBeRemoved(kit)
95
- .then(() => expect(kit).not.toBeInTheDocument())
100
+ expect(mockClose).toHaveBeenCalled()
101
+ cleanup()
96
102
  })
97
103
 
98
- test('Closes on close button', () => {
104
+ test('Closes on close button', async () => {
105
+ const mockClose = jest.fn()
106
+
99
107
  render(
100
108
  <Lightbox
101
109
  data={{ testid: testId }}
@@ -103,7 +111,7 @@ test('Closes on close button', () => {
103
111
  iconSize="3x"
104
112
  id="test1"
105
113
  initialPhoto={0}
106
- onClose={() => {}}
114
+ onClose={mockClose}
107
115
  photos={TEST_PHOTOS}
108
116
  />
109
117
  )
@@ -119,6 +127,6 @@ test('Closes on close button', () => {
119
127
  }),
120
128
  )
121
129
 
122
- waitForElementToBeRemoved(kit)
123
- .then(() => expect(kit).not.toBeInTheDocument())
130
+ expect(mockClose).toHaveBeenCalled()
131
+ cleanup()
124
132
  })
@@ -3,7 +3,7 @@ import classnames from "classnames";
3
3
 
4
4
  import DateTime from "../pb_kit/dateTime";
5
5
  import { buildCss } from "../utilities/props";
6
- import { globalProps } from "../utilities/globalProps";
6
+ import { globalProps, GlobalProps } from "../utilities/globalProps";
7
7
 
8
8
  import Body from "../pb_body/_body";
9
9
  import Caption from "../pb_caption/_caption";
@@ -20,7 +20,7 @@ type TimeProps = {
20
20
  size?: "md" | "sm";
21
21
  showTimezone?: boolean;
22
22
  timeZone?: string;
23
- };
23
+ } & GlobalProps
24
24
 
25
25
  const Time = (props: TimeProps) => {
26
26
  const {
@@ -21,6 +21,7 @@ type TimestampProps = {
21
21
  id?: string,
22
22
  showDate?: boolean,
23
23
  showUser?: boolean,
24
+ hideUpdated?: boolean,
24
25
  showTimezone?: boolean,
25
26
  variant?: "default" | "elapsed" | "updated"
26
27
  }
@@ -37,6 +38,7 @@ const Timestamp = (props: TimestampProps) => {
37
38
  timezone,
38
39
  showDate = true,
39
40
  showUser = false,
41
+ hideUpdated = false,
40
42
  showTimezone = false,
41
43
  variant = 'default',
42
44
  } = props
@@ -57,6 +59,7 @@ const Timestamp = (props: TimestampProps) => {
57
59
  const dateDisplay = `${dateTimestamp.toMonth()} ${dateTimestamp.toDay()}`
58
60
  const shouldShowUser = showUser == true && text.length > 0
59
61
  const shouldShowTimezone = showTimezone == true && timezone.length > 0
62
+ const updatedText = hideUpdated ? "" : "Last updated"
60
63
  const userDisplay = shouldShowUser ? ` by ${text}` : ''
61
64
 
62
65
  let timeDisplay = `${dateTimestamp.toHour()}:${dateTimestamp.toMinute()}${dateTimestamp.toMeridian()}`
@@ -81,7 +84,7 @@ const Timestamp = (props: TimestampProps) => {
81
84
  }
82
85
 
83
86
  const formatElapsedString = () => {
84
- return `Last updated ${userDisplay} ${dateTimestamp.value.fromNow()}`
87
+ return `${updatedText} ${userDisplay} ${dateTimestamp.value.fromNow()}`
85
88
  }
86
89
 
87
90
  const captionText = () => {
@@ -89,7 +92,7 @@ const Timestamp = (props: TimestampProps) => {
89
92
  case 'updated':
90
93
  return formatUpdatedString(userDisplay, dateTimestamp)
91
94
  case 'elapsed':
92
- return formatElapsedString(userDisplay, timeDisplay)
95
+ return formatElapsedString(userDisplay, timeDisplay, updatedText)
93
96
  default:
94
97
  return showDate ? timestamp ? fullDateDisplay() : text : fullTimeDisplay()
95
98
  }
@@ -12,3 +12,12 @@
12
12
  variant: "elapsed",
13
13
  show_user: false
14
14
  }) %>
15
+
16
+ <br>
17
+
18
+ <%= pb_rails("timestamp", props: {
19
+ timestamp: DateTime.now,
20
+ variant: "elapsed",
21
+ show_user: false,
22
+ hide_updated: true
23
+ }) %>
@@ -28,6 +28,16 @@ const TimestampElapsed = (props) => {
28
28
  variant="elapsed"
29
29
  {...props}
30
30
  />
31
+
32
+ <br />
33
+
34
+ <Timestamp
35
+ hideUpdated
36
+ showUser={false}
37
+ timestamp={customDate}
38
+ variant="elapsed"
39
+ {...props}
40
+ />
31
41
  </div>
32
42
  )
33
43
  }
@@ -12,6 +12,8 @@ module Playbook
12
12
  prop :align, type: Playbook::Props::Enum,
13
13
  values: %w[left center right],
14
14
  default: "left"
15
+ prop :hide_updated, type: Playbook::Props::Boolean,
16
+ default: false
15
17
  prop :show_date, type: Playbook::Props::Boolean,
16
18
  default: true
17
19
  prop :show_timezone, type: Playbook::Props::Boolean,
@@ -70,8 +72,9 @@ module Playbook
70
72
  def format_elapsed_string
71
73
  user_string = show_user ? " by #{text}" : ""
72
74
  datetime_string = " #{time_ago_in_words(pb_date_time.convert_to_timestamp)} ago"
75
+ updated_string = hide_updated ? "" : "Last updated"
73
76
 
74
- "Last updated#{user_string}#{datetime_string}"
77
+ "#{updated_string}#{user_string}#{datetime_string}"
75
78
  end
76
79
 
77
80
  def datetime_or_text