playbook_ui 12.25.0 → 12.26.0.pre.alpha.PLAY603datepickerquickpickinputpresetdropdown794

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/index.js +1 -0
  4. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_swift.md +82 -1
  5. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +26 -0
  6. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +102 -95
  7. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +30 -2
  8. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +11 -4
  9. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +44 -1
  10. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +38 -4
  11. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.html.erb +8 -0
  12. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick.jsx +18 -0
  13. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  14. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +2 -1
  15. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +168 -0
  16. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_calendar_input_icon.scss +3 -2
  17. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_quick_pick_styles.scss +75 -0
  18. data/app/pb_kits/playbook/pb_detail/_detail.scss +44 -0
  19. data/app/pb_kits/playbook/pb_detail/_detail.tsx +55 -0
  20. data/app/pb_kits/playbook/pb_detail/_detail_mixins.scss +29 -0
  21. data/app/pb_kits/playbook/pb_detail/detail.html.erb +7 -0
  22. data/app/pb_kits/playbook/pb_detail/detail.rb +31 -0
  23. data/app/pb_kits/playbook/pb_detail/detail.test.jsx +46 -0
  24. data/app/pb_kits/playbook/pb_detail/docs/_description.md +1 -0
  25. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.html.erb +34 -0
  26. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.jsx +49 -0
  27. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.md +1 -0
  28. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.html.erb +24 -0
  29. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.jsx +38 -0
  30. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.md +6 -0
  31. data/app/pb_kits/playbook/pb_detail/docs/_detail_default.html.erb +3 -0
  32. data/app/pb_kits/playbook/pb_detail/docs/_detail_default.jsx +13 -0
  33. data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.html.erb +22 -0
  34. data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.jsx +32 -0
  35. data/app/pb_kits/playbook/pb_detail/docs/example.yml +11 -0
  36. data/app/pb_kits/playbook/pb_detail/docs/index.js +4 -0
  37. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +14 -13
  38. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +3 -2
  39. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +212 -0
  40. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +58 -98
  41. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +340 -86
  42. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.md +1 -1
  43. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +1 -0
  44. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +1 -1
  45. data/app/pb_kits/playbook/pb_nav/_item.tsx +1 -1
  46. data/app/pb_kits/playbook/pb_nav/_subtle_mixin.scss +1 -1
  47. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  48. data/dist/menu.yml +1 -0
  49. data/dist/playbook-rails.js +279 -7
  50. data/lib/playbook/version.rb +2 -2
  51. metadata +31 -9
  52. data/app/pb_kits/playbook/pb_multi_level_select/_multi_select_helper.tsx +0 -31
  53. data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +0 -87
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c0e138725ae04e9e300cea544d787219534b5da851b11840c536622e6a94c6c
4
- data.tar.gz: '067282a70e9f2e6277f85bb62ca4eb398a6f3e001f6acfcd36e445bbd141b322'
3
+ metadata.gz: 360413b8af66e57c96b50f7a3d42e090570ce350ffaa9ec7d316ce5f3cffd9df
4
+ data.tar.gz: d96327fc8f503da031ffb1cfe9d5dfde31551860650d0ae01a0cc5e249fa5114
5
5
  SHA512:
6
- metadata.gz: d034799f6965ecd6d82823ac00d5392c5427ff175b322b0a33fbed74fbebfa558207a4c6372b8aca269c3d0e14a2acf4e0edc0cfcaddf8ebc66325be62614325
7
- data.tar.gz: 0ebf023711e4150a1a610f5eee2ae3d9a5c3499c4f15222fe84a94a9e8aaf53c2501889b655840241c1f4a94111d72ed8216a821be22271049f9155b500466bf
6
+ metadata.gz: 5350397053b9dba7747150cf2f3a85d074456ecd0afbc70ebe68175c53c7840983427d4c38daf97423e3d09136ce0db11ad9445e38dbd49dcd46f4060f59cb4a
7
+ data.tar.gz: 4422d0c952be46f567154bcd58037fb66763aa44cddfc47179de84b62d335083b055ac0edf97b616674e7b5861ff2d6f18b70ca1b41cc12e2ecf22df1be1a89a
@@ -5,6 +5,7 @@
5
5
  @import 'pb_button_toolbar/button_toolbar';
