playbook_ui 15.6.0.pre.alpha.PLAY2686contactkittextonly13049 → 15.6.0.pre.alpha.draggableask12898

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_card/docs/_card_header.md +1 -1
  3. data/app/pb_kits/playbook/pb_card/docs/_card_highlight.md +1 -1
  4. data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +2 -2
  5. data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleIcon.tsx +8 -10
  6. data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_icons.jsx +1 -0
  7. data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_state.jsx +3 -0
  8. data/app/pb_kits/playbook/pb_contact/_contact.tsx +24 -51
  9. data/app/pb_kits/playbook/pb_contact/contact.html.erb +19 -53
  10. data/app/pb_kits/playbook/pb_contact/contact.rb +1 -11
  11. data/app/pb_kits/playbook/pb_contact/contact.test.js +0 -76
  12. data/app/pb_kits/playbook/pb_contact/docs/example.yml +0 -2
  13. data/app/pb_kits/playbook/pb_contact/docs/index.js +0 -1
  14. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +0 -24
  15. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +3 -181
  16. data/app/pb_kits/playbook/pb_distribution_bar/docs/_distribution_bar_custom_colors.md +1 -1
  17. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +88 -91
  18. data/app/pb_kits/playbook/pb_draggable/context/types.ts +1 -1
  19. data/app/pb_kits/playbook/pb_filter/Filter/FilterBackground.tsx +3 -3
  20. data/app/pb_kits/playbook/pb_radio/docs/_radio_error.md +1 -1
  21. data/app/pb_kits/playbook/pb_select/_select.tsx +3 -8
  22. data/app/pb_kits/playbook/pb_select/docs/_select_error.md +1 -1
  23. data/app/pb_kits/playbook/pb_select/docs/example.yml +0 -2
  24. data/app/pb_kits/playbook/pb_select/docs/index.js +0 -1
  25. data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
  26. data/app/pb_kits/playbook/pb_select/select.rb +1 -3
  27. data/app/pb_kits/playbook/pb_select/select.test.js +0 -23
  28. data/app/pb_kits/playbook/pb_table/_table.tsx +33 -187
  29. data/app/pb_kits/playbook/pb_table/docs/example.yml +0 -4
  30. data/app/pb_kits/playbook/pb_table/docs/index.js +0 -2
  31. data/app/pb_kits/playbook/pb_table/table.html.erb +12 -68
  32. data/app/pb_kits/playbook/pb_table/table.rb +3 -22
  33. data/app/pb_kits/playbook/pb_table/table.test.js +0 -143
  34. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.md +1 -1
  35. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.md +1 -1
  36. data/app/pb_kits/playbook/pb_timeline/_item.tsx +0 -3
  37. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_date.md +1 -1
  38. data/app/pb_kits/playbook/pb_timeline/docs/example.yml +0 -2
  39. data/app/pb_kits/playbook/pb_timeline/docs/index.js +0 -1
  40. data/app/pb_kits/playbook/pb_timeline/item.html.erb +1 -1
  41. data/app/pb_kits/playbook/pb_timeline/item.rb +0 -2
  42. data/app/pb_kits/playbook/pb_timeline/label.html.erb +1 -2
  43. data/app/pb_kits/playbook/pb_timeline/label.rb +0 -2
  44. data/app/pb_kits/playbook/pb_timeline/subcomponents/Label.tsx +0 -3
  45. data/app/pb_kits/playbook/pb_timeline/timeline.test.js +0 -51
  46. data/app/pb_kits/playbook/tokens/_colors.scss +1 -2
  47. data/dist/chunks/_typeahead-319r1pyq.js +6 -0
  48. data/dist/chunks/lib-CgpqUb6l.js +29 -0
  49. data/dist/chunks/vendor.js +3 -3
  50. data/dist/playbook-rails-react-bindings.js +1 -1
  51. data/dist/playbook-rails.js +1 -1
  52. data/dist/playbook.css +1 -1
  53. data/lib/playbook/forms/builder/collection_select_field.rb +1 -9
  54. data/lib/playbook/forms/builder/select_field.rb +1 -9
  55. data/lib/playbook/forms/builder/time_zone_select_field.rb +1 -9
  56. data/lib/playbook/pb_kit_helper.rb +0 -35
  57. data/lib/playbook/version.rb +1 -1
  58. metadata +4 -23
  59. data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled.html.erb +0 -33
  60. data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled.jsx +0 -46
  61. data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled_rails.md +0 -2
  62. data/app/pb_kits/playbook/pb_contact/docs/_contact_unstyled_react.md +0 -2
  63. data/app/pb_kits/playbook/pb_select/docs/_select_input_options.html.erb +0 -16
  64. data/app/pb_kits/playbook/pb_select/docs/_select_input_options.jsx +0 -30
  65. data/app/pb_kits/playbook/pb_select/docs/_select_input_options.md +0 -1
  66. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.jsx +0 -134
  67. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.md +0 -34
  68. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.html.erb +0 -101
  69. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.md +0 -33
  70. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.jsx +0 -180
  71. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.md +0 -3
  72. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.html.erb +0 -122
  73. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.md +0 -3
  74. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.html.erb +0 -60
  75. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.jsx +0 -118
  76. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.md +0 -1
  77. data/app/pb_kits/playbook/utilities/deprecated.ts +0 -73
  78. data/dist/chunks/_typeahead-CHwm9MTE.js +0 -6
  79. data/dist/chunks/lib-Cugvy62C.js +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a30081dbc5a14dfeec79933dd490fe553502036499c58f64de1d148a0fba985e
