playbook_ui 15.5.0.pre.alpha.PLAY2554homeaddressstreetaccessibility12695 → 15.5.0.pre.alpha.PLAY2581aggressivevalidation12650

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b17349abd67079ab8e811b239c8971e2809a0299a6f69e41e247ee2a34a8d7bc
4
- data.tar.gz: f0d3ef9cca63f616d580065e9058bc5a6514ddfda74ea028af65191562bf7c9e
3
+ metadata.gz: e03ff921e93222ee43918cb8f7587728ec77eecf9d7bf901103e955fa387d9d3
4
+ data.tar.gz: 124557cd8f737ad7999cf59787eb9183e52f3ebcd4853bad2241b7e4d1982aa0
5
5
  SHA512:
6
- metadata.gz: 65f48b3ade3d01c25fb8e4f44828db75e64aba0ceba8bcfd7b9f7b17b11750ed7c7ad890e424a33333da0c88e299701094d18fbc8227b20994579cecaa575a2c
7
- data.tar.gz: 858d50215f7af0969b58fddf455b162a6109efd4a3854884dcfbf55fbf29658345dd7dcd1faf97f9b5ecaf79a2022637e0f9f869f3ba7159cdf174e9c615bc0d
6
+ metadata.gz: 2a97fa52358423064cf1c1564ea623fc2087debacc08bf9e282c59ea274b41c8725f9ea37b3dc414d35227bf7d17dc621e2850def822925047564deb6181edf0
7
+ data.tar.gz: '0195e845746b7ab77e555c006a506a951ca7347ce65668b12d67401387363c1031b641f156cda4ba2332bfd11b9b46d3dfbe772d3d42c01f58f3930650870f88'
@@ -1,24 +1,3 @@
1
- <%
2
- options = [
3
- {
4
- label: "United States",
5
- value: "unitedStates",
6
- id: "us"
7
- },
8
- {
9
- label: "United Kingdom",
10
- value: "unitedKingdom",
11
- id: "gb"
12
- },
13
- {
14
- label: "Pakistan",
15
- value: "pakistan",
16
- id: "pk"
17
- }
18
- ]
19
- %>
20
-
21
-
22
1
  <%= pb_rails("button", props: { text: "Open Complex Dialog", data:{"open-dialog": "dialog-complex"} }) %>
23
2
 
24
3
  <%= pb_rails("dialog", props: { id:"dialog-complex", size: "lg", full_height: true }) do %>
@@ -31,16 +10,6 @@
31
10
  <%= pb_rails("rich_text_editor", props: {id: "default", value: "Add your text here"}) %>
32
11
  <%= pb_rails("caption", props: { text: "Type in a word or term too help find tickets later. ex. training, phone setup, hr", margin_bottom: "xs", margin_top: "sm" }) %>
33
12
  <%= pb_rails("typeahead", props: { placeholder: "Tags.."}) %>
34
- <%= pb_rails("dropdown", props: {options: options, autocomplete: true}) %>
35
- <%= pb_rails("typeahead", props: {
36
- id: "typeahead-default",
37
- placeholder: "Select one...",
38
- options: options,
39
- name: :foo,
40
- margin_top: "sm",
41
- is_multi: false
42
- })
43
- %>
44
13
 
45
14
  <% end %>
46
15
  <%= pb_rails("dialog/dialog_footer", props: {cancel_button: "Back", confirm_button: "Send my Issue", confirm_button_id:"confirm-complex", id: "dialog-complex"}) %>