6
6
  @import 'pb_caption/caption';
7
7
  @import 'pb_card/card';
8
+ @import 'pb_detail/detail';
8
9
  @import 'pb_title/title';
9
10
  @import 'pb_avatar/avatar';
10
11
  @import 'pb_avatar_action_button/avatar_action_button';
@@ -31,6 +31,7 @@ export { default as DateStacked } from './pb_date_stacked/_date_stacked'
31
31
  export { default as DateTime } from './pb_date_time/_date_time'
32
32
  export { default as DateTimeStacked } from './pb_date_time_stacked/_date_time_stacked'
33
33
  export { default as DateYearStacked } from './pb_date_year_stacked/_date_year_stacked'
34
+ export { default as Detail} from './pb_detail/_detail'
34
35
  export { default as Dialog } from './pb_dialog/_dialog'
35
36
  export { default as DistributionBar } from './pb_distribution_bar/_distribution_bar'
36
37
  export { default as FileUpload } from './pb_file_upload/_file_upload'
@@ -1 +1,82 @@
1
- ![image for avatar](https://images.unsplash.com/photo-1684237276530-a562fa8338b1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=580&q=80)
1
+ In the world of design, consistency is key. Whether you're designing a website, app, or product, having a consistent visual language can make all the difference. That's where design systems come in.
2
+
3
+ A design system is a collection of reusable components, guidelines, and assets that help ensure consistency across all of your design work. It's a way to standardize your design language, making it easier for your team to work together and for your users to navigate your products.
4
+
5
+ In this article, we'll explore the various elements of a design system and how they can be used to create a cohesive and effective design language.
6
+
7
+ ### Headings
8
+ Headings are an essential component of any design system. They help organize content, provide visual hierarchy, and make it easier for users to scan and find what they're looking for. A good design system will have headings of various sizes, ranging from H1 (the largest) to H6 (the smallest). Here's an example:
9
+
10
+ # H1: Main Title Headings
11
+ ## H2: Headings
12
+ ### H3: Subheadings
13
+ #### H4: Sub-Subheadings
14
+
15
+ ![image for avatar](https://images.unsplash.com/photo-1684237276530-a562fa8338b1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=580&q=80)
16
+
17
+ ### Lists
18
+ Lists are another important component of a design system. They help organize content into easily digestible chunks, making it easier for users to read and understand. There are two types of lists: ordered and unordered.
19
+
20
+ Ordered lists are numbered, and each item is listed in a specific order. For example:
21
+
22
+ 1. Headings
23
+ 2. Lists
24
+ 3. Blockquotes
25
+ 4. Links
26
+ 5. Bold
27
+ 6. Underline
28
+ 7. Code Blocks
29
+ 8. Inline Code
30
+ 9. Example Tables
31
+ 10. Horizontal Rules
32
+
33
+ Unordered lists, on the other hand, use bullet points to separate each item. For example:
34
+
35
+ * Headings
36
+ * Lists
37
+ * Blockquotes
38
+ * Links
39
+ * Bold
40
+ * Underline
41
+ * Code Blocks
42
+ * Inline Code
43
+ * Example Tables
44
+ * Horizontal Rules
45
+
46
+ ### Blockquotes
47
+ Blockquotes are used to highlight a particular section of text or quote. They’re often used to emphasize an important point or to provide context. Here’s an example:
48
+
49
+ > “Design systems are a collection of reusable components, guidelines, and assets that help ensure consistency across all of your design work.” - ChatGPT
50
+
51
+
52
+ ### Links
53
+ Links are an important part of any design system. They allow users to navigate between different pages and sections of your product. When using links in your design system, it’s important to make sure they’re consistent in color, size, and style. Here’s an example:
54
+ Click here to learn more about design systems.
55
+
56
+ ### Bold, Underline, & Italics
57
+ **Bold** and _underline_ are used to *highlight specific words* or phrases within ~~a block of~~ text. They help draw the user’s attention to important information. Here’s an example: *Design systems are* a collection of **reusable components**, **guidelines**, and **assets** that help ensure _consistency across all of your design work_.
58
+
59
+ ### Code Blocks and Inline Code
60
+ Code blocks and `inline code` are used to display and highlight code within a block of text. This is especially useful for developers who need to reference code snippets in their work.
61
+
62
+ Here’s an example:
63
+
64
+ ```js
65
+ function greet() {
66
+ console.log(“Hello, world!”);
67
+ }
68
+ ```
69
+
70
+ ### Example Tables
71
+ Example tables are used to display data in a clear and organized way. They help users compare and analyze information quickly. Here’s an example:
72
+
73
+ | Tables | Are | Cool |
74
+ |----------|:-------------:|------:|
75
+ | col 1 is | left-aligned | $1600 |
76
+ | col 2 is | centered | $12 |
77
+ | col 3 is | right-aligned | $1 |
78
+
79
+ ---
80
+
81
+ ### Horizontal Rules
82
+ Horizontal rules are used to separate sections of content visually. They help break up long blocks of text and make it easier for users
@@ -6,6 +6,7 @@
6
6
  @import "./sass_partials/month_and_year_styles";
7
7
  @import "./sass_partials/time_selection_styles";
8
8
  @import "./sass_partials/input_styles";
9
+ @import "./sass_partials/quick_pick_styles";
9
10
 
10
11
  [class^=pb_date_picker_kit] {
11
12
  .input_wrapper {
@@ -26,7 +27,32 @@
26
27
  @include transition_default;
27
28
  border-color: $primary;
28
29
  }
30
+ .add-on-card {
31
+ border-color: $primary;
32
+ }
33
+ }
34
+
35
+ @media (hover: hover) {
36
+ &:hover {
37
+ .add-on-card {
38
+ cursor: pointer;
39
+ background-color: rgba($focus_input_light,$opacity_5);
40
+ }
41
+ }
42
+ }
43
+ .text_input_wrapper_add_on .add-on-icon {
44
+ color: $text_lt_light
29
45
  }
46
+
47
+ .text_input_wrapper_add_on .add-on-right .text_input{
48
+ cursor: pointer;
49
+ }
50
+
51
+ }
52
+
53
+
54
+ .pb_popover_reference_wrapper {
55
+ display: unset !important
30
56
  }
31
57
 
32
58
  .flatpickr-calendar {
@@ -30,7 +30,7 @@ type DatePickerProps = {
30
30
  inputAria?: { [key: string]: string },
31
31
  inputData?: { [key: string]: string },
32
32
  inputOnChange?: (e: React.FormEvent<HTMLInputElement>) => void,
33
- inputValue?: any,
33
+ inputValue?: string,
34
34
  label?: string,
35
35
  maxDate: string,
36
36
  minDate: string,
@@ -39,9 +39,10 @@ type DatePickerProps = {
39
39
  placeholder?: string,
40
40
  positionElement?: HTMLElement | null,
41
41
  scrollContainer?: string,
42
- selectionType?: "month" | "week",
42
+ selectionType?: "month" | "week"| "quickpick",
43
43
  showTimezone?: boolean,
44
44
  staticPosition: boolean,
45
+ thisRangesEndToday?: boolean,
45
46
  timeFormat?: string,
46
47
  type?: string,
47
48
  yearRange?: number[],
@@ -88,6 +89,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
88
89
  selectionType = '',
89
90
  showTimezone = false,
90
91
  staticPosition = true,
92
+ thisRangesEndToday = false,
91
93
  yearRange = [1900, 2100],
92
94
  } = props
93
95
 
@@ -96,46 +98,47 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
96
98
  const inputAriaProps = buildAriaProps(inputAria)
97
99
  const inputDataProps = buildDataProps(inputData)
98
100
 
101
+ useEffect(() => {
102
+ datePickerHelper({
103
+ allowInput,
104
+ defaultDate,
105
+ disableDate,
106
+ disableRange,
107
+ disableWeekdays,
108
+ enableTime,
109
+ format,
110
+ hideIcon,
111
+ inLine,
112
+ maxDate,
113
+ minDate,
114
+ mode,
115
+ onChange,
116
+ onClose,
117
+ pickerId,
118
+ plugins,
119
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
120
+ // @ts-ignore
121
+ position,
122
+ positionElement,
123
+ selectionType,
124
+ showTimezone,
125
+ staticPosition,
126
+ thisRangesEndToday,
127
+ yearRange,
128
+ required: false,
129
+ }, scrollContainer)
130
+ })
99
131
  const filteredProps = {...props}
100
132
  delete filteredProps?.position
101
133
 
102
134
  const classes = classnames(
103
135
  buildCss('pb_date_picker_kit'),
136
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
104
137
  //@ts-ignore
105
138
  globalProps(filteredProps),
106
139
  error ? 'error' : null,
107
140
  className
108
141
  )
109
-
110
- useEffect(() => {
111
- datePickerHelper({
112
- allowInput,
113
- defaultDate,
114
- disableDate,
115
- disableRange,
116
- disableWeekdays,
117
- enableTime,
118
- format,
119
- hideIcon,
120
- inLine,
121
- maxDate,
122
- minDate,
123
- mode,
124
- onChange,
125
- onClose,
126
- pickerId,
127
- plugins,
128
- // @ts-ignore
129
- position,
130
- positionElement,
131
- selectionType,
132
- showTimezone,
133
- staticPosition,
134
- yearRange,
135
- required: false,
136
- }, scrollContainer)
137
- })
138
-
139
142
  const iconWrapperClass = () => {
140
143
  let base = 'cal_icon_wrapper'
141
144
  if (dark) {
@@ -150,80 +153,84 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
150
153
  return base
151
154
  }
152
155
 
156
+
153
157
  return (
154
158
  <div
155
- {...ariaProps}
156
- {...dataProps}
157
- className={classes}
158
- id={id}
159
+ {...ariaProps}
160
+ {...dataProps}
161
+ className={classes}
162
+ id={id}
159
163
  >
160
164
  <div
161
- {...inputAriaProps}
162
- {...inputDataProps}
163
- className="input_wrapper">
165
+ {...inputAriaProps}
166
+ {...inputDataProps}
167
+ className="input_wrapper"
168
+ >
164
169
 
165
170
  <Caption
166
- className="pb_date_picker_kit_label"
167
- text={hideLabel ? null : label}
171
+ className="pb_date_picker_kit_label"
172
+ text={hideLabel ? null : label}
168
173
  />
169
-
170
- <div className="date_picker_input_wrapper">
171
- <input
172
- autoComplete="off"
173
- className="date_picker_input"
174
- disabled={disableInput}
175
- id={pickerId}
176
- name={name}
177
- onChange={inputOnChange}
178
- placeholder={placeholder}
179
- value={inputValue}
180
- />
181
-
182
- {error && <Body
183
- status="negative"
184
- text={error}
185
- variant={null}
186
- />
187
- }
188
- </div>
189
-
190
- {!hideIcon &&
191
- <div
192
- className={iconWrapperClass()}
193
- id={`cal-icon-${pickerId}`}
194
- >
195
- <Icon
196
- className="cal_icon"
197
- icon="calendar-alt"
198
- />
199
- </div>
200
- }
201
-
202
- {hideIcon && inLine ?
203
- <div>
204
- <div
205
- className={iconWrapperClass()}
206
- id={`${pickerId}-icon-plus`}
207
- >
208
- <Icon
209
- className="date-picker-plus-icon"
210
- icon="plus"
211
- />
212
- </div>
213
- <div
214
- className={iconWrapperClass()}
215
- id={`${pickerId}-angle-down`}
216
- >
217
- <Icon
218
- className="angle_down_icon"
219
- icon="angle-down"
174
+ <>
175
+ <div className="date_picker_input_wrapper">
176
+ <input
177
+ autoComplete="off"
178
+ className="date_picker_input"
179
+ disabled={disableInput}
180
+ id={pickerId}
181
+ name={name}
182
+ onChange={inputOnChange}
183
+ placeholder={placeholder}
184
+ value={inputValue}
220
185
  />
186
+
187
+ {error &&
188
+ <Body
189
+ status="negative"
190
+ text={error}
191
+ variant={null}
192
+ />
193
+ }
221
194
  </div>
222
- </div>
223
- : null}
195
+
196
+ {!hideIcon &&
197
+ <div
198
+ className={iconWrapperClass()}
199
+ id={`cal-icon-${pickerId}`}
200
+ >
201
+ <Icon
202
+ className="cal_icon"
203
+ icon="calendar-alt"
204
+ />
205
+ </div>
206
+ }
207
+
208
+ {hideIcon && inLine ?
209
+ <div>
210
+ <div
211
+ className={iconWrapperClass()}
212
+ id={`${pickerId}-icon-plus`}
213
+ >
214
+ <Icon
215
+ className="date-picker-plus-icon"
216
+ icon="plus"
217
+ />
218
+ </div>
219
+ <div
220
+ className={iconWrapperClass()}
221
+ id={`${pickerId}-angle-down`}
222
+ >
223
+ <Icon
224
+ className="angle_down_icon"
225
+ icon="angle-down"
226
+ />
227
+ </div>
228
+ </div>
229
+ : null
230
+ }
231
+ </>
224
232
  </div>
225
233
  </div>
226
234
  )
227
235
  }
228
-
229
236
  export default DatePicker
@@ -20,6 +20,16 @@
20
20
  placeholder: object.placeholder,
21
21
  required: object.required,
22
22
  }) %>
23
+ <% if object.selection_type == "quickpick" %>
24
+ <%= pb_rails("text_input", props: {
25
+ id: "#{object.start_date}-#{object.picker_id}",
26
+ name: object.start_date,
27
+ }) %>
28
+ <%= pb_rails("text_input", props: {
29
+ id: "#{object.end_date}-#{object.picker_id}",
30
+ name: object.end_date,
31
+ }) %>
32
+ <% end %>
23
33
  <% end %>
24
34
  <% if !object.hide_icon %>
25
35
  <div
@@ -60,8 +70,26 @@
60
70
  </div>
61
71
 
62
72
  <%= javascript_tag do %>
73
+ if (<%= object.selection_type == "quickpick" %>) {
74
+ const startDate = document.getElementById("<%= object.start_date %>-<%= object.picker_id %>")
75
+ if (startDate) startDate.style.display = "none"
76
+
77
+ const endDate = document.getElementById("<%= object.end_date %>-<%= object.picker_id %>")
78
+ if (endDate) endDate.style.display = "none"
79
+ }
80
+
63
81
  window.addEventListener("DOMContentLoaded", () => {
64
- datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
82
+ datePickerHelper(<%= object.date_picker_config %>, "<%= object.scroll_container %>")
83
+
84
+ if (<%= object.selection_type == "quickpick" %>) {
85
+ document.getElementById("<%= object.picker_id %>").addEventListener("change", ({ target }) => {
86
+ const startDate = document.getElementById("<%= object.start_date %>-<%= object.picker_id %>")
87
+ const endDate = document.getElementById("<%= object.end_date %>-<%= object.picker_id %>")
88
+ const splittedValue = target.value.split(" → ")
89
+ startDate.value = splittedValue[0]
90
+ endDate.value = splittedValue[1] ? splittedValue[1] : splittedValue[0]
91
+ })
92
+ }
65
93
  })
66
94
  <% end %>
67
- <% end %>
95
+ <% end %>
@@ -19,6 +19,8 @@ module Playbook
19
19
  default: []
20
20
  prop :enable_time, type: Playbook::Props::Boolean,
21
21
  default: false
22
+ prop :end_date, type: Playbook::Props::String,
23
+ default: "endDate"
22
24
  prop :error, type: Playbook::Props::String
23
25
  prop :format, type: Playbook::Props::String,
24
26
  default: "m/d/Y"
@@ -43,20 +45,24 @@ module Playbook
43
45
  required: true
44
46
  prop :placeholder, type: Playbook::Props::String,
45
47
  default: "Select Date"
46
- prop :plugins, type: Playbook::Props::Boolean,
47
- default: false,
48
- deprecated: true
48
+ prop :plugins, type: Playbook::Props::Boolean,
49
+ default: false,
50
+ deprecated: true
49
51
  prop :position, type: Playbook::Props::String,
50
52
  default: "auto"
51
53
  prop :position_element, type: Playbook::Props::String
52
54
  prop :scroll_container, type: Playbook::Props::String
53
55
  prop :selection_type, type: Playbook::Props::Enum,
54
- values: %w[week month none],
56
+ values: %w[week month quickpick none],
55
57
  default: "none"
56
58
  prop :show_timezone, type: Playbook::Props::Boolean,
57
59
  default: false
60
+ prop :start_date, type: Playbook::Props::String,
61
+ default: "startDate"
58
62
  prop :static_position, type: Playbook::Props::Boolean,
59
63
  default: true
64
+ prop :this_ranges_end_today, type: Playbook::Props::Boolean,
65
+ default: false
60
66
  prop :required, type: Playbook::Props::Boolean,
61
67
  default: false
62
68
  prop :year_range, type: Playbook::Props::Array,
@@ -88,6 +94,7 @@ module Playbook
88
94
  selectionType: selection_type,
89
95
  showTimezone: show_timezone,
90
96
  staticPosition: static_position,
97
+ thisRangesEndToday: this_ranges_end_today,
91
98
  yearRange: year_range,
92
99
  }.to_json.html_safe
