playbook_ui 11.4.0 → 11.5.0.pre.alpha.datepicker1

Sign up to get free protection for your applications and to get access to all the features.
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`