@@ -143,30 +143,25 @@ export default class PbDialog extends PbEnhancedElement {
143
143
 
144
144
  // Close dialog box on outside click
145
145
  dialogs.forEach((dialogElement) => {
146
- const originalClickHandler = dialogElement._outsideClickHandler
147
- if (originalClickHandler) dialogElement.removeEventListener("click", originalClickHandler)
148
-
146
+ const originalMousedownHandler = dialogElement._outsideClickHandler
147
+ if (originalMousedownHandler) dialogElement.removeEventListener("mousedown", originalMousedownHandler)
149
148
  dialogElement._outsideClickHandler = (event) => {
150
149
  const dialogParentDataset = dialogElement.parentElement.dataset
151
150
  if (dialogParentDataset.overlayClick === "overlay_close") return
152
151
 
153
- // Get the dialog's bounding box (the actual content area)
154
- const rect = dialogElement.getBoundingClientRect()
155
- const clickedInDialog = (
156
- event.clientX >= rect.left &&
157
- event.clientX <= rect.right &&
158
- event.clientY >= rect.top &&
159
- event.clientY <= rect.bottom
160
- )
161
-
162
- // Only close if clicked outside the dialog content (on the backdrop)
163
- if (!clickedInDialog) {
152
+ const dialogModal = event.target.getBoundingClientRect()
153
+ const clickedOutsideDialogModal = event.clientX < dialogModal.left ||
154
+ event.clientX > dialogModal.right ||
155
+ event.clientY < dialogModal.top ||
156
+ event.clientY > dialogModal.bottom
157
+
158
+ if (clickedOutsideDialogModal) {
164
159
  dialogElement.close()
165
160
  event.stopPropagation()
166
161
  }
167
162
  }
168
163
 
169
- dialogElement.addEventListener("click", dialogElement._outsideClickHandler);
164
+ dialogElement.addEventListener("mousedown", dialogElement._outsideClickHandler);
170
165
  })
171
166
  }
172
167
  }
