playbook_ui 11.4.0 → 11.5.0.pre.alpha.datepicker1

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/data/menu.yml +0 -13
  3. data/app/pb_kits/playbook/pb_badge/badge.test.js +80 -0
  4. data/app/pb_kits/playbook/pb_button/_button.tsx +7 -2
  5. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +7 -0
  6. data/app/pb_kits/playbook/pb_button/button.html.erb +11 -0
  7. data/app/pb_kits/playbook/pb_button/button.rb +3 -0
  8. data/app/pb_kits/playbook/pb_button/button.test.js +6 -8
  9. data/app/pb_kits/playbook/pb_button/docs/_button_block_content.html.erb +1 -1
  10. data/app/pb_kits/playbook/pb_button/docs/_button_block_content.jsx +12 -9
  11. data/app/pb_kits/playbook/pb_button/docs/_button_block_content.md +1 -0
  12. data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.html.erb +2 -0
  13. data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.jsx +23 -0
  14. data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.md +1 -0
  15. data/app/pb_kits/playbook/pb_button/docs/example.yml +2 -0
  16. data/app/pb_kits/playbook/pb_button/docs/index.js +1 -0
  17. data/app/pb_kits/playbook/pb_date/_date.tsx +1 -1
  18. data/app/pb_kits/playbook/pb_date_picker/_date_picker.jsx +13 -1
  19. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +24 -19
  20. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -1
  21. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +9 -0
  22. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.js +25 -3
  23. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.html.erb +44 -0
  24. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.jsx +60 -0
  25. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions.md +9 -0
  26. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions_element.html.erb +33 -0
  27. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_positions_element.jsx +67 -0
  28. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +4 -0
  29. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +2 -0
  30. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_flatpickr_styles.scss +0 -3
  31. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_overrides.scss +4 -4
  32. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.tsx +142 -0
  33. data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.test.js +116 -0
  34. data/app/pb_kits/playbook/pb_date_range_inline/docs/_date_range_inline_default.jsx +1 -1
  35. data/app/pb_kits/playbook/pb_date_time/{_date_time.jsx → _date_time.tsx} +2 -5
  36. data/app/pb_kits/playbook/pb_date_time/dateTime.test.js +110 -0
  37. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_align.jsx +1 -1
  38. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_default.jsx +1 -1
  39. data/app/pb_kits/playbook/pb_date_time/docs/_date_time_size.jsx +1 -1
  40. data/app/pb_kits/playbook/pb_date_year_stacked/{_date_year_stacked.jsx → _date_year_stacked.tsx} +6 -6
  41. data/app/pb_kits/playbook/pb_date_year_stacked/date_year_stacked.test.js +67 -0
  42. data/app/pb_kits/playbook/pb_dialog/_dialog.jsx +32 -14
  43. data/app/pb_kits/playbook/pb_dialog/_dialog.scss +5 -0
  44. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_body.jsx +2 -2
  45. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_footer.jsx +22 -4
  46. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_header.jsx +3 -3
  47. data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +79 -17
  48. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.jsx +55 -93
  49. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.jsx +79 -42
  50. data/app/pb_kits/playbook/pb_file_upload/{_file_upload.jsx → _file_upload.tsx} +6 -10
  51. data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.jsx +2 -0
  52. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.jsx +2 -0
  53. data/app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.jsx +2 -2
  54. data/app/pb_kits/playbook/pb_filter/docs/_filter_min_width.html.erb +1 -0
  55. data/app/pb_kits/playbook/pb_filter/docs/_filter_placement.html.erb +34 -0
  56. data/app/pb_kits/playbook/pb_filter/docs/_filter_placement.jsx +66 -0
  57. data/app/pb_kits/playbook/pb_filter/docs/_filter_placement.md +4 -0
  58. data/app/pb_kits/playbook/pb_filter/docs/example.yml +2 -0
  59. data/app/pb_kits/playbook/pb_filter/docs/index.js +1 -0
  60. data/app/pb_kits/playbook/pb_filter/filter.html.erb +2 -2
  61. data/app/pb_kits/playbook/pb_filter/filter.rb +3 -0
  62. data/app/pb_kits/playbook/pb_filter/filter.test.js +76 -0
  63. data/app/pb_kits/playbook/pb_form_group/{_form_group.jsx → _form_group.tsx} +1 -4
  64. data/app/pb_kits/playbook/pb_form_group/form_group.test.js +17 -0
  65. data/app/pb_kits/playbook/pb_hashtag/_hashtag.tsx +10 -1
  66. data/app/pb_kits/playbook/pb_hashtag/docs/_hashtag_link.html.erb +5 -0
  67. data/app/pb_kits/playbook/pb_hashtag/docs/_hashtag_link.jsx +26 -0
  68. data/app/pb_kits/playbook/pb_hashtag/docs/_hashtag_link.md +1 -0
  69. data/app/pb_kits/playbook/pb_hashtag/docs/example.yml +2 -0
  70. data/app/pb_kits/playbook/pb_hashtag/docs/index.js +1 -0
  71. data/app/pb_kits/playbook/pb_hashtag/hashtag.html.erb +1 -1
  72. data/app/pb_kits/playbook/pb_hashtag/hashtag.rb +6 -0
  73. data/app/pb_kits/playbook/pb_hashtag/hashtag.test.js +54 -0
  74. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +129 -0
  75. data/app/pb_kits/playbook/pb_home_address_street/city_emphasis.html.erb +2 -1
  76. data/app/pb_kits/playbook/pb_home_address_street/city_emphasis.rb +2 -0
  77. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_default.jsx +1 -1
  78. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_emphasis.jsx +2 -2
  79. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_link.html.erb +12 -0
  80. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_link.jsx +23 -0
  81. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_link.md +1 -0
  82. data/app/pb_kits/playbook/pb_home_address_street/docs/example.yml +3 -0
  83. data/app/pb_kits/playbook/pb_home_address_street/docs/index.js +1 -0
  84. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.rb +4 -0
  85. data/app/pb_kits/playbook/pb_home_address_street/home_adress_street.test.js +60 -0
  86. data/app/pb_kits/playbook/pb_home_address_street/street_emphasis.html.erb +2 -1
  87. data/app/pb_kits/playbook/pb_home_address_street/street_emphasis.rb +4 -1
  88. data/app/pb_kits/playbook/pb_icon_stat_value/{_icon_stat_value.jsx → _icon_stat_value.tsx} +2 -4
  89. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +154 -0
  90. data/app/pb_kits/playbook/pb_icon_value/{_icon_value.jsx → _icon_value.tsx} +2 -4
  91. data/app/pb_kits/playbook/pb_icon_value/icon_value.test.js +77 -0
  92. data/app/pb_kits/playbook/pb_label_value/_label_value.tsx +123 -0
  93. data/app/pb_kits/playbook/pb_label_value/label_value.test.js +109 -0
  94. data/app/pb_kits/playbook/pb_layout/{_layout.jsx → _layout.tsx} +13 -19
  95. data/app/pb_kits/playbook/pb_layout/layout.test.js +97 -0
  96. data/app/pb_kits/playbook/pb_lightbox/lightbox.test.jsx +23 -15
  97. data/app/pb_kits/playbook/pb_popover/popover.rb +1 -1
  98. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +0 -1
  99. data/app/pb_kits/playbook/pb_time/_time.tsx +2 -2
  100. data/app/pb_kits/playbook/pb_timestamp/_timestamp.jsx +5 -2
  101. data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.html.erb +9 -0
  102. data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_elapsed.jsx +10 -0
  103. data/app/pb_kits/playbook/pb_timestamp/timestamp.rb +4 -1
  104. data/app/pb_kits/playbook/pb_timestamp/timestamp.test.js +164 -0
  105. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +0 -4
  106. data/app/pb_kits/playbook/pb_tooltip/tooltip.test.jsx +11 -8
  107. data/app/pb_kits/playbook/tokens/_colors.scss +74 -74
  108. data/app/pb_kits/playbook/tokens/_typography.scss +8 -8
  109. data/app/pb_kits/playbook/utilities/_flexbox.scss +11 -11
  110. data/app/pb_kits/playbook/utilities/{_align_content.scss → flexbox_global_props/_align_content.scss} +0 -0
  111. data/app/pb_kits/playbook/utilities/{_align_items.scss → flexbox_global_props/_align_items.scss} +0 -0
  112. data/app/pb_kits/playbook/utilities/{_align_self.scss → flexbox_global_props/_align_self.scss} +0 -0
  113. data/app/pb_kits/playbook/utilities/{_flex.scss → flexbox_global_props/_flex.scss} +0 -0
  114. data/app/pb_kits/playbook/utilities/{_flex_direction.scss → flexbox_global_props/_flex_direction.scss} +0 -0
  115. data/app/pb_kits/playbook/utilities/{_flex_grow.scss → flexbox_global_props/_flex_grow.scss} +0 -0
  116. data/app/pb_kits/playbook/utilities/{_flex_shrink.scss → flexbox_global_props/_flex_shrink.scss} +0 -0
  117. data/app/pb_kits/playbook/utilities/{_flex_wrap.scss → flexbox_global_props/_flex_wrap.scss} +0 -0
  118. data/app/pb_kits/playbook/utilities/{_justify_content.scss → flexbox_global_props/_justify_content.scss} +0 -0
  119. data/app/pb_kits/playbook/utilities/{_justify_self.scss → flexbox_global_props/_justify_self.scss} +0 -0
  120. data/app/pb_kits/playbook/utilities/{_order.scss → flexbox_global_props/_order.scss} +0 -0
  121. data/app/pb_kits/playbook/utilities/props.ts +1 -1
  122. data/app/pb_kits/playbook/utilities/test-utils.js +2 -3
  123. data/app/pb_kits/playbook/utilities/text.ts +1 -1
  124. data/lib/playbook/version.rb +2 -2
  125. metadata +56 -25
  126. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.jsx +0 -155
  127. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.jsx +0 -124
  128. data/app/pb_kits/playbook/pb_label_value/_label_value.jsx +0 -155
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 638051af443b06b03b9de8a9092d21f8ce06f3806e60bd43cec8463ce428a69a
4
- data.tar.gz: c43d207810694a318a13280bb917b8a295cb44310e05433a262639bee6b8778e
3
+ metadata.gz: 23dd757338e004c593559cfc4694eb98763f5ccd2e848fefa2887f8ccc0b46f6
4
+ data.tar.gz: 952a958a08a4ca5127e6981c21001757469ee0fc599a75dd076bc1dbd9d958ec
5
5
  SHA512:
