playbook_ui 15.1.0.pre.alpha.PLAY2468phonenuminputvalidation10803 → 15.1.0.pre.alpha.PLAY251810942

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: 1607dd2475fc082a109f3ad1d2dc03b07887fba69f23a5754d96020c18e75397
4
- data.tar.gz: 3b597c713dd113e61049aea67c57d0e30e2c33a8c144e2f0611cd053c3fa1406
3
+ metadata.gz: ea9f5c8acfb10e8fb3d40fea187b82854b1fb068361853c9b032f91fca4685ad
4
+ data.tar.gz: ff8472f9f4055f5b24cb17583c02c37fa5cc022f37bf7d36869cb4d2dc06feaf
5
5
  SHA512:
6
- metadata.gz: 89b69260b005e8a057fe6ada81c6c09706ad2dd938d1a1ea3403a5b8e36c5b50802f7c8976312429b14e2a9cc4c881d148f46e2567593f8a9db801d994a0c231
7
- data.tar.gz: 6121137545315510e02d3cda537276fb12b196e93cb3032542a6dd4c84a81ca612ecd181304d52710c2b8eaf07ce8238daf8f4cbdb64f9e39b257235178bd132
6
+ metadata.gz: a7a3df82c8d6bb097dc840c452b3658a4751f3ecb1efde791db7043328cca7a1450adb4d56b0b1d52e13ebd7e75163573105a2910bd01faeca49c05937086f83
7
+ data.tar.gz: 869e0b7510f081c28a277b0f77f1c96e2f63dccfc5955913140a00952741545f79e728370a234ded1cedba4fde080bbd396650e357a37b24ede37ac55428bfff
@@ -0,0 +1,31 @@
1
+ <%= pb_rails("body", props: { text: "Click to disable the Buttons below", id: "toggle-disabled-demo", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
2
+ <%= pb_rails("body", props: { text: "Click to enable the Buttons below", id: "toggle-enabled-demo", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
3
+
4
+ <%= pb_rails("card", props:{display:"flex", flex_direction:"row", justify_content:"center"}) do %>
5
+ <%= pb_rails("button", props: { text: "I am a Button", id: "normal_managed_button", data:{pb_button_managed: true}, margin_right: "lg" }) %>
6
+ <%= pb_rails("button", props: { text: "I am an <a> Button", id: "a_tag_managed_button", tag:"a", data:{pb_button_managed: true}, link: "http://google.com"}) %>
7
+ <% end %>
8
+ <script>
9
+ document.addEventListener('DOMContentLoaded', function () {
10
+ const disableTrigger = document.querySelector('#toggle-disabled-demo')
11
+ const enableTrigger = document.querySelector('#toggle-enabled-demo')
12
+
13
+ // Find the Buttons you want to 'manage'
14
+ const btn = document.querySelector('#normal_managed_button');
15
+ const link = document.querySelector('#a_tag_managed_button');
16
+
17
+ disableTrigger.addEventListener('click', (e) => {
18
+ // Disable default button
19
+ btn.setAttribute('disabled', true)
20
+ // Disable a tag button
21
+ link.setAttribute('aria-disabled', 'true')
22
+ });
23
+
24
+ enableTrigger.addEventListener('click', (e) => {
25
+ // Enable default button
26
+ btn.removeAttribute('disabled')
27
+ // Enable a tag button
28
+ link.removeAttribute('aria-disabled')
29
+ });
30
+ });
31
+ </script>
@@ -0,0 +1,7 @@
1
+ If needing to toggle the disabled state of the Button dynamically (for example, within a Turbo or Stimulus context), you can now do so in rails using the `pb-button-managed` data attribute.
2
+
3
+ 1) Add the following data attribute to your button kit: `data:{ pb-button-managed: true }`
4
+
5
+ 2) To toggle enabled/disabled state via attributes: for buttons set/remove disabled, for links set/remove aria-disabled="true". This will handle disabling the button, preventing clicks as well as all style changes so you don't have to.
6
+
7
+ Click to enable or disable the buttons above and view the code snippet below for details!
@@ -0,0 +1,21 @@
1
+ <%= pb_rails("body", props: { text: "Click to disable the Button below", id: "toggle-disabled-demo-with-helper", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
2
+ <%= pb_rails("body", props: { text: "Click to enable the Button below", id: "toggle-enabled-demo-with-helper", cursor: "pointer", color:"link", margin_bottom:"sm" }) %>
3
+ <br/>
4
+ <%= pb_rails("card", props:{display:"flex", flex_direction:"row", justify_content:"center"}) do %>
5
+ <%= pb_rails("button", props: { text: "Watch me Change!", id: "managed_button_with_helper", data:{pb_button_managed: true} }) %>
6
+ <% end %>
7
+
8
+ <script>
9
+ document.addEventListener('DOMContentLoaded', function () {
10
+ const disable = document.querySelector('#toggle-disabled-demo-with-helper')
11
+ const enable = document.querySelector('#toggle-enabled-demo-with-helper')
12
+
13
+ // Find the Button you want to 'manage'
14
+ const demoBtn = document.querySelector('#managed_button_with_helper')
15
+
16
+ // Use the pbButton object created by the kit to call the enable/disable methods
17
+ disable.addEventListener('click', (e) => {demoBtn._pbButton.disable()});
18
+ enable.addEventListener('click', (e) => {demoBtn._pbButton.enable()});
19
+
20
+ });
21
+ </script>
@@ -0,0 +1,7 @@
1
+ The disabled state for the button can also be toggled via small helpers available through the `pb-button-managed` data attribute.
2
+
3
+ 1) Add the following data attribute to your button kit: `data:{ pb-button-managed: true }`
4
+
5
+ 2) Toggle state via the provided `_pbButton.disable()` and `_pbButton.enable()` helpers as shown in the code snippet below.
6
+
7
+ Click to enable or disable the buttons above to see this in action!
@@ -11,6 +11,8 @@ examples:
11
11
  - button_options: Button Additional Options
12
12
  - button_size: Button Size
13
13
  - button_form: Button Form Attribute
14
+ - button_managed_disabled: Button Toggle Disabled State
15
+ - button_managed_disabled_helper: Button Toggle Disabled State Helper
14
16
 
15
17
  react:
16
18
  - button_default: Button Variants
@@ -0,0 +1,99 @@
1
+ import PbEnhancedElement from "../pb_enhanced_element"
2
+
3
+ const BUTTON_SELECTOR = "[data-pb-button-managed]"
4
+
5
+ export default class PbButton extends PbEnhancedElement {
6
+ static get selector() {
7
+ return BUTTON_SELECTOR
8
+ }
9
+
10
+ connect() {
11
+ this._attrManaged = this._attributesPresent()
12
+ this.element._pbButton = this
13
+
14
+ this._onClick = (e) => {
15
+ if (this.isDisabled()) {
16
+ e.preventDefault()
17
+ e.stopImmediatePropagation()
18
+ }
19
+ }
20
+ this.element.addEventListener("click", this._onClick, true)
21
+
22
+ if (this._attrManaged) this._syncClassesFromAttributes()
23
+
24
+ this._observer = new MutationObserver(() => {
25
+ this._attrManaged = true
26
+ this._syncClassesFromAttributes()
27
+ })
28
+ this._observer.observe(this.element, {
29
+ attributes: true,
30
+ attributeFilter: ["disabled", "aria-disabled"],
31
+ })
32
+ }
33
+
34
+ disconnect() {
35
+ this.element.removeEventListener("click", this._onClick, true)
36
+ this._observer?.disconnect()
37
+ delete this.element._pbButton
38
+ }
39
+
40
+ disable() { this.setDisabled(true) }
41
+ enable() { this.setDisabled(false) }
42
+
43
+ setDisabled(state) {
44
+ if (this._isButton()) {
45
+ state
46
+ ? this.element.setAttribute("disabled", "disabled")
47
+ : this.element.removeAttribute("disabled")
48
+ } else {
49
+ state
50
+ ? this.element.setAttribute("aria-disabled", "true")
51
+ : this.element.removeAttribute("aria-disabled")
52
+ }
53
+ this._attrManaged = true
54
+ this._applyClassState(state)
55
+ }
56
+
57
+ isDisabled() {
58
+ if (this._isButton()) {
59
+ if (this.element.hasAttribute("disabled")) return true
60
+ if (this._attrManaged && !this.element.hasAttribute("disabled")) return false
61
+ } else {
62
+ const aria = this.element.getAttribute("aria-disabled")
63
+ if (aria === "true") return true
64
+ if (this._attrManaged && aria !== "true") return false
65
+ }
66
+ return this.element.classList.contains("pb_button_disabled")
67
+ }
68
+
69
+ _isButton() {
70
+ return this.element.tagName === "BUTTON"
71
+ }
72
+
73
+ _attributesPresent() {
74
+ return this.element.hasAttribute("disabled") || this.element.hasAttribute("aria-disabled")
75
+ }
76
+
77
+ _syncClassesFromAttributes() {
78
+ const state = this._attrDisabledState()
79
+ const disabled = (state === null) ? false : state
80
+ this._applyClassState(disabled)
81
+ }
82
+
83
+ _attrDisabledState() {
84
+ if (this._isButton()) {
85
+ return this.element.hasAttribute("disabled") ? true : null
86
+ } else {
87
+ const aria = this.element.getAttribute("aria-disabled")
88
+ if (aria === "true") return true
89
+ if (aria === "false") return false
90
+ return this.element.hasAttribute("aria-disabled") ? false : null
91
+ }
92
+ }
93
+
94
+ _applyClassState(disabled) {
95
+ this.element.classList.toggle("pb_button_disabled", !!disabled)
96
+ this.element.classList.toggle("pb_button_enabled", !disabled)
97
+ }
98
+ }
99
+
@@ -10,9 +10,15 @@
10
10
  @import "./scss_partials/dropdown_animation";
11
11
  @import "dropdown_mixin";
12
12
 
13
- [class*="pb_dropdown"] {
13
+ .pb_dropdown_default,
14
+ .pb_dropdown_subtle,
15
+ .pb_dropdown_default_separators_hidden,
16
+ .pb_dropdown_subtle_separators_hidden {
14
17
  .dropdown_wrapper {
15
- [class*="dropdown_trigger_wrapper"] {
18
+ .dropdown_trigger_wrapper,
19
+ .dropdown_trigger_wrapper_focus,
20
+ .dropdown_trigger_wrapper_focus_select_only,
21
+ .dropdown_trigger_wrapper_select_only {
16
22
  @include pb_body;
17
23
  border: 1px solid $border_light;
18
24
  background-color: $white;
@@ -48,11 +54,11 @@
48
54
  transition: box-shadow 0.15s ease-in-out;
49
55
  }
50
56
 
51
- &[class*="_select_only"] {
57
+ &.dropdown_trigger_wrapper_select_only {
52
58
  box-shadow: inset 0 -11px 20px rgba($primary, 0.05);
53
59
  }
54
60
 
55
- &[class*="_focus"] {
61
+ &.dropdown_trigger_wrapper_focus {
56
62
  box-shadow: 0px 0px 0 1px $primary !important;
57
63
  transition: box-shadow 0.1s ease-in-out;
58
64
  }
@@ -69,7 +75,12 @@
69
75
  z-index: $z_1;
70
76
  width: 100%;
71
77
 
72
- [class*="pb_dropdown_option"] {
78
+ .pb_dropdown_option,
79
+ .pb_dropdown_option_list,
80
+ .pb_dropdown_option_selected,
81
+ .pb_dropdown_option_focused,
82
+ .pb_dropdown_option_list_focused,
83
+ .pb_dropdown_option_selected_focused {
73
84
  padding-left: $space_sm;
74
85
  padding-right: $space_sm;
75
86
  padding-top: $space_xs;
@@ -79,11 +90,14 @@
79
90
  background-color: $bg_light;
80
91
  }
81
92
 
82
- &[class*="_focused"] {
93
+ &.pb_dropdown_option_focused,
94
+ &.pb_dropdown_option_list_focused,
95
+ &.pb_dropdown_option_selected_focused {
83
96
  background-color: $bg_light;
84
97
  }
85
98
 
86
- &[class*="_list"] {
99
+ &.pb_dropdown_option_list,
100
+ &.pb_dropdown_option_list_focused {
87
101
  border-bottom: 1px solid $border_light;
88
102
 
89
103
  &:hover, &:focus {
@@ -92,7 +106,8 @@
92
106
  }
93
107
  }
94
108
  }
95
- &[class*="selected"] {
109
+ &.pb_dropdown_option_selected,
110
+ &.pb_dropdown_option_selected_focused {
96
111
  background-color: $primary;
97
112
  color: $white;
98
113
  [class^="pb_body"],
@@ -141,41 +156,66 @@
141
156
  }
142
157
 
143
158
  &.error {
144
- [class*=pb_body_kit] {
159
+ .pb_body_kit_negative {
145
160
  margin-top: $space_xs / 2;
146
161
  }
147
162
 
148
- [class*="dropdown_trigger_wrapper"] {
163
+ .dropdown_trigger_wrapper,
164
+ .dropdown_trigger_wrapper_focus,
165
+ .dropdown_trigger_wrapper_focus_select_only,
166
+ .dropdown_trigger_wrapper_select_only {
149
167
  border-color: $error;
150
168
  box-shadow: none !important;
151
169
  }
152
170
  }
153
171
  }
154
172
 
155
- &[class*="separators_hidden"] {
173
+ &.pb_dropdown_default_separators_hidden,
174
+ &.pb_dropdown_subtle_separators_hidden {
156
175
  .dropdown_wrapper {
157
176
  .pb_dropdown_container {
158
177
 
159
- [class*="pb_dropdown_option"] {
178
+ .pb_dropdown_option,
179
+ .pb_dropdown_option_list,
180
+ .pb_dropdown_option_selected,
181
+ .pb_dropdown_option_focused,
182
+ .pb_dropdown_option_list_focused,
183
+ .pb_dropdown_option_selected_focused {
160
184
  border: none;
161
185
  }
162
186
  }
163
187
  }
164
188
  }
165
189
 
166
- &[class*="subtle"] {
190
+ &.pb_dropdown_subtle,
191
+ &.pb_dropdown_subtle_separators_hidden {
167
192
  .dropdown_wrapper {
168
193
  .pb_dropdown_container {
169
194
 
170
- [class*="pb_dropdown_option"]:first-child {
195
+ .pb_dropdown_option:first-child,
196
+ .pb_dropdown_option_list:first-child,
197
+ .pb_dropdown_option_selected:first-child,
198
+ .pb_dropdown_option_focused:first-child,
199
+ .pb_dropdown_option_list_focused:first-child,
200
+ .pb_dropdown_option_selected_focused:first-child {
171
201
  margin-top: $space_xs;
172
202
  }
173
203
 
174
- [class*="pb_dropdown_option"]:last-child {
204
+ .pb_dropdown_option:last-child,
205
+ .pb_dropdown_option_list:last-child,
206
+ .pb_dropdown_option_selected:last-child,
207
+ .pb_dropdown_option_focused:last-child,
208
+ .pb_dropdown_option_list_focused:last-child,
209
+ .pb_dropdown_option_selected_focused:last-child {
175
210
  margin-bottom: $space_xs;
176
211
  }
177
212
 
178
- [class*="pb_dropdown_option"] {
213
+ .pb_dropdown_option,
214
+ .pb_dropdown_option_list,
215
+ .pb_dropdown_option_selected,
216
+ .pb_dropdown_option_focused,
217
+ .pb_dropdown_option_list_focused,
218
+ .pb_dropdown_option_selected_focused {
179
219
  margin: $space_xs;
180
220
  padding: $space_xs;
181
221
  border-radius: $border_radius_md;
@@ -193,24 +233,44 @@
193
233
  }
194
234
  }
195
235
 
196
- [class*="pb_dropdown_option"]:last-child::after {
236
+ .pb_dropdown_option:last-child::after,
237
+ .pb_dropdown_option_list:last-child::after,
238
+ .pb_dropdown_option_selected:last-child::after,
239
+ .pb_dropdown_option_focused:last-child::after,
240
+ .pb_dropdown_option_list_focused:last-child::after,
241
+ .pb_dropdown_option_selected_focused:last-child::after {
197
242
  display: none;
198
243
  }
199
244
  }
200
245
  }
201
246
 
202
- &[class*="separators_hidden"] {
247
+ &.pb_dropdown_subtle_separators_hidden {
203
248
  .dropdown_wrapper {
204
249
  .pb_dropdown_container {
205
- [class*="pb_dropdown_option"]:first-child {
250
+ .pb_dropdown_option:first-child,
251
+ .pb_dropdown_option_list:first-child,
252
+ .pb_dropdown_option_selected:first-child,
253
+ .pb_dropdown_option_focused:first-child,
254
+ .pb_dropdown_option_list_focused:first-child,
255
+ .pb_dropdown_option_selected_focused:first-child {
206
256
  margin-top: $space_xs;
207
257
  }
208
258
 
209
- [class*="pb_dropdown_option"]:last-child {
259
+ .pb_dropdown_option:last-child,
260
+ .pb_dropdown_option_list:last-child,
261
+ .pb_dropdown_option_selected:last-child,
262
+ .pb_dropdown_option_focused:last-child,
263
+ .pb_dropdown_option_list_focused:last-child,
264
+ .pb_dropdown_option_selected_focused:last-child {
210
265
  margin-bottom: $space_xs;
211
266
  }
212
267
 
213
- [class*="pb_dropdown_option"] {
268
+ .pb_dropdown_option,
269
+ .pb_dropdown_option_list,
270
+ .pb_dropdown_option_selected,
271
+ .pb_dropdown_option_focused,
272
+ .pb_dropdown_option_list_focused,
273
+ .pb_dropdown_option_selected_focused {
214
274
  padding: $space_xxs $space_xs;
215
275
  margin: $space_xxs $space_xs;
216
276
 
@@ -218,7 +278,8 @@
218
278
  height: 0px;
219
279
  }
220
280
 
221
- &[class*="selected"] {
281
+ &.pb_dropdown_option_selected,
282
+ &.pb_dropdown_option_selected_focused {
222
283
  border-bottom: none;
223
284
  }
224
285
  }
@@ -229,7 +290,10 @@
229
290
 
230
291
  &.dark {
231
292
  .dropdown_wrapper {
232
- [class*="dropdown_trigger_wrapper"] {
293
+ .dropdown_trigger_wrapper,
294
+ .dropdown_trigger_wrapper_focus,
295
+ .dropdown_trigger_wrapper_focus_select_only,
296
+ .dropdown_trigger_wrapper_select_only {
233
297
  @include pb_body_light_dark;
234
298
  background-color: rgba($white, 0.1) !important;
235
299
  background: none;
@@ -244,7 +308,7 @@
244
308
  [class^="pb_body"] {
245
309
  color: $white;
246
310
  }
247
- &[class*="_select_only"] {
311
+ &.dropdown_trigger_wrapper_select_only {
248
312
  box-shadow: inset 0 -11px 20px rgba($white, 0.05);
249
313
  }
250
314
  .dropdown_input {
@@ -254,7 +318,10 @@
254
318
  }
255
319
 
256
320
  &.error {
257
- [class*="dropdown_trigger_wrapper"] {
321
+ .dropdown_trigger_wrapper,
322
+ .dropdown_trigger_wrapper_focus,
323
+ .dropdown_trigger_wrapper_focus_select_only,
324
+ .dropdown_trigger_wrapper_select_only {
258
325
  border-color: $error_dark;
259
326
  }
260
327
  }
@@ -268,19 +335,28 @@
268
335
  color: $white !important;
269
336
  }
270
337
 
271
- [class*="pb_dropdown_option"] {
338
+ .pb_dropdown_option,
339
+ .pb_dropdown_option_list,
340
+ .pb_dropdown_option_selected,
341
+ .pb_dropdown_option_focused,
342
+ .pb_dropdown_option_list_focused,
343
+ .pb_dropdown_option_selected_focused {
272
344
  &:hover {
273
345
  background-color: $hover_dark;
274
346
  }
275
347
 
276
- &[class*="_focused"] {
348
+ &.pb_dropdown_option_focused,
349
+ &.pb_dropdown_option_list_focused,
350
+ &.pb_dropdown_option_selected_focused {
277
351
  background-color: $hover_dark;
278
352
  }
279
353
 
280
- &[class*="_list"] {
354
+ &.pb_dropdown_option_list,
355
+ &.pb_dropdown_option_list_focused {
281
356
  border-color: rgba($white, 0.15);
282
357
  }
283
- &[class*="selected"] {
358
+ &.pb_dropdown_option_selected,
359
+ &.pb_dropdown_option_selected_focused {
284
360
  background-color: $primary;
285
361
  border-bottom: rgba($white, 0.15);
286
362
  }
@@ -90,7 +90,7 @@
90
90
  <%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
91
91
  <%= form.typeahead :example_typeahead_validation, props: { data: { typeahead_example2: true, user: {} }, label: true, placeholder: "Search for a user", required: true, validation: { message: "Please select a user." } } %>
92
92
  <%= form.text_field :example_text_field_validation, props: { label: true, required: true } %>
93
- <%= form.phone_number_field :example_phone_number_field_validation, props: { label: "Example phone field", hidden_inputs: true, required: true } %>
93
+ <%= form.phone_number_field :example_phone_number_field_validation, props: { label: "Example phone field", hidden_inputs: true } %>
94
94
  <%= form.email_field :example_email_field_validation, props: { label: true, required: true } %>
95
95
  <%= form.number_field :example_number_field_validation, props: { label: true, required: true } %>
96
96
  <%= form.search_field :example_project_number_validation, props: { label: true, required: true, validation: { pattern: "[0-9]{2}-[0-9]{5}", message: "Please enter a valid project number (example: 33-12345)." } } %>
@@ -2,14 +2,12 @@ import PbEnhancedElement from '../pb_enhanced_element'
2
2
  import { debounce } from '../utilities/object'
3
3
 
4
4
  // Kit selectors
5
- const KIT_SELECTOR = '[class^="pb_"][class*="_kit"]'
6
- const ERROR_MESSAGE_SELECTOR = '.pb_body_kit_negative'
7
- const PHONE_NUMBER_INPUT_SELECTOR = '.pb_phone_number_input'
5
+ const KIT_SELECTOR = '[class^="pb_"][class*="_kit"]'
6
+ const ERROR_MESSAGE_SELECTOR = '.pb_body_kit_negative'
8
7
 
9
8
  // Validation selectors
10
- const FORM_SELECTOR = 'form[data-pb-form-validation="true"]'
11
- const REQUIRED_FIELDS_SELECTOR = 'input[required],textarea[required],select[required]'
12
- const PHONE_NUMBER_VALIDATION_ERROR_SELECTOR = '[data-pb-phone-validation-error="true"]'
9
+ const FORM_SELECTOR = 'form[data-pb-form-validation="true"]'
10
+ const REQUIRED_FIELDS_SELECTOR = 'input[required],textarea[required],select[required]'
13
11
 
14
12
  const FIELD_EVENTS = [
15
13
  'change',
@@ -30,14 +28,6 @@ class PbFormValidation extends PbEnhancedElement {
30
28
  }, 250), false)
31
29
  })
32
30
  })
33
-
34
- // Add event listener to check for phone number validation errors
35
- this.element.addEventListener('submit', (event) => {
36
- if (this.hasPhoneNumberValidationErrors()) {
37
- event.preventDefault()
38
- return false
39
- }
40
- })
41
31
  }
42
32
 
43
33
  validateFormField(event) {
@@ -55,18 +45,10 @@ class PbFormValidation extends PbEnhancedElement {
55
45
 
56
46
  showValidationMessage(target) {
57
47
  const { parentElement } = target
58
- const kitElement = parentElement.closest(KIT_SELECTOR)
59
-
60
- // Skip error message container for Phone Number Input as it handles its own errors
61
- // as the closest kitElement is "pb_text_input_kit mb_sm" for Phone Number Input,
62
- // we target the parent element of kitElement to check
63
- if (kitElement && kitElement.parentElement.matches(PHONE_NUMBER_INPUT_SELECTOR)) {
64
- return
65
- }
66
48
 
67
49
  // ensure clean error message state
68
50
  this.clearError(target)
69
- kitElement.classList.add('error')
51
+ parentElement.closest(KIT_SELECTOR).classList.add('error')
70
52
 
71
53
  // set the error message element
72
54
  const errorMessageContainer = this.errorMessageContainer
@@ -81,23 +63,9 @@ class PbFormValidation extends PbEnhancedElement {
81
63
 
82
64
  clearError(target) {
83
65
  const { parentElement } = target
84
- const kitElement = parentElement.closest(KIT_SELECTOR)
85
-
86
- if (kitElement) {
87
- kitElement.classList.remove('error')
88
-
89
- // Only remove error message container for non-Phone Number Input kits
90
- if (!kitElement.matches(PHONE_NUMBER_INPUT_SELECTOR)) {
91
- const errorMessageContainer = parentElement.querySelector(ERROR_MESSAGE_SELECTOR)
92
- if (errorMessageContainer) errorMessageContainer.remove()
93
- }
94
- }
95
- }
96
-
97
- // Check if there are phone number input errors
98
- hasPhoneNumberValidationErrors() {
99
- const phoneNumberErrors = this.element.querySelectorAll(PHONE_NUMBER_VALIDATION_ERROR_SELECTOR)
100
- return phoneNumberErrors.length > 0
66
+ parentElement.closest(KIT_SELECTOR).classList.remove('error')
67
+ const errorMessageContainer = parentElement.querySelector(ERROR_MESSAGE_SELECTOR)
68
+ if (errorMessageContainer) errorMessageContainer.remove()
101
69
  }
102
70
 
103
71
  get errorMessageContainer() {
@@ -110,35 +110,18 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
110
110
 
111
111
  const inputRef = useRef<HTMLInputElement | null>(null)
112
112
  const itiRef = useRef<any>(null);
113
- const wrapperRef = useRef<HTMLDivElement | null>(null); // Add wrapper ref
114
113
  const [inputValue, setInputValue] = useState(value)
115
114
  const [error, setError] = useState(props.error)
116
115
  const [dropDownIsOpen, setDropDownIsOpen] = useState(false)
117
116
  const [selectedData, setSelectedData] = useState()
118
117
  const [hasTyped, setHasTyped] = useState(false)
119
118
 
120
- // Function to update validation state on the wrapper element
121
- // Only applies when input is required
122
- const updateValidationState = (hasError: boolean) => {
123
- if (wrapperRef.current && required) {
124
- if (hasError) {
125
- wrapperRef.current.setAttribute('data-pb-phone-validation-error', 'true')
126
- } else {
127
- wrapperRef.current.removeAttribute('data-pb-phone-validation-error')
128
- }
129
- }
130
- }
131
-
132
119
  useEffect(() => {
133
- const hasError = (error ?? '').length > 0
134
- if (hasError) {
120
+ if ((error ?? '').length > 0) {
135
121
  onValidate(false)
136
122
  } else {
137
123
  onValidate(true)
138
124
  }
139
-
140
- // Update validation state whenever error changes
141
- updateValidationState(hasError)
142
125
  }, [error, onValidate])
143
126
 
144
127
  /*
@@ -152,10 +135,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
152
135
  setInputValue("")
153
136
  setError("")
154
137
  setHasTyped(false)
155
- // Only clear validation state if field was required
156
- if (required) {
157
- updateValidationState(false)
158
- }
159
138
  },
160
139
  inputNode() {
161
140
  return inputRef.current
@@ -185,13 +164,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
185
164
 
186
165
  const validateTooShortNumber = (itiInit: any) => {
187
166
  if (!itiInit) return
188
-
189
- // If field is empty, don't show "too short" error
190
- if (!inputValue || inputValue.trim() === '') {
191
- setError('')
192
- return false
193
- }
194
-
195
167
  if (itiInit.getValidationError() === ValidationError.TooShort) {
196
168
  return showFormattedError('too short')
197
169
  } else {
@@ -240,26 +212,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
240
212
  }
241
213
  }
242
214
 
243
- // Validation for required empty fields
244
- const validateRequiredField = () => {
245
- if (required && (!inputValue || inputValue.trim() === '')) {
246
- setError('Missing phone number')
247
- return true
248
- }
249
- return false
250
- }
251
215
 
252
216
  const validateErrors = () => {
253
- // If field is empty, only show required field error if applicable
254
- if (!inputValue || inputValue.trim() === '') {
255
- if (validateRequiredField()) return
256
- // Clear any existing errors if field is empty and not required
257
- if (!required) {
258
- setError('')
259
- }
260
- return
261
- }
262
-
263
217
  if (!hasTyped && !error) return
264
218
 
265
219
  if (itiRef.current) isValid(itiRef.current.isValidNumber())
@@ -356,10 +310,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
356
310
  value: inputValue
357
311
  }
358
312
 
359
- let wrapperProps: Record<string, unknown> = {
360
- className: classes,
361
- ref: wrapperRef // Add ref to wrapper
362
- }
313
+ let wrapperProps: Record<string, unknown> = { className: classes }
363
314
 
364
315
  if (!isEmpty(aria)) textInputProps = {...textInputProps, ...ariaProps}
365
316
  if (!isEmpty(data)) wrapperProps = {...wrapperProps, ...dataProps}