@@ -1,5 +1,5 @@
1
1
  .pb_file_upload_kit {
2
- .pb_card_kit {
2
+ .pb_card_kit_deselected_border_radius_md {
3
3
  border: 1px #ccc dashed;
4
4
  text-align: center;
5
5
  }
@@ -11,7 +11,7 @@
11
11
  }
12
12
  &.error,
13
13
  &.pb_file_upload_kit_error {
14
- .pb_card_kit {
14
+ .pb_card_kit_deselected_border_radius_md {
15
15
  border-color: $error;
16
16
  }
17
17
  .pb_body_kit_negative {
@@ -30,12 +30,12 @@
30
30
  }
31
31
 
32
32
  .dark .pb_file_upload_kit {
33
- .pb_card_kit {
33
+ .pb_card_kit_deselected_border_radius_md {
34
34
  border: 1px $text_dk_lighter dashed;
35
35
  }
36
36
  &.error,
37
37
  &.pb_file_upload_kit_error {
38
- .pb_card_kit {
38
+ .pb_card_kit_deselected_border_radius_md {
39
39
  border-color: $error_dark;
40
40
  }
41
41
  }
@@ -96,24 +96,20 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
96
96
  {hasAllEmptyProps && '—'}
97
97
  {emphasis == 'street' && !hasAllEmptyProps &&
98
98
  <div>
99
- {(address || houseStyle) && (
100
- <Title
101
- className="pb_home_address_street_address"
102
- dark={dark}
103
- size={4}
104
- >
105
- {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
106
- </Title>
107
- )}
108
- {addressCont && (
109
- <Title
110
- className="pb_home_address_street_address"
111
- dark={dark}
112
- size={4}
113
- >
114
- {titleize(addressCont)}
115
- </Title>
116
- )}
99
+ <Title
100
+ className="pb_home_address_street_address"
101
+ dark={dark}
102
+ size={4}
103
+ >
104
+ {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
105
+ </Title>
106
+ <Title
107
+ className="pb_home_address_street_address"
108
+ dark={dark}
109
+ size={4}
110
+ >
111
+ {titleize(addressCont)}
112
+ </Title>
117
113
  <Body color="light">
118
114
  {`${city ? `${titleize(city)}, ` : ''}${uppercaseState}${zipcode ? ` ${zipcode}` : ''}`}
119
115
  </Body>
@@ -121,14 +117,10 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
121
117
  }
122
118
  {emphasis == 'city' && !hasAllEmptyProps &&
123
119
  <div>
124
- {(address || houseStyle) && (
125
- <Body color="light">
126
- {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
127
- </Body>
128
- )}
129
- {addressCont && (
130
- <Body color="light">{titleize(addressCont)}</Body>
131
- )}
120
+ <Body color="light">
121
+ {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
122
+ </Body>
123
+ <Body color="light">{titleize(addressCont)}</Body>
132
124
  <div>
133
125
  <Title
134
126
  className="pb_home_address_street_address"
@@ -149,14 +141,10 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
149
141
  }
150
142
  {emphasis == 'none' && !hasAllEmptyProps &&
151
143
  <div>
152
- {(address || houseStyle) && (
153
- <Body dark={dark}>
154
- {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
155
- </Body>
156
- )}
157
- {addressCont && (
158
- <Body dark={dark}>{formatStreetAdr(addressCont)}</Body>
159
- )}
144
+ <Body dark={dark}>
145
+ {joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
146
+ </Body>
147
+ <Body dark={dark}>{formatStreetAdr(addressCont)}</Body>
160
148
  <div>
161
149
  <Body
162
150
  color="light"
@@ -1,19 +1,15 @@
1
- <% if object.address_house_style.present? %>
2
- <%= pb_rails "body", props: {
3
- classname: "pb_home_address_street_address",
4
- color: "light",
5
- text: object.address_house_style,
6
- dark: object.dark
7
- } %>
8
- <% end %>
9
- <% if object.address_house_style2.present? %>
10
- <%= pb_rails "body", props: {
11
- classname: "pb_home_address_street_address",
12
- color: "light",
13
- text: object.address_house_style2,
14
- dark: object.dark
15
- } %>
16
- <% end %>
1
+ <%= pb_rails "body", props: {
2
+ classname: "pb_home_address_street_address",
3
+ color: "light",
4
+ text: object.address_house_style,
5
+ dark: object.dark
6
+ } %>
7
+ <%= pb_rails "body", props: {
8
+ classname: "pb_home_address_street_address",
9
+ color: "light",
10
+ text: object.address_house_style2,
11
+ dark: object.dark
12
+ } %>
17
13
  <div>
18
14
  <%= pb_rails "title", props: {
19
15
  tag: "span",
@@ -1,4 +1,3 @@
1
- <%= pb_rails("caption", props: { text: "with all" }) %>
2
1
  <%= pb_rails("home_address_street", props: {
3
2
  address: "70 Prospect Ave",
4
3
  address_cont: "Apt M18",
@@ -10,126 +9,3 @@
10
9
  zipcode: "19382",
11
10
  territory: "PHL",
12
11
  }) %>
13
-
14
- <%= pb_rails("caption", props: { margin_top: "sm", text: "First two lines blank: without address and address cont and housestyle" }) %>
15
- <%= pb_rails("home_address_street", props: {
16
- city: "West Chester",
17
- home_id: 8250263,
18
- home_url: "https://powerhrg.com/",
19
- state: "PA",
20
- zipcode: "19382",
21
- territory: "PHL",
22
- }) %>
23
-
24
- <%= pb_rails("caption", props: { margin_top: "sm", text: "First line half blank Second line full: with housestyle and without address and address cont" }) %>
25
- <%= pb_rails("home_address_street", props: {
26
- city: "West Chester",
27
- home_id: 8250263,
28
- home_url: "https://powerhrg.com/",
29
- house_style: "Colonial",
30
- state: "PA",
31
- zipcode: "19382",
32
- territory: "PHL",
33
- }) %>
34
-
35
- <%= pb_rails("caption", props: { margin_top: "sm", text: "First line full Second line blank: with address and housestyle and without address cont" }) %>
36
- <%= pb_rails("home_address_street", props: {
37
- address: "70 Prospect Ave",
38
- city: "West Chester",
39
- home_id: 8250263,
40
- home_url: "https://powerhrg.com/",
41
- house_style: "Colonial",
42
- state: "PA",
43
- zipcode: "19382",
44
- territory: "PHL",
45
- }) %>
46
-
47
- <%= pb_rails("caption", props: { margin_top: "sm", text: "First line half blank Second line full: without address and with housestyle and address cont" }) %>
48
- <%= pb_rails("home_address_street", props: {
49
- address_cont: "Apt M18",
50
- city: "West Chester",
51
- home_id: 8250263,
52
- home_url: "https://powerhrg.com/",
53
- house_style: "Colonial",
54
- state: "PA",
55
- zipcode: "19382",
56
- territory: "PHL",
57
- }) %>
58
-
59
- <%= pb_rails("caption", props: { margin_top: "sm", text: "First line blank Second line full: with address cont and without address and housestyle" }) %>
60
- <%= pb_rails("home_address_street", props: {
61
- address_cont: "Apt M18",
62
- city: "West Chester",
63
- home_id: 8250263,
64
- home_url: "https://powerhrg.com/",
65
- state: "PA",
66
- zipcode: "19382",
67
- territory: "PHL",
68
- }) %>
69
-
70
- <%= pb_rails("caption", props: { margin_top: "sm", text: "Emphasis, Modified, Target and Formatted doc examples below" }) %>
71
- <%= pb_rails("home_address_street", props: {
72
- address: "70 Prospect Ave",
73
- city: "West Chester",
74
- emphasis: "none",
75
- home_id: 8250263,
76
- home_url: "https://powerhrg.com/",
77
- house_style: "Colonial",
78
- margin_bottom: "sm",
79
- state: "PA",
80
- zipcode: "19382",
81
- territory: "PHL",
82
- }) %>
83
-
84
- <%= pb_rails("home_address_street", props: {
85
- city: "West Chester",
86
- emphasis: "city",
87
- home_id: 8250263,
88
- home_url: "https://powerhrg.com/",
89
- margin_bottom: "sm",
90
- state: "PA",
91
- zipcode: "19382",
92
- territory: "PHL",
93
- }) %>
94
-
95
- <%= pb_rails("home_address_street", props: {
96
- city: "West Chester",
97
- emphasis: "none",
98
- home_id: 8250263,
99
- home_url: "https://powerhrg.com/",
100
- margin_bottom: "sm",
101
- state: "PA",
102
- zipcode: "19382",
103
- territory: "PHL",
104
- }) %>
105
-
106
- <%= pb_rails("home_address_street", props: {
107
- address: "70 Prospect Ave",
108
- city: "West Chester",
109
- margin_bottom: "sm",
110
- state: "PA",
111
- zipcode: "19382",
112
- territory: "PHL",
113
- }) %>
114
-
115
- <%= pb_rails("home_address_street", props: {
116
- city: "West Chester",
117
- home_id: 8250263,
118
- home_url: "https://powerhrg.com/",
119
- margin_bottom: "sm",
120
- state: "PA",
121
- target: "_blank",
122
- zipcode: "19382",
123
- territory: "PHL",
124
- }) %>
125
-
126
- <%= pb_rails("home_address_street", props: {
127
- address: "70 pRoSpEcT ave",
128
- city: "West Chester",
129
- home_id: 8250263,
130
- home_url: "https://powerhrg.com/",
131
- preserve_case: true,
132
- state: "pa",
133
- zipcode: "19382",
134
- territory: "PHL",
135
- }) %>
@@ -1,156 +1,21 @@
1
1
  import React from 'react'
2
2
 
3
3
  import HomeAddressStreet from '../_home_address_street'
4
- import Caption from '../../pb_caption/_caption'
5
4
 
6
5
  const HomeAddressStreetDefault = (props) => {
7
6
  return (
8
- <>
9
- <Caption text="with all" />
10
- <HomeAddressStreet
11
- address="70 Prospect Ave"
12
- addressCont="Apt M18"
13
- city="West Chester"
14
- homeId="8250263"
15
- homeUrl="https://powerhrg.com/"
16
- houseStyle="Colonial"
17
- state="PA"
18
- territory="PHL"
19
- zipcode="19382"
20
- {...props}
21
- />
22
- <Caption marginTop="sm"
23
- text="First two lines blank: without address and address cont and housestyle"
24
- />
25
- <HomeAddressStreet
26
- city="West Chester"
27
- homeId="8250263"
28
- homeUrl="https://powerhrg.com/"
29
- state="PA"
30
- territory="PHL"
31
- zipcode="19382"
32
- {...props}
33
- />
34
- <Caption marginTop="sm"
35
- text="First line half blank Second line full: with housestyle and without address and address cont"
36
- />
37
- <HomeAddressStreet
38
- city="West Chester"
39
- homeId="8250263"
40
- homeUrl="https://powerhrg.com/"
41
- houseStyle="Colonial"
42
- state="PA"
43
- territory="PHL"
44
- zipcode="19382"
45
- {...props}
46
- />
47
- <Caption marginTop="sm"
48
- text="First line full Second line blank: with address and housestyle and without address cont and address cont"
49
- />
50
- <HomeAddressStreet
51
- address="70 Prospect Ave"
52
- city="West Chester"
53
- homeId="8250263"
54
- homeUrl="https://powerhrg.com/"
55
- houseStyle="Colonial"
56
- state="PA"
57
- territory="PHL"
58
- zipcode="19382"
59
- {...props}
60
- />
61
- <Caption marginTop="sm"
62
- text="First line half blank Second line full: without address and with housestyle and address cont and address cont"
63
- />
64
- <HomeAddressStreet
65
- city="West Chester"
66
- homeId="8250263"
67
- homeUrl="https://powerhrg.com/"
68
- houseStyle="Colonial"
69
- state="PA"
70
- territory="PHL"
71
- zipcode="19382"
72
- {...props}
73
- />
74
- <Caption marginTop="sm"
75
- text="First line blank Second line full: with address cont and without address and housestyle and address cont"
76
- />
77
- <HomeAddressStreet
78
- addressCont="Apt M18"
79
- city="West Chester"
80
- homeId="8250263"
81
- homeUrl="https://powerhrg.com/"
82
- state="PA"
83
- territory="PHL"
84
- zipcode="19382"
85
- {...props}
86
- />
87
- <Caption marginTop="sm"
88
- text="Emphasis, Modified, Target and Formatted doc examples below and address cont"
89
- />
90
- <HomeAddressStreet
91
- address="70 Prospect Ave"
92
- city="West Chester"
93
- emphasis="none"
94
- homeId="8250263"
95
- homeUrl="https://powerhrg.com/"
96
- houseStyle="Colonial"
97
- marginBottom="sm"
98
- state="PA"
99
- territory="PHL"
100
- zipcode="19382"
101
- {...props}
102
- />
103
- <HomeAddressStreet
104
- city="West Chester"
105
- emphasis="city"
106
- homeId="8250263"
107
- homeUrl="https://powerhrg.com/"
108
- marginBottom="sm"
109
- state="PA"
110
- territory="PHL"
111
- zipcode="19382"
112
- {...props}
113
- />
114
- <HomeAddressStreet
115
- city="West Chester"
116
- emphasis="none"
117
- homeId="8250263"
118
- homeUrl="https://powerhrg.com/"
119
- marginBottom="sm"
120
- state="PA"
121
- territory="PHL"
122
- zipcode="19382"
123
- {...props}
124
- />
125
- <HomeAddressStreet
126
- address="70 Prospect Ave"
127
- city="West Chester"
128
- marginBottom="sm"
129
- state="PA"
130
- territory="PHL"
131
- zipcode="19382"
132
- />
133
- <HomeAddressStreet
134
- city="West Chester"
135
- homeId={8250263}
136
- homeUrl="https://powerhrg.com/"
137
- marginBottom="sm"
138
- state="PA"
139
- target="_blank"
140
- territory="PHL"
141
- zipcode="19382"
142
- />
143
- <HomeAddressStreet
144
- address="70 pRoSpEcT ave"
145
- city="West Chester"
146
- homeId="8250263"
147
- homeUrl="https://powerhrg.com/"
148
- preserveCase
149
- state="pa"
150
- territory="PHL"
151
- zipcode="19382"
152
- />
153
- </>
7
+ <HomeAddressStreet
8
+ address="70 Prospect Ave"
9
+ addressCont="Apt M18"
10
+ city="West Chester"
11
+ homeId="8250263"
12
+ homeUrl="https://powerhrg.com/"
13
+ houseStyle="Colonial"
14
+ state="PA"
15
+ territory="PHL"
16
+ zipcode="19382"
17
+ {...props}
18
+ />
154
19
  )
155
20
  }
156
21
 
@@ -1,19 +1,15 @@
1
- <% if object.address_house_style.present? %>
2
- <%= pb_rails "body", props: {
3
- classname: "pb_home_address_street_address",
4
- size: 4,
5
- text: object.address_house_style,
6
- dark: object.dark
7
- } %>
8
- <% end %>
9
- <% if object.address_house_style2.present? %>
10
- <%= pb_rails "body", props: {
11
- classname: "pb_home_address_street_address",
12
- size: 4,
13
- text: object.address_house_style2,
14
- dark: object.dark
15
- } %>
16
- <% end %>
1
+ <%= pb_rails "body", props: {
2
+ classname: "pb_home_address_street_address",
3
+ size: 4,
4
+ text: object.address_house_style,
5
+ dark: object.dark
6
+ } %>
7
+ <%= pb_rails "body", props: {
8
+ classname: "pb_home_address_street_address",
9
+ size: 4,
10
+ text: object.address_house_style2,
11
+ dark: object.dark
12
+ } %>
17
13
  <%= pb_rails "body", props: {
18
14
  color: "light",
19
15
  text: object.city_state_zip,
@@ -1,19 +1,15 @@
1
- <% if object.address_house_style.present? %>
2
- <%= pb_rails "title", props: {
3
- classname: "pb_home_address_street_address",
4
- size: 4,
5
- text: object.address_house_style,
6
- dark: object.dark
7
- } %>
8
- <% end %>
9
- <% if object.address_house_style2.present? %>
10
- <%= pb_rails "title", props: {
11
- classname: "pb_home_address_street_address",
12
- size: 4,
13
- text: object.address_house_style2,
14
- dark: object.dark
15
- } %>
16
- <% end %>
1
+ <%= pb_rails "title", props: {
2
+ classname: "pb_home_address_street_address",
3
+ size: 4,
4
+ text: object.address_house_style,
5
+ dark: object.dark
6
+ } %>
7
+ <%= pb_rails "title", props: {
8
+ classname: "pb_home_address_street_address",
9
+ size: 4,
10
+ text: object.address_house_style2,
11
+ dark: object.dark
12
+ } %>
17
13
  <%= pb_rails "body", props: {
18
14
  color: "light",
19
15
  text: object.city_state_zip,
@@ -115,6 +115,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
115
115
  const [dropDownIsOpen, setDropDownIsOpen] = useState(false)
116
116
  const [selectedData, setSelectedData] = useState()
117
117
  const [hasTyped, setHasTyped] = useState(false)
118
+ const [hasBlurred, setHasBlurred] = useState(false)
118
119
  const [formSubmitted, setFormSubmitted] = useState(false)
119
120
  const [hasStartedValidating, setHasStartedValidating] = useState(false)
120
121
 
@@ -143,8 +144,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
143
144
  }
144
145
 
145
146
  // Determine which error to display
146
- // Show internal errors on blur (hasTyped) or on form submission (formSubmitted)
147
- const shouldShowInternalError = (hasTyped || formSubmitted) && required && error
147
+ // Show internal errors only after blur (hasBlurred) or on form submission (formSubmitted)
148
+ const shouldShowInternalError = (hasBlurred || formSubmitted) && error
148
149
  const displayError = shouldShowInternalError ? error : ""
149
150
 
150
151
  useEffect(() => {
@@ -259,7 +260,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
259
260
  return
260
261
  }
261
262
 
262
- if (!hasTyped && !error) return
263
+ // Only validate if field has been blurred or form has been submitted
264
+ if (!hasBlurred && !formSubmitted && !error) return
263
265
 
264
266
  // Run validation checks
265
267
  if (itiRef.current) isValid(itiRef.current.isValidNumber())
@@ -305,6 +307,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
305
307
  setInputValue("")
306
308
  setError("")
307
309
  setHasTyped(false)
310
+ setHasBlurred(false)
308
311
  setFormSubmitted(false)
309
312
  setHasStartedValidating(false)
310
313
  // Only clear validation state if field was required
@@ -418,9 +421,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
418
421
  onChange(phoneNumberData)
419
422
  isValid(itiRef.current.isValidNumber())
420
423
 
421
- // Trigger validation after onChange for React Hook Form
422
- // This ensures validation state is up-to-date
423
- setTimeout(() => validateErrors(), 0)
424
+ // Don't validate on change - only validate on blur or form submission
424
425
  }
425
426
 
426
427
  // Separating Concerns as React Docs Recommend
@@ -497,7 +498,10 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
497
498
  id,
498
499
  label,
499
500
  name,
500
- onBlur: validateErrors,
501
+ onBlur: (e: React.FocusEvent<HTMLInputElement>) => {
502
+ setHasBlurred(true)
503
+ validateErrors()
504
+ },
501
505
  onChange: formatAsYouType ? undefined : handleOnChange,
502
506
  value: inputValue
503
507
  }