6
- metadata.gz: 80aad4d2179d46bc3332b631a1f4e4e90640d61b3cbd3bfa1894cd8e5710f20ecea86f8d71cada0811e9ac434a99c70cd31a7622c33df2434d82370b5f0a9157
7
- data.tar.gz: 8a8562a4d3efced667089ca24567758a341255de55f885d1068c7722b301886d427f07943a03ae391d47a1b1d5b4ce279d7bb80a42d7e53042ed9b22ab71d4dc
6
+ metadata.gz: 007d11d01011984e0193310b17f2f3afc922281b9fb1fa0cc9dba28310fd258e4f08218d58ef80f10b8d370536b0e4c9534d26cad8861f41224ebca165938d03
7
+ data.tar.gz: 9161f9c2541a94573f547aaea38e81f299b6ab4c28a0242bb6bf528c0e2d0958434352f5a4d8dc463505e959b933a20b04140e81d0cdb0dbd4745cae367b77cf
@@ -104,16 +104,3 @@ kits:
104
104
  - title_detail
105
105
  - user_badge
106
106
  - walkthrough
107
- visual_guidelines:
108
- - colors
109
- - max_width
110
- - number_spacing
111
- - positioning
112
- - line_height
113
- - spacing
114
- - border_radius
115
- - typography
116
- - shadows
117
- - display
118
- - cursor
119
- - flex_box
@@ -0,0 +1,80 @@
1
+ import React from 'react'
2
+ import { cleanup, render, screen } from '../utilities/test-utils'
3
+
4
+ import Badge from './_badge'
5
+
6
+ const testId = "badge"
7
+
8
+ test('default class name', () => {
9
+ render(
10
+ <Badge
11
+ data={{ testid: testId }}
12
+ text="+1"
13
+ />
14
+ )
15
+
16
+ const kit = screen.getByTestId(testId)
17
+
18
+ expect(kit).toHaveClass('pb_badge_kit_neutral')
19
+ })
20
+
21
+ test('primary class name', () => {
22
+ render(
23
+ <Badge
24
+ data={{ testid: testId }}
25
+ text="+1"
26
+ variant="primary"
27
+ />
28
+ )
29
+
30
+ const kit = screen.getByTestId(testId)
31
+
32
+ expect(kit).toHaveClass('pb_badge_kit_primary')
33
+ })
34
+
35
+ test('displays text content', () => {
36
+ render(
37
+ <Badge
38
+ text="+1"
39
+ variant="primary"
40
+ />
41
+ )
42
+
43
+ const text = screen.getByText("+1")
44
+ expect(text).toBeInTheDocument()
45
+ })
46
+
47
+ test('displays rounded corners', () => {
48
+ render(
49
+ <Badge
50
+ data={{ testid: testId }}
51
+ rounded
52
+ text="+1"
53
+ variant="primary"
54
+ />
55
+ )
56
+
57
+ const kit = screen.getByTestId(testId)
58
+ expect(kit).toHaveClass('pb_badge_kit_primary_rounded')
59
+ })
60
+
61
+ test('displays color variants', () => {
62
+ [
63
+ "success",
64
+ "warning",
65
+ "error",
66
+ "info"
67
+ ].forEach((colorVariant) => {
68
+ render(
69
+ <Badge
70
+ data={{ testid: testId }}
71
+ text={colorVariant}
72
+ variant={colorVariant}
73
+ />
74
+ )
75
+ const kit = screen.getByTestId(testId)
76
+ expect(kit).toHaveClass(`pb_badge_kit_${colorVariant}`)
77
+
78
+ cleanup()
79
+ })
80
+ })
@@ -17,6 +17,7 @@ type ButtonPropTypes = {
17
17
  form?: string,
18
18
  fullWidth?: boolean,
19
19
  icon?: string,
20
+ iconRight?: boolean,
20
21
  id?: string,
21
22
  link?: string,
22
23
  loading?: boolean,
@@ -61,6 +62,7 @@ const Button = (props: ButtonPropTypes) => {
61
62
  data = {},
62
63
  disabled,
63
64
  icon = null,
65
+ iconRight = false,
64
66
  id,
65
67
  loading = false,
66
68
  onClick,
@@ -91,10 +93,13 @@ const Button = (props: ButtonPropTypes) => {
91
93
 
92
94
  const content = (
93
95
  <span className="pb_button_content">
94
- {icon && (
95
- <i className={`pb_icon_kit far fa-${icon} fa-fw`} />
96
+ {icon && !iconRight && (
97
+ <i className={`pb_icon_kit far fa-${icon} fa-fw button_with_icon`} />
96
98
  )}
97
99
  <span>{text || children}</span>
100
+ {icon && iconRight && (
101
+ <i className={`pb_icon_kit far fa-${icon} fa-fw button_with_icon_right`} />
102
+ )}
98
103
  </span>
99
104
  )
100
105
 
@@ -55,6 +55,13 @@ $pb_button_border_width: 0px;
55
55
  visibility: visible;
56
56
  }
57
57
 
58
+ .button_with_icon {
59
+ margin-right: $space_xs;
60
+ }
61
+ .button_with_icon_right {
62
+ margin-left: $space_xs;
63
+ }
64
+
58
65
  &:hover, &:focus {
59
66
  outline: none;
60
67
 
@@ -1,5 +1,16 @@
1
1
  <%= content_tag(object.tag,
2
2
  object.tag == "button" ? object.options : object.link_options) do %>
3
+ <% if object.icon && !object.icon_right %>
4
+ <span>
5
+ <%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_right: "xs" }) %>
6
+ </span>
7
+ <% end %>
3
8
  <%= pb_rails("icon", props: { icon: "spinner", pulse: true, fixed_width: true, classname: "loading-icon" }) %>
4
9
  <span class="pb_button_content"><%= content.presence || object.text %></span>
10
+ <% if object.icon && object.icon_right %>
11
+ <span>
12
+ <%= pb_rails("icon", props: { icon: "#{icon}", fixed_width: true, margin_left: "xs" }) %>
13
+ </span>
14
+ <% end %>
15
+
5
16
  <% end %>
@@ -7,6 +7,9 @@ module Playbook
7
7
  default: false
8
8
  prop :full_width, type: Playbook::Props::Boolean,
9
9
  default: false
10
+ prop :icon
11
+ prop :icon_right, type: Playbook::Props::Boolean,
12
+ default: false
10
13
  prop :link
11
14
  prop :loading, type: Playbook::Props::Boolean,
12
15
  default: false
@@ -11,14 +11,12 @@ const htmlType = 'submit',
11
11
 
12
12
  test('passes type, text, and value props to button', () => {
13
13
  render(
14
- <>
15
- <Button
16
- data={{ testid: 'primary-test' }}
17
- htmlType={htmlType}
18
- text={text}
19
- value={value}
20
- />
21
- </>
14
+ <Button
15
+ data={{ testid: 'primary-test' }}
16
+ htmlType={htmlType}
17
+ text={text}
18
+ value={value}
19
+ />
22
20
  )
23
21
 
24
22
  const kit = screen.getByTestId('primary-test')
@@ -1,4 +1,4 @@
1
1
  <%= pb_rails("button") do %>
2
- <%= pb_rails("icon", props: { icon: "users", fixed_width: true }) %>
2
+ <%= pb_rails("pill", props: { text:"5", fixed_width: true, margin_right: "xs", variant:"info" }) %>
3
3
  <span>Button with Block Content</span>
4
4
  <% end %>
@@ -1,15 +1,18 @@
1
- import React from 'react'
2
- import { Button } from '../../'
1
+ import React from "react";
2
+ import { Button, Pill } from "../../";
3
3
 
4
4
  const ButtonBlockContent = (props) => (
5
5
  <div>
6
- <Button
7
- fixedWidth
8
- icon="users"
9
- text="Button with Block Content"
6
+ <Button fixedWidth
10
7
  {...props}
11
- />
8
+ >
9
+ <Pill marginRight="xs"
10
+ text="5"
11
+ variant="info"
12
+ />
13
+ <span>Button with Block Content</span>
14
+ </Button>
12
15
  </div>
13
- )
16
+ );
14
17
 
15
- export default ButtonBlockContent
18
+ export default ButtonBlockContent;
@@ -0,0 +1 @@
1
+ Used when the user wants to display custom content within a button instead of passing in text or props to the kit itself. In this example the button is using the Pill kit and a `<span>` element inside the button.
@@ -0,0 +1,2 @@
1
+ <%= pb_rails("button", props: { icon: "plus", text: "Icon on Left" }) %>
2
+ <%= pb_rails("button", props: { icon: "chevron-right", icon_right: true, text: "Icon on Right" }) %>
@@ -0,0 +1,23 @@
1
+ import React from 'react'
2
+ import { Button } from '../../'
3
+
4
+ const ButtonIconOptions = (props) => (
5
+ <div>
6
+ <Button
7
+ fixedWidth
8
+ icon='plus'
9
+ text="Icon on Left"
10
+ {...props}
11
+ />
12
+ {' '}
13
+ <Button
14
+ fixedWidth
15
+ icon='chevron-right'
16
+ iconRight
17
+ text="Icon on Right"
18
+ {...props}
19
+ />
20
+ </div>
21
+ )
22
+
23
+ export default ButtonIconOptions
@@ -0,0 +1 @@
1
+ Icons can also be added to a button if needed. By default, the icon will be displayed on the left of the text. To display the icon on the right, use the optional prop of `iconRight` in react or `icon_right` in rails.
@@ -5,6 +5,7 @@ examples:
5
5
  - button_link: Button Links
6
6
  - button_loading: Button Loading
7
7
  - button_block_content: Button Block Content
8
+ - button_icon_options: Button Icon Options
8
9
  - button_accessibility: Button Accessibility Options
9
10
  - button_options: Button Additional Options
10
11
  - button_size: Button Size
@@ -15,6 +16,7 @@ examples:
15
16
  - button_link: Button Links
16
17
  - button_loading: Button Loading
17
18
  - button_block_content: Button Block Content
19
+ - button_icon_options: Button Icon Options
18
20
  - button_accessibility: Button Accessibility Options
19
21
  - button_options: Button Additional Options (onClick)
20
22
  - button_size: Button Size
@@ -3,6 +3,7 @@ export { default as ButtonFullWidth } from './_button_full_width.jsx'
3
3
  export { default as ButtonLink } from './_button_link.jsx'
4
4
  export { default as ButtonLoading } from './_button_loading.jsx'
5
5
  export { default as ButtonBlockContent } from './_button_block_content.jsx'
6
+ export { default as ButtonIconOptions } from './_button_icon_options.jsx'
6
7
  export { default as ButtonAccessibility } from './_button_accessibility.jsx'
7
8
  export { default as ButtonOptions } from './_button_options.jsx'
8
9
  export { default as ButtonSize } from './_button_size.jsx'
@@ -12,7 +12,7 @@ import Title from "../pb_title/_title";
12
12
 
13
13
  type PbDateProps = {
14
14
  alignment?: "left" | "center" | "right";
15
- aria: { [key: string]: string };
15
+ aria?: { [key: string]: string };
16
16
  className?: string;
17
17
  data?: { [key: string]: string };
18
18
  id?: string;
@@ -42,12 +42,17 @@ type DatePickerProps = {
42
42
  pickerId?: String,
43
43
  placeholder?: String,
44
44
  plugins: Boolean,
45
+ position: String,
46
+ positionElement?: HTMLElement | null,
47
+ scrollContainer?: String,
45
48
  selectionType?: "month" | "week",
46
49
  showTimezone?: Boolean,
50
+ staticPosition: Boolean,
47
51
  timeFormat?: String,
48
52
  type?: String,
49
53
  yearRange?: Array,
50
54
  }
55
+
51
56
  const DatePicker = (props: DatePickerProps) => {
52
57
  if (props.plugins) deprecatedProps('Date Picker', ['plugins'])
53
58
 
@@ -82,8 +87,12 @@ const DatePicker = (props: DatePickerProps) => {
82
87
  pickerId,
83
88
  placeholder = 'Select Date',
84
89
  plugins = false,
90
+ position,
91
+ positionElement,
92
+ scrollContainer,
85
93
  selectionType = '',
86
94
  showTimezone = false,
95
+ staticPosition = true,
87
96
  yearRange = [ 1900, 2100 ],
88
97
  } = props
89
98
 
@@ -113,10 +122,13 @@ const DatePicker = (props: DatePickerProps) => {
113
122
  onChange,
114
123
  pickerId,
115
124
  plugins,
125
+ position,
126
+ positionElement,
116
127
  selectionType,
117
128
  showTimezone,
129
+ staticPosition,
118
130
  yearRange,
119
- })
131
+ }, scrollContainer)
120
132
  })
121
133
 
122
134
  const iconWrapperClass = () => {
@@ -12,34 +12,39 @@
12
12
  .input_wrapper {
13
13
  margin-bottom: $space_sm;
14
14
  position: relative;
15
- @import "./sass_partials/calendar_input_icon";
16
- @import "./sass_partials/day_styles";
17
- @import "./sass_partials/header_styles";
18
- @import "./sass_partials/overrides";
19
15
 
20
16
  .flatpickr-wrapper {
21
17
  display: block;
22
- .text_input.flatpickr-input {
23
- text-overflow: ellipsis;
24
- padding-right: $space_xl + 10 !important;
25
- }
26
- // Calendar Shadow and Border
27
- .flatpickr-calendar {
28
- box-shadow: $shadow_deeper;
29
- border: 1px solid $border_light;
30
- }
31
- // Hide Caret
32
- .flatpickr-calendar:before,
33
- .flatpickr-calendar:after {
34
- content: none;
35
- }
36
18
  }
19
+
20
+ @import "./sass_partials/calendar_input_icon";
37
21
  }
38
22
 
39
- &:focus,:focus-within{
23
+ &:focus, :focus-within {
40
24
  div.cal_icon_wrapper, input.text_input{
41
25
  @include transition_default;
42
26
  border-color: $primary;
43
27
  }
44
28
  }
45
29
  }
30
+
31
+ .flatpickr-calendar {
32
+ @import "./sass_partials/day_styles";
33
+ @import "./sass_partials/header_styles";
34
+ @import "./sass_partials/overrides";
35
+
36
+ .text_input.flatpickr-input {
37
+ text-overflow: ellipsis;
38
+ padding-right: $space_xl + 10 !important;
39
+ }
40
+ // Calendar Shadow and Border
41
+ .flatpickr-calendar {
42
+ box-shadow: $shadow_deeper;
43
+ border: 1px solid $border_light;
44
+ }
45
+ // Hide Caret
46
+ &:before,
47
+ &:after {
48
+ content: none;
49
+ }
50
+ }
@@ -61,7 +61,7 @@
61
61
 
62
62
  <%= javascript_tag do %>
63
63
  window.addEventListener("DOMContentLoaded", () => {
64
- datePickerHelper(<%= object.date_picker_config %>)
64
+ datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
65
65
  })
66
66
  <% end %>
67
67
  <% end %>
@@ -46,11 +46,17 @@ module Playbook
46
46
  prop :plugins, type: Playbook::Props::Boolean,
47
47
  default: false,
48
48
  deprecated: true
49
+ prop :position, type: Playbook::Props::String,
50
+ default: "auto"
51
+ prop :position_element, type: Playbook::Props::String
52
+ prop :scroll_container, type: Playbook::Props::String
49
53
  prop :selection_type, type: Playbook::Props::Enum,
50
54
  values: %w[week month none],
51
55
  default: "none"
52
56
  prop :show_timezone, type: Playbook::Props::Boolean,
53
57
  default: false
58
+ prop :static_position, type: Playbook::Props::Boolean,
59
+ default: true
54
60
  prop :required, type: Playbook::Props::Boolean,
55
61
  default: false
56
62
  prop :year_range, type: Playbook::Props::Array,
@@ -76,9 +82,12 @@ module Playbook
76
82
  mode: mode,
77
83
  pickerId: picker_id,
78
84
  plugins: plugins,
85
+ position: position,
86
+ positionElement: position_element,
79
87
  required: required,
80
88
  selectionType: selection_type,
81
89
  showTimezone: show_timezone,
90
+ staticPosition: static_position,
82
91
  yearRange: year_range,
83
92
  }.to_json.html_safe
84
93
  end
@@ -3,7 +3,11 @@ import monthSelectPlugin from 'flatpickr/dist/plugins/monthSelect'
3
3
  import weekSelect from "flatpickr/dist/plugins/weekSelect/weekSelect"
4
4
  import timeSelectPlugin from './plugins/timeSelect'
5
5
 
6
- const datePickerHelper = (config) => {
6
+ const getPositionElement = (element) => {
7
+ return (typeof element === 'string') ? document.querySelectorAll(element)[0] : element
8
+ }
9
+
10
+ const datePickerHelper = (config, scrollContainer) => {
7
11
  const {
8
12
  allowInput,
9
13
  defaultDate,
@@ -18,9 +22,12 @@ const datePickerHelper = (config) => {
18
22
  onChange = () => {},
19
23
  pickerId,
20
24
  plugins,
25
+ position = "auto",
26
+ positionElement,
21
27
  required,
22
28
  selectionType,
23
29
  showTimezone,
30
+ staticPosition = true,
24
31
  timeCaption = 'Select Time',
25
32
  timeFormat = 'at h:i K',
26
33
  yearRange,
@@ -117,19 +124,23 @@ const datePickerHelper = (config) => {
117
124
  onOpen: [() => {
118
125
  calendarResizer()
119
126
  window.addEventListener('resize', calendarResizer)
127
+ if (!staticPosition && scrollContainer) attachToScroll(scrollContainer)
120
128
  }],
121
129
  onClose: [() => {
122
130
  window.removeEventListener('resize', calendarResizer)
131
+ if (!staticPosition && scrollContainer) detachFromScroll(scrollContainer)
123
132
  }],
124
133
  onChange: [(selectedDates, dateStr) => {
125
- onChange(dateStr, selectedDates)
134
+ onChange(dateStr, selectedDates)
126
135
  }],
127
136
  onYearChange: [() => {
128
137
  yearChangeHook()
129
138
  }],
130
139
  plugins: setPlugins(),
140
+ position,
141
+ positionElement: getPositionElement(positionElement),
131
142
  prevArrow: '<i class="far fa-angle-left"></i>',
132
- static: true,
143
+ static: staticPosition,
133
144
  })
134
145
 
135
146
  // ===========================================================
@@ -140,6 +151,17 @@ const datePickerHelper = (config) => {
140
151
  const picker = document.querySelector(`#${pickerId}`)._flatpickr
141
152
  picker.innerContainer.parentElement.id = `cal-${pickerId}`
142
153
 
154
+ // Attach / detach to / from scroll events
155
+ const scrollEvent = () => {
156
+ picker._positionCalendar()
157
+ }
158
+ function attachToScroll(scrollParent) {
159
+ document.querySelectorAll(scrollParent)[0]?.addEventListener("scroll", scrollEvent, { passive: true })
160
+ }
161
+ function detachFromScroll(scrollParent = document.body) {
162
+ document.querySelectorAll(scrollParent)[0]?.removeEventListener("scroll", scrollEvent)
163
+ }
164
+
143
165
  // replace year selector with dropdown
144
166
  picker.yearElements[0].parentElement.innerHTML = `<select class="numInput cur-year" type="number" tabIndex="-1" aria-label="Year" id="year-${pickerId}"></select>`
145
167
 
@@ -0,0 +1,44 @@
1
+ <%= pb_rails("flex") do %>
2
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "50%"}) do %>
3
+ <%= pb_rails("date_picker", props: {
4
+ label: "Datepicker (opens on the right)",
5
+ picker_id: "date-picker-positions1",
6
+ position: "auto right",
7
+ scroll_container: ".pb--page--content--main",
8
+ static_position: false
9
+ }) %>
10
+ <% end %>
11
+ <% end %>
12
+ <%= pb_rails("flex") do %>
13
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "50%"}) do %>
14
+ <%= pb_rails("date_picker", props: {
15
+ label: "Datepicker (opens on the left)",
16
+ picker_id: "date-picker-positions2",
17
+ position: "auto left",
18
+ scroll_container: ".pb--page--content--main",
19
+ static_position: false
20
+ }) %>
21
+ <% end %>
22
+ <% end %>
23
+ <%= pb_rails("flex") do %>
24
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "50%"}) do %>
25
+ <%= pb_rails("date_picker", props: {
26
+ label: "Datepicker (opens above on the left)",
27
+ picker_id: "date-picker-positions3",
28
+ position: "above left",
29
+ scroll_container: ".pb--page--content--main",
30
+ static_position: false
31
+ }) %>
32
+ <% end %>
33
+ <% end %>
34
+ <%= pb_rails("flex") do %>
35
+ <%= pb_rails("flex/flex_item", props: {fixed_size: "50%"}) do %>
36
+ <%= pb_rails("date_picker", props: {
37
+ label: "Datepicker (opens below on the right)",
38
+ picker_id: "date-picker-positions4",
39
+ position: "below right",
40
+ scroll_container: ".pb--page--content--main",
41
+ static_position: false
42
+ }) %>
43
+ <% end %>
44
+ <% end %>
@@ -0,0 +1,60 @@
1
+ import React from 'react'
2
+
3
+ import Flex from '../../pb_flex/_flex'
4
+ import FlexItem from '../../pb_flex/_flex_item'
5
+ import DatePicker from '../_date_picker'
6
+
7
+ const DatePickerPositions = (props) => (
8
+ <React.Fragment>
9
+ <Flex>
10
+ <FlexItem fixedSize="50%">
11
+ <DatePicker
12
+ label="Datepicker (opens on the right)"
13
+ pickerId="date-picker-positions1"
14
+ position="auto right"
15
+ scrollContainer=".pb--page--content--main"
16
+ staticPosition={false}
17
+ {...props}
18
+ />
19
+ </FlexItem>
20
+ </Flex>
21
+ <Flex>
22
+ <FlexItem fixedSize="50%">
23
+ <DatePicker
24
+ label="Datepicker (opens on the left)"
25
+ pickerId="date-picker-positions2"
26
+ position="auto left"
27
+ scrollContainer=".pb--page--content--main"
28
+ staticPosition={false}
29
+ {...props}
30
+ />
31
+ </FlexItem>
32
+ </Flex>
33
+ <Flex>
34
+ <FlexItem fixedSize="50%">
35
+ <DatePicker
36
+ label="Datepicker (opens above on the left)"
37
+ pickerId="date-picker-positions3"
38
+ position="above left"
39
+ scrollContainer=".pb--page--content--main"
40
+ staticPosition={false}
41
+ {...props}
42
+ />
43
+ </FlexItem>
44
+ </Flex>
45
+ <Flex>
46
+ <FlexItem fixedSize="50%">
47
+ <DatePicker
48
+ label="Datepicker (opens below on the right)"
49
+ pickerId="date-picker-positions4"
50
+ position="below right"
51
+ scrollContainer=".pb--page--content--main"
52
+ staticPosition={false}
53
+ {...props}
54
+ />
55
+ </FlexItem>
56
+ </Flex>
57
+ </React.Fragment>
58
+ )
59
+
60
+ export default DatePickerPositions
@@ -0,0 +1,9 @@
1
+ Datepicker supports `position` options from [Flatpickr Options Documentation](https://flatpickr.js.org/options/). There are multiple positioning options to choose from.
2
+
3
+ **Note:** In order for the above prop to work properly, you must also send `staticPosition={false}` to your Datepicker kit instance.
4
+
5
+ #### Affix Datepicker Upon Scrolling
6
+
7
+ Upon adding `static={false}` to the date picker, you will notice that the date picker detaches from the input field while scrolling. This is a known Flatpickr nuance. By adding the `scrollContainer` prop, you can tell the date picker which DOM container it should watch for scroll events. In this example, you can see that `scrollContainer=".pb--page--content--main"` is being passed in order to keep the date picker correctly positioned on page scroll.
8
+
9
+ **Useage:** `scrollContainer: .validQuerySelectorHere`