4
- data.tar.gz: b6cf7dd45fd95b0cc39435dd440bb3829648799a28295ca0fd5b0f7d324a07d2
3
+ metadata.gz: a1dcc4b2b7843d520c80b11f73c74e196883d2bd1a3ecf55d92c16be884d0099
4
+ data.tar.gz: f071a4758c69143994205e7f230baa51f860f304d27887211d39eb910480b080
5
5
  SHA512:
6
- metadata.gz: ae9a12d8598e97d2326f6d8b6c65950a2316e511d1e22de76709c4fb416b3f67a61e02dbc895138b64ec80c2f68bfd26be27a2e0aaa1a07f439c4be7a3e87c63
7
- data.tar.gz: 97507923ae090f97a814c18cbd242e3746f7481fd797e0f3b809ccc34c3a784644e9b5d5b5ac8c8ef407bc712f17d67f1e2c778c82c0abc1ac28aa070fa79285
6
+ metadata.gz: eab9a32c8a93c485adea409dca924d0d6947d00433ed2f2b347a820b102e71de3a015b2f00a09d11a6928eda21f68cb95131463946346ae2b86e8f941dc1cd96
7
+ data.tar.gz: 3e2dc18bf9ad106c8dd35ce73ef90498e79eecfc1de411c4889c235d80e5aa0220013f49fcf12fdd9d09dd4738ba74f5410ade65eb4d913f764fc349dcce01d7
@@ -1 +1 @@
1
- Card headers pass category, product, status and background colors only. List of all category, product, status and background colors can be viewed <a href="https://playbook.powerapp.cloud/tokens/colors" target="_blank">here</a>.
1
+ Card headers pass category, product, status and background colors only. List of all category, product, status and background colors can be viewed <a href="https://playbook.powerapp.cloud/token/colors" target="_blank">here</a>.
@@ -1 +1 @@
1
- Card highlight can pass status, product, and category colors. List of all colors can be viewed <a href="https://playbook.powerapp.cloud/tokens/colors" target="_blank">here</a>.
1
+ Card highlight can pass status, product, and category colors. List of all colors can be viewed <a href="https://playbook.powerapp.cloud/token/colors" target="_blank">here</a>.
@@ -25,11 +25,11 @@ exports[`html structure is correct 1`] = `
25
25
  >
26
26
  <div
27
27
  class="icon_wrapper"
28
- style="vertical-align: middle;"
28
+ style="vertical-align: middle; color: rgb(193, 205, 214);"
29
29
  >
30
30
  <svg
31
31
  aria-label="chevron-down icon"
32
- class="pb_custom_icon svg-inline--fa color_text_lt_lighter svg_lg svg_fw"
32
+ class="pb_custom_icon svg-inline--fa svg_lg svg_fw"
33
33
  color="currentColor"
34
34
  fill="none"
35
35
  height="auto"
@@ -27,12 +27,12 @@ type colorMap = {
27
27
  };
28
28
 
29
29
  const colorMap = {
30
- default:"text_lt_default",
31
- light: "text_lt_light",
32
- lighter: "text_lt_lighter",
33
- link: "primary",
34
- error: "error",
35
- success: "text_dk_success_sm",
30
+ default: "#242B42",
31
+ light: "#687887",
32
+ lighter: "#C1CDD6",
33
+ link: "#0056CF",
34
+ error: "#FF2229",
35
+ success: "#00CA74",
36
36
  };
37
37
 
38
38
  const CollapsibleIcon = ({
@@ -68,10 +68,9 @@ const CollapsibleIcon = ({
68
68
  className="icon_wrapper"
69
69
  key={icon ? showIcon(icon)[0] : "chevron-down"}
70
70
  onClick={(e) => handleIconClick(e)}
71
- style={{ verticalAlign: "middle"}}
71
+ style={{ verticalAlign: "middle", color: color }}
72
72
  >
73
73
  <Icon
74
- color={color}
75
74
  icon={icon ? showIcon(icon)[0] : "chevron-down"}
76
75
  size={iconSize}
77
76
  />
@@ -81,10 +80,9 @@ const CollapsibleIcon = ({
81
80
  className="icon_wrapper"
82
81
  key={icon ? showIcon(icon)[1] : "chevron-up"}
83
82
  onClick={(e) => handleIconClick(e)}
84
- style={{ verticalAlign: "middle" }}
83
+ style={{ verticalAlign: "middle", color: color }}
85
84
  >
86
85
  <Icon
87
- color={color}
88
86
  icon={icon ? showIcon(icon)[1] : "chevron-up"}
89
87
  size={iconSize}
90
88
  />
@@ -7,6 +7,7 @@ const CollapsibleIcons = (props) => {
7
7
  <>
8
8
  <Collapsible
9
9
  icon={['plus','minus']}
10
+ iconColor='white'
10
11
  >
11
12
  <Collapsible.Main {...props}>
12
13
  <div>{'Main Section'}</div>
@@ -22,6 +22,7 @@ const CollapsibleState = (props) => {
22
22
  <Collapsible
23
23
  collapsed={isCollapsed}
24
24
  icon={["plus", "minus"]}
25
+ iconColor='white'
25
26
  padding="none"
26
27
  >
27
28
  <Collapsible.Main padding="sm"
@@ -40,6 +41,7 @@ const CollapsibleState = (props) => {
40
41
  <Collapsible
41
42
  collapsed={isCollapsed}
42
43
  icon={["plus", "minus"]}
44
+ iconColor='white'
43
45
  padding="none"
44
46
  >
45
47
  <Collapsible.Main padding="sm"
@@ -58,6 +60,7 @@ const CollapsibleState = (props) => {
58
60
  <Collapsible
59
61
  collapsed={isCollapsed}
60
62
  icon={["plus", "minus"]}
63
+ iconColor='white'
61
64
  padding="none"
62
65
  >
63
66
  <Collapsible.Main padding="sm"
@@ -61,9 +61,7 @@ type ContactProps = {
61
61
  data?: { [key: string]: string }
62
62
  dark?: boolean
63
63
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) }
64
- iconEnabled?: boolean
65
64
  id?: string
66
- unstyled?: boolean
67
65
  }
68
66
 
69
67
  const Contact = (props: ContactProps): React.ReactElement => {
@@ -76,9 +74,7 @@ const Contact = (props: ContactProps): React.ReactElement => {
76
74
  data = {},
77
75
  dark = false,
78
76
  htmlOptions = {},
79
- iconEnabled = true,
80
77
  id,
81
- unstyled = false,
82
78
  } = props
83
79
  const ariaProps = buildAriaProps(aria)
84
80
  const dataProps = buildDataProps(data)
@@ -89,51 +85,6 @@ const Contact = (props: ContactProps): React.ReactElement => {
89
85
  className
90
86
  )
91
87
 
92
- const formattedValue = formatContact(contactValue, contactType)
93
- const content = (
94
- <>
95
- {iconEnabled && (contactType === 'email' ? (
96
- <Icon
97
- className="svg-inline--fa envelope"
98
- customIcon={envelopeIcon}
99
- dark={dark}
100
- fixedWidth
101
- />
102
- ) : (
103
- <Icon
104
- dark={dark}
105
- fixedWidth
106
- icon={contactTypeMap[contactType] || 'phone'}
107
- />
108
- ))}
109
- {iconEnabled ? ` ${formattedValue} ` : formattedValue}
110
- {contactDetail && (
111
- <Caption
112
- dark={dark}
113
- size="xs"
114
- tag="span"
115
- text={contactDetail}
116
- />
117
- )}
118
- </>
119
- )
120
-
121
- // When unstyled, render just the content without Body wrapper
122
- if (unstyled) {
123
- return (
124
- <span
125
- {...ariaProps}
126
- {...dataProps}
127
- {...htmlProps}
128
- className={classes}
129
- id={id}
130
- >
131
- {content}
132
- </span>
133
- )
134
- }
135
-
136
- // Default styled mode with Body wrapper
137
88
  return (
138
89
  <div
139
90
  {...ariaProps}
@@ -144,11 +95,33 @@ const Contact = (props: ContactProps): React.ReactElement => {
144
95
  >
145
96
  <Body
146
97
  className="pb_contact_kit"
147
- color="light"
98
+ color={"light"}
148
99
  dark={dark}
149
100
  tag="span"
150
101
  >
151
- {content}
102
+ {contactType === 'email' ? (
103
+ <Icon
104
+ className="svg-inline--fa envelope"
105
+ customIcon={envelopeIcon}
106
+ dark={dark}
107
+ fixedWidth
108
+ />
109
+ ) : (
110
+ <Icon
111
+ dark={dark}
112
+ fixedWidth
113
+ icon={contactTypeMap[contactType] || 'phone'}
114
+ />
115
+ )}
116
+ {` ${formatContact(contactValue, contactType)} `}
117
+ {contactDetail && (
118
+ <Caption
119
+ dark={dark}
120
+ size="xs"
121
+ tag="span"
122
+ text={contactDetail}
123
+ />
124
+ )}
152
125
  </Body>
153
126
  </div>
154
127
  )
@@ -1,23 +1,24 @@
1
- <% if object.unstyled %>
2
- <%= content_tag :span, class: object.classname, id: object.id, data: object.data, aria: object.aria, **object.html_options do %>
3
- <% if icon_enabled %>
4
- <% if contact_type == "email" %>
5
- <%= pb_rails("icon", props: {
6
- custom_icon: Playbook::Engine::root.join(envelope_path),
7
- fixed_width: true,
8
- dark: object.dark
9
- }) %>
10
- <% else %>
11
- <%= pb_rails("icon", props: {
12
- icon: object.contact_icon,
13
- fixed_width: true,
14
- dark: object.dark
15
- }) %>
16
- <% end %>
17
- <%= " #{object.formatted_contact_value}" if object.contact_value %>
1
+ <%= pb_content_tag do %>
2
+ <%= pb_rails("body", props: {
3
+ tag: "span",
4
+ classname: "pb_contact_kit",
5
+ color: "light",
6
+ dark: object.dark
7
+ }) do %>
8
+ <% if contact_type == "email" %>
9
+ <%= pb_rails("icon", props: {
10
+ custom_icon: Playbook::Engine::root.join(envelope_path),
11
+ fixed_width: true,
12
+ dark: object.dark
13
+ }) %>
18
14
  <% else %>
19
- <%= object.formatted_contact_value if object.contact_value %>
15
+ <%= pb_rails("icon", props: {
16
+ icon: object.contact_icon,
17
+ fixed_width: true,
18
+ dark: object.dark
19
+ }) %>
20
20
  <% end %>
21
+ <%= object.formatted_contact_value if object.contact_value %>
21
22
 
22
23
  <%= pb_rails("caption", props: {
23
24
  text: object.contact_detail,
@@ -26,39 +27,4 @@
26
27
  dark: object.dark
27
28
  }) if object.contact_detail %>
28
29
  <% end %>
29
- <% else %>
30
- <%= pb_content_tag do %>
31
- <%= pb_rails("body", props: {
32
- tag: "span",
33
- classname: "pb_contact_kit",
34
- color: "light",
35
- dark: object.dark
36
- }) do %>
37
- <% if icon_enabled %>
38
- <% if contact_type == "email" %>
39
- <%= pb_rails("icon", props: {
40
- custom_icon: Playbook::Engine::root.join(envelope_path),
41
- fixed_width: true,
42
- dark: object.dark
43
- }) %>
44
- <% else %>
45
- <%= pb_rails("icon", props: {
46
- icon: object.contact_icon,
47
- fixed_width: true,
48
- dark: object.dark
49
- }) %>
50
- <% end %>
51
- <%= " #{object.formatted_contact_value}" if object.contact_value %>
52
- <% else %>
53
- <%= object.formatted_contact_value if object.contact_value %>
54
- <% end %>
55
-
56
- <%= pb_rails("caption", props: {
57
- text: object.contact_detail,
58
- tag: 'span',
59
- size: 'xs',
60
- dark: object.dark
61
- }) if object.contact_detail %>
62
- <% end %>
63
- <% end %>
64
30
  <% end %>
@@ -8,8 +8,6 @@ module Playbook
8
8
  prop :contact_type
9
9
  prop :contact_value
10
10
  prop :contact_detail
11
- prop :icon_enabled, type: Playbook::Props::Boolean, default: true
12
- prop :unstyled, type: Playbook::Props::Boolean, default: false
13
11
 
14
12
  def classname
15
13
  generate_classname("pb_contact_kit")
@@ -46,15 +44,7 @@ module Playbook
46
44
  elsif contact_type == "international"
47
45
  contact_value
48
46
  else
49
- # Check if number has leading 1 (US country code)
50
- # Format like "+1 (212) 555-1234"
51
- intl_code = ""
52
- cleaned_number = formatted_value
53
- if cleaned_number.length == 11 && cleaned_number.start_with?("1")
54
- intl_code = "+1 "
55
- cleaned_number = cleaned_number.sub(/^1/, "")
56
- end
57
- "#{intl_code}#{number_to_phone(cleaned_number, area_code: true)}"
47
+ number_to_phone(formatted_value, area_code: true)
58
48
  end
59
49
  end
60
50
 
@@ -149,79 +149,3 @@ test('international contact type preserves original format', () => {
149
149
  const kit = screen.getByTestId('test-international-format')
150
150
  expect(kit).toHaveTextContent('+44 20 7946 0958')
151
151
  })
152
-
153
- test('iconEnabled prop hides icon when false', () => {
154
- render(
155
- <>
156
- <Contact
157
- contactType="home"
158
- contactValue="2125551234"
159
- data={{ testid: 'test-with-icon' }}
160
- iconEnabled
161
- />
162
- <Contact
163
- contactType="home"
164
- contactValue="2125551234"
165
- data={{ testid: 'test-without-icon' }}
166
- iconEnabled={false}
167
- />
168
- </>
169
- )
170
-
171
- // With icon enabled, should have icon
172
- expect(screen.getByTestId('test-with-icon').querySelector('.pb_custom_icon')).toBeInTheDocument()
173
-
174
- // Without icon, should not have icon
175
- expect(screen.getByTestId('test-without-icon').querySelector('.pb_custom_icon')).not.toBeInTheDocument()
176
-
177
- // But should still have the formatted phone number
178
- expect(screen.getByTestId('test-without-icon')).toHaveTextContent('(212) 555-1234')
179
- })
180
-
181
- test('unstyled prop renders without Body wrapper', () => {
182
- render(
183
- <>
184
- <Contact
185
- contactType="home"
186
- contactValue="2125551234"
187
- data={{ testid: 'test-styled' }}
188
- />
189
- <Contact
190
- contactType="home"
191
- contactValue="2125551234"
192
- data={{ testid: 'test-unstyled' }}
193
- unstyled
194
- />
195
- </>
196
- )
197
-
198
- // Styled version should have Body wrapper with pb_contact_kit class
199
- const styled = screen.getByTestId('test-styled')
200
- const styledBody = styled.querySelector('span.pb_contact_kit')
201
- expect(styledBody).toBeInTheDocument()
202
- expect(styledBody).toHaveTextContent('(212) 555-1234')
203
-
204
- // Unstyled version should be a span without Body wrapper
205
- const unstyled = screen.getByTestId('test-unstyled')
206
- expect(unstyled.tagName).toBe('SPAN')
207
- expect(unstyled.querySelector('span.pb_contact_kit')).not.toBeInTheDocument()
208
- expect(unstyled).toHaveTextContent('(212) 555-1234')
209
- })
210
-
211
- test('unstyled and iconEnabled work together', () => {
212
- render(
213
- <Contact
214
- contactType="home"
215
- contactValue="2125551234"
216
- data={{ testid: 'test-unstyled-no-icon' }}
217
- iconEnabled={false}
218
- unstyled
219
- />
220
- )
221
-
222
- const kit = screen.getByTestId('test-unstyled-no-icon')
223
- expect(kit.tagName).toBe('SPAN')
224
- expect(kit.querySelector('.pb_custom_icon')).not.toBeInTheDocument()
225
- expect(kit.querySelector('.pb_body_kit')).not.toBeInTheDocument()
226
- expect(kit).toHaveTextContent('(212) 555-1234')
227
- })
@@ -3,13 +3,11 @@ examples:
3
3
  rails:
4
4
  - contact_default: Default
5
5
  - contact_with_detail: Detail Indicator
6
- - contact_unstyled: Unstyled
7
6
 
8
7
 
9
8
  react:
10
9
  - contact_default: Default
11
10
  - contact_with_detail: Detail Indicator
12
- - contact_unstyled: Unstyled
13
11
 
14
12
 
15
13
  swift:
@@ -1,3 +1,2 @@
1
1
  export { default as ContactDefault } from './_contact_default.jsx'
2
2
  export { default as ContactWithDetail } from './_contact_with_detail.jsx'
3
- export { default as ContactUnstyled } from './_contact_unstyled.jsx'
@@ -251,28 +251,4 @@ describe('DatePicker Kit', () => {
251
251
  expect(input).toHaveValue(DateTime.getYearStartDate(new Date()).formatDate() + " to " + new Date().formatDate())
252
252
  })
253
253
  })
254
-
255
-
256
- test('displays defaultDate when it is later than maxDate', async () => {
257
- const testId = 'datepicker-out-of-range-after'
258
- const futureDateString = '01/15/2020'
259
- const maxDateString = '01/10/2020'
260
-
261
- render(
262
- <DatePicker
263
- data={{ testid: testId }}
264
- defaultDate={futureDateString}
265
- format="m/d/Y"
266
- maxDate={maxDateString}
267
- pickerId="date-picker-out-of-range-after"
268
- />
269
- )
270
-
271
- const kit = screen.getByTestId(testId)
272
- const input = within(kit).getByPlaceholderText('Select Date')
273
-
274
- await waitFor(() => {
275
- expect(input).toHaveValue('01/15/2020')
276
- }, { timeout: 5000 })
277
- })
278
254
  })
@@ -275,80 +275,6 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
275
275
 
276
276
  const { setMinDate, setMaxDate } = getMinMaxDates()
277
277
 
278
- // Default Date + Min/Max Date Initialization Helper Functions section ----/
279
- const toDateObject = (dateValue: any): Date | null => {
280
- if (!dateValue) return null
281
- if (dateValue instanceof Date) return dateValue
282
- if (typeof dateValue === 'string') {
283
- const parsed = new Date(dateValue)
284
- return isNaN(parsed.getTime()) ? null : parsed
285
- }
286
- if (typeof dateValue === 'number') {
287
- return new Date(dateValue)
288
- }
289
- return null
290
- }
291
-
292
- // Formatting Date for Flatpickr
293
- const formatDateForFlatpickr = (dateValue: any): string | null => {
294
- const dateObj = toDateObject(dateValue)
295
- if (!dateObj) return null
296
-
297
- const year = dateObj.getFullYear()
298
- const month = String(dateObj.getMonth() + 1).padStart(2, '0')
299
- const day = String(dateObj.getDate()).padStart(2, '0')
300
- return `${year}-${month}-${day}`
301
- }
302
-
303
- // Helper to check if defaultDate is earlier than minDate
304
- const isDefaultDateBeforeMinDate = (defaultDateValue: any, minDateValue: any): boolean => {
305
- if (!defaultDateValue || !minDateValue) return false
306
-
307
- const defaultDateObj = toDateObject(defaultDateValue)
308
- const minDateObj = toDateObject(minDateValue)
309
-
310
- if (!defaultDateObj || !minDateObj) return false
311
-
312
- const defaultDateOnly = new Date(defaultDateObj.getFullYear(), defaultDateObj.getMonth(), defaultDateObj.getDate())
313
- const minDateOnly = new Date(minDateObj.getFullYear(), minDateObj.getMonth(), minDateObj.getDate())
314
-
315
- return defaultDateOnly < minDateOnly
316
- }
317
-
318
- // Helper to check if defaultDate is later than maxDate
319
- const isDefaultDateAfterMaxDate = (defaultDateValue: any, maxDateValue: any): boolean => {
320
- if (!defaultDateValue || !maxDateValue) return false
321
-
322
- const defaultDateObj = toDateObject(defaultDateValue)
323
- const maxDateObj = toDateObject(maxDateValue)
324
-
325
- if (!defaultDateObj || !maxDateObj) return false
326
-
327
- const defaultDateOnly = new Date(defaultDateObj.getFullYear(), defaultDateObj.getMonth(), defaultDateObj.getDate())
328
- const maxDateOnly = new Date(maxDateObj.getFullYear(), maxDateObj.getMonth(), maxDateObj.getDate())
329
-
330
- return defaultDateOnly > maxDateOnly
331
- }
332
-
333
- const defaultDateValue: any = defaultDateGetter()
334
- // Only check for and out-of-range if user actually provided minDate/maxDate constraints
335
- const isBeforeMin = minDate && isDefaultDateBeforeMinDate(defaultDateValue, setMinDate)
336
- const isAfterMax = maxDate && isDefaultDateAfterMaxDate(defaultDateValue, setMaxDate)
337
-
338
- // Store these values for use in onClose handler
339
- const hasOutOfRangeDefault = (isBeforeMin || isAfterMax) && defaultDateValue
340
-
341
- // Temporarily adjust minDate/maxDate to allow defaultDate to render if it's out of range via user provided minDate/maxDate constraints
342
- const effectiveMinDate = isBeforeMin && defaultDateValue && minDate
343
- ? formatDateForFlatpickr(defaultDateValue) || setMinDate
344
- : setMinDate
345
-
346
- const effectiveMaxDate = isAfterMax && defaultDateValue && maxDate
347
- ? formatDateForFlatpickr(defaultDateValue) || setMaxDate
348
- : setMaxDate
349
-
350
- // End of Default Date + Min/Max Date Initialization Helper Functions section ----/
351
-
352
278
  flatpickr(`#${pickerId}`, {