93
100
  end
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable no-console */
2
2
  import React from 'react'
3
+ import moment from 'moment'
3
4
  import { fireEvent, render, screen, waitFor, within } from '../utilities/test-utils'
4
5
 
5
6
  import DatePicker from './_date_picker'
@@ -10,7 +11,6 @@ import { getTimezoneText } from './plugins/timeSelect'
10
11
  jest.setSystemTime(new Date('01/01/2020'));
11
12
  const DEFAULT_DATE = new Date()
12
13
 
13
-
14
14
  describe('DatePicker Kit', () => {
15
15
  beforeEach(() => {
16
16
  jest.spyOn(console, 'error').mockImplementation(() => { });
@@ -158,4 +158,47 @@ describe('DatePicker Kit', () => {
158
158
  expect(input).toHaveValue('01/01/2020 at 12:00 PM')
159
159
  })
160
160
  })
161
+ test('shows DatePicker QuickPick dropdown and adds correct date to input', async () => {
162
+ const testId = 'datepicker-quick-pick'
163
+ render(
164
+ <DatePicker
165
+ allowInput
166
+ data={{ testid: testId }}
167
+ mode="range"
168
+ pickerId="date-picker-quick-pick"
169
+ placeholder="mm/dd/yyyy → mm/dd/yyyy"
170
+ selectionType="quickpick"
171
+ />
172
+ )
173
+
174
+ const kit = screen.getByTestId(testId)
175
+ const input = within(kit).getByPlaceholderText('mm/dd/yyyy → mm/dd/yyyy')
176
+
177
+ fireEvent(
178
+ input,
179
+ new MouseEvent('click', {
180
+ bubbles: true,
181
+ cancelable: true,
182
+ }),
183
+ )
184
+ const today = within(kit).getByText('Today')
185
+ const thisYear = within(kit).getByText('This year')
186
+ await waitFor(() => {
187
+ expect(today).toBeInTheDocument()
188
+ expect(thisYear).toBeInTheDocument()
189
+ })
190
+
191
+ fireEvent(
192
+ thisYear,
193
+ new MouseEvent('click', {
194
+ bubbles: true,
195
+ cancelable: true,
196
+ }),
197
+ )
198
+
199
+ await waitFor(() => {
200
+ expect(input).toHaveValue(moment().startOf('year').format('MM/DD/YYYY') + " → " + moment().format('MM/DD/YYYY'))
201
+ })
202
+
203
+ })
161
204
  })
@@ -3,6 +3,7 @@ import { BaseOptions } from 'flatpickr/dist/types/options'
3
3
  import monthSelectPlugin from 'flatpickr/dist/plugins/monthSelect'
4
4
  import weekSelect from "flatpickr/dist/plugins/weekSelect/weekSelect"
5
5
  import timeSelectPlugin from './plugins/timeSelect'
6
+ import quickPickPlugin from './plugins/quickPick'
6
7
 
7
8
  const getPositionElement = (element: string | Element) => {
8
9
  return (typeof element === 'string') ? document.querySelectorAll(element)[0] : element
@@ -19,10 +20,11 @@ type DatePickerConfig = {
19
20
  hideIcon?: boolean;
20
21
  inLine?: boolean,
21
22
  onChange: (dateStr: string, selectedDates: Date[]) => void,
23
+ selectionType?: "month" | "week" | "quickpick" | "",
22
24
  onClose: (dateStr: Date[] | string, selectedDates: Date[] | string) => void,
23
- selectionType?: "month" | "week" | "",
24
25
  showTimezone?: boolean,
25
26
  staticPosition: boolean,
27
+ thisRangesEndToday?: boolean,
26
28
  timeCaption?: string,
27
29
  timeFormat?: string,
28
30
  yearRange: number[]
@@ -51,6 +53,7 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
51
53
  selectionType,
52
54
  showTimezone,
53
55
  staticPosition = true,
56
+ thisRangesEndToday = false,
54
57
  timeCaption = 'Select Time',
55
58
  timeFormat = 'at h:i K',
56
59
  yearRange,
@@ -89,19 +92,24 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
89
92
  }
90
93
  }
91
94
 
92
- const setPlugins = () => {
93
- let pluginList = []
95
+ const setPlugins = (thisRangesEndToday: boolean) => {
96
+ const pluginList = []
94
97
 
95
98
  // month and week selection
96
99
  if (selectionType === "month" || plugins.length > 0) {
97
100
  pluginList.push(monthSelectPlugin({ shorthand: true, dateFormat: 'F Y', altFormat: 'F Y' }))
98
101
  } else if ( selectionType === "week") {
99
102
  pluginList.push(weekSelect())
103
+
104
+ } else if (selectionType === "quickpick") {
105
+ //------- QUICKPICK VARIANT PLUGIN -------------//
106
+ pluginList.push(quickPickPlugin(thisRangesEndToday))
100
107
  }
101
108
 
102
109
  // time selection
103
110
  if (enableTime) pluginList.push(timeSelectPlugin({ caption: timeCaption, showTimezone: showTimezone}))
104
111
 
112
+
105
113
  return pluginList
106
114
  }
107
115
 
@@ -144,6 +152,9 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
144
152
  },
145
153
  ] : disabledParser(),
146
154
  enableTime,
155
+ locale: {
156
+ rangeSeparator: ' → '
157
+ },
147
158
  maxDate,
148
159
  minDate,
149
160
  mode,
@@ -164,17 +175,40 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
164
175
  onYearChange: [() => {
165
176
  yearChangeHook()
166
177
  }],
167
- plugins: setPlugins(),
178
+ plugins: setPlugins(thisRangesEndToday),
168
179
  position,
169
180
  positionElement: getPositionElement(positionElement),
170
181
  prevArrow: '<i class="far fa-angle-left"></i>',
171
182
  static: staticPosition,
172
183
  })
173
184
 
185
+
174
186
  // ===========================================================
175
187
  // Additional JS Functionality |
176
188
  // ===========================================================
177
189
 
190
+ // opens flatpickr instance when calander icon is clicked so we can have a hover state on icon
191
+ // window.addEventListener("DOMContentLoaded", (event) => {
192
+ // event.preventDefault();
193
+ // function attachIconClickHandler() {
194
+ // const variantArr = document.querySelectorAll(`#cal-icon-${pickerId}`)
195
+ // if (!variantArr) {
196
+ // setTimeout(attachIconClickHandler, 100);
197
+ // return;
198
+ // }
199
+
200
+ // const instance = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
201
+ // variantArr.forEach((icon) => {
202
+ // icon.addEventListener("click", function(event) {
203
+ // event.preventDefault();
204
+ // instance.open()
205
+ // });
206
+ // })
207
+ // }
208
+
209
+ // attachIconClickHandler();
210
+ // });
211
+
178
212
  // Assign dynamically sourced flatpickr instance to variable
179
213
  const picker = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
180
214
  picker.innerContainer.parentElement.id = `cal-${pickerId}`
@@ -0,0 +1,8 @@
1
+ <%= pb_rails("date_picker", props: {
2
+ allow_input: true,
3
+ mode: "range",
4
+ picker_id: "date-picker-quick-pick",
5
+ placeholder: "mm/dd/yyyy → mm/dd/yyyy",
6
+ selection_type: "quickpick"
7
+ }) %>
8
+