353
279
  allowInput,
354
280
  closeOnSelect,
@@ -360,32 +286,11 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
360
286
  locale: {
361
287
  rangeSeparator: ' to '
362
288
  },
363
- maxDate: effectiveMaxDate,
364
- minDate: effectiveMinDate,
289
+ maxDate: setMaxDate,
290
+ minDate: setMinDate,
365
291
  mode,
366
292
  nextArrow: '<i class="far fa-angle-right"></i>',
367
293
  onOpen: [(_selectedDates, _dateStr, fp) => {
368
- // If defaultDate was out of range of a dev set min/max date, restore it when calendar opens (in situation where the input was manually cleared or the calendar was closed without selection)
369
- if (hasOutOfRangeDefault) {
370
- const dateObj = toDateObject(defaultDateValue)
371
- if (dateObj) {
372
- const inputIsBlank = !fp.input.value || fp.input.value.trim() === ''
373
- const noSelection = !fp.selectedDates || fp.selectedDates.length === 0
374
-
375
- if (inputIsBlank || noSelection) {
376
- const formattedDate = fp.formatDate(dateObj, getDateFormat())
377
- if (formattedDate) {
378
- fp.input.value = formattedDate
379
- }
380
- fp.selectedDates = [dateObj]
381
- fp.jumpToDate(dateObj)
382
- setTimeout(() => {
383
- yearChangeHook(fp)
384
- }, 0)
385
- }
386
- }
387
- }
388
-
389
294
  calendarResizer()
390
295
  if (resizeRepositionHandlerRef) {
391
296
  window.removeEventListener('resize', resizeRepositionHandlerRef)
@@ -398,30 +303,12 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
398
303
  if (!staticPosition && scrollContainer) attachToScroll(scrollContainer)
399
304
  positionCalendarIfNeeded(fp)
400
305
  }],
401
- onClose: [(selectedDates, dateStr, fp) => {
306
+ onClose: [(selectedDates, dateStr) => {
402
307
  if (resizeRepositionHandlerRef) {
403
308
  window.removeEventListener('resize', resizeRepositionHandlerRef)
404
309
  resizeRepositionHandlerRef = null
405
310
  }
406
311
  if (!staticPosition && scrollContainer) detachFromScroll(scrollContainer as HTMLElement)
407
-
408
- // If defaultDate was out of range and no date was selected, preserve the default date
409
- if (hasOutOfRangeDefault && (!selectedDates || selectedDates.length === 0)) {
410
- const dateObj = toDateObject(defaultDateValue)
411
- if (dateObj && fp.input) {
412
- const formattedDate = fp.formatDate(dateObj, getDateFormat())
413
- if (formattedDate) {
414
- setTimeout(() => {
415
- if (fp.input && (!fp.selectedDates || fp.selectedDates.length === 0)) {
416
- fp.input.value = formattedDate
417
- fp.selectedDates = [dateObj]
418
- fp.jumpToDate(dateObj)
419
- }
420
- }, 0)
421
- }
422
- }
423
- }
424
-
425
312
  onClose(selectedDates, dateStr)
426
313
  }],
427
314
  onChange: [(selectedDates, dateStr, fp) => {
@@ -443,71 +330,6 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
443
330
  const picker = document.querySelector<HTMLElement & { [x: string]: any }>(`#${pickerId}`)._flatpickr
444
331
  picker.innerContainer.parentElement.id = `cal-${pickerId}`
445
332
 
446
- // If defaultDate was out of range, restore the original minDate/maxDate after initialization (defaultDate displayed, still cannot select dates outside the actual range via user provided minDate/maxDate constraints)
447
- if ((isBeforeMin || isAfterMax) && defaultDateValue) {
448
- const dateObj = toDateObject(defaultDateValue)
449
- const formattedDate = dateObj ? picker.formatDate(dateObj, getDateFormat()) : null
450
-
451
- setTimeout(() => {
452
- if (!dateObj || !picker.input || !formattedDate) return
453
-
454
- picker.setDate(dateObj, false)
455
-
456
- if (isBeforeMin && setMinDate && minDate) {
457
- picker.set('minDate', setMinDate)
458
- }
459
- if (isAfterMax && setMaxDate && maxDate) {
460
- picker.set('maxDate', setMaxDate)
461
- }
462
- picker.input.value = formattedDate
463
-
464
- picker.selectedDates = [dateObj]
465
-
466
- setTimeout(() => {
467
- yearChangeHook(picker)
468
- }, 0)
469
-
470
- // Restore function for out-of-range default dates
471
- const restoreOutOfRangeValue = () => {
472
- if (!picker.input) return
473
-
474
- const inputIsBlank = !picker.input.value || picker.input.value.trim() === ''
475
- const noSelection = !picker.selectedDates || picker.selectedDates.length === 0
476
-
477
- if (inputIsBlank || noSelection) {
478
- setTimeout(() => {
479
- if (picker.input && (!picker.input.value || picker.input.value.trim() === '')) {
480
- picker.input.value = formattedDate
481
- }
482
- if (!picker.selectedDates || picker.selectedDates.length === 0) {
483
- picker.selectedDates = [dateObj]
484
- if (picker.isOpen) {
485
- picker.jumpToDate(dateObj)
486
- picker.redraw()
487
- setTimeout(() => {
488
- yearChangeHook(picker)
489
- }, 0)
490
- }
491
- }
492
- }, 0)
493
- }
494
- }
495
-
496
- const originalClear = picker.clear.bind(picker)
497
- picker.clear = function(...args: any[]) {
498
- const result = originalClear(...args)
499
- setTimeout(() => restoreOutOfRangeValue(), 0)
500
- return result
501
- }
502
-
503
- picker.input.addEventListener('input', restoreOutOfRangeValue)
504
-
505
- picker.config.onClose.push(() => {
506
- restoreOutOfRangeValue()
507
- })
508
- }, 10)
509
- }
510
-
511
333
  // replace year selector with dropdown
512
334
  picker.yearElements[0].parentElement.innerHTML = `<select class="numInput cur-year" type="number" tabIndex="-1" aria-label="Year" id="year-${pickerId}"></select>`
513
335