playbook_ui 15.1.0.pre.alpha.PLAY2468phonenuminputvalidation10803 → 15.1.0.pre.alpha.iconstatvaluescss10956

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled.html.erb +31 -0
  3. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled.md +7 -0
  4. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled_helper.html.erb +21 -0
  5. data/app/pb_kits/playbook/pb_button/docs/_button_managed_disabled_helper.md +7 -0
  6. data/app/pb_kits/playbook/pb_button/docs/example.yml +2 -0
  7. data/app/pb_kits/playbook/pb_button/index.js +99 -0
  8. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -1
  9. data/app/pb_kits/playbook/pb_form/pb_form_validation.js +8 -40
  10. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +2 -2
  11. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.scss +15 -21
  12. data/app/pb_kits/playbook/pb_icon_stat_value/_icon_stat_value.tsx +6 -5
  13. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.html.erb +2 -0
  14. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.rb +11 -3
  15. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +9 -8
  16. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +2 -51
  17. data/dist/chunks/{_line_graph-Bkn-wx30.js → _line_graph-C9stNsP3.js} +1 -1
  18. data/dist/chunks/{_typeahead-DkRYiut7.js → _typeahead-D3MtsWXG.js} +1 -1
  19. data/dist/chunks/{_weekday_stacked-BUjWQnqn.js → _weekday_stacked-BkTDqn-r.js} +2 -2
  20. data/dist/chunks/pb_form_validation-CleM960_.js +1 -0
  21. data/dist/chunks/vendor.js +1 -1
  22. data/dist/menu.yml +1 -1
  23. data/dist/playbook-doc.js +1 -1
  24. data/dist/playbook-rails-react-bindings.js +1 -1
  25. data/dist/playbook-rails.js +1 -1
  26. data/dist/playbook.css +1 -1
  27. data/lib/playbook/version.rb +1 -1
  28. metadata +11 -6
  29. data/dist/chunks/pb_form_validation-B4uRmBwC.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1607dd2475fc082a109f3ad1d2dc03b07887fba69f23a5754d96020c18e75397
4
- data.tar.gz: 3b597c713dd113e61049aea67c57d0e30e2c33a8c144e2f0611cd053c3fa1406
3
+ metadata.gz: 023dae1c06846305a2de70d79d36fac8bb6e685e9eed4da1157a84559d3749c6
4
+ data.tar.gz: f8154d1b04e55366e85ddf6f2a21d2e465d49ba40d6a456ddb43450307930e91
5
5
  SHA512:
6
- metadata.gz: 89b69260b005e8a057fe6ada81c6c09706ad2dd938d1a1ea3403a5b8e36c5b50802f7c8976312429b14e2a9cc4c881d148f46e2567593f8a9db801d994a0c231
7
- data.tar.gz: 6121137545315510e02d3cda537276fb12b196e93cb3032542a6dd4c84a81ca612ecd181304d52710c2b8eaf07ce8238daf8f4cbdb64f9e39b257235178bd132
6
+ metadata.gz: d7fa8e2b752601706f4aa07fc61cb6c08280c21c315faf666ef054eac38a01e6e14e17fe5015de1d6c3734ba0fae3039b01223ab85a32a305166ca0bd06983e7
7
+ data.tar.gz: f61864e43078b05767ba7fc2335881b00ee99799b8731ca982e00a43fc952c5b085b5712626d66b410548f5b6e83bbaf200b2343bf6ef4f7aff8ee94b046e76d
@@ -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
+
@@ -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() {
@@ -3,7 +3,7 @@ import React from 'react'
3
3
  import classnames from 'classnames'
4
4
 
5
5
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
6
- import { globalProps } from '../utilities/globalProps'
6
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
7
7
 
8
8
  import Icon from '../pb_icon/_icon'
9
9
 
@@ -26,7 +26,7 @@ type IconCircleProps = {
26
26
  | "orange"
27
27
  | "green"
28
28
  | "lighter",
29
- }
29
+ } & GlobalProps
30
30
 
31
31
  const IconCircle = (props: IconCircleProps) => {
32
32
  const {
@@ -3,51 +3,45 @@
3
3
  @import "../tokens/spacing";
4
4
  @import "../pb_icon_circle/icon_circle";
5
5
 
6
- [class^=pb_icon_stat_value_kit]{
6
+ .pb_icon_stat_value_kit_horizontal,
7
+ .pb_icon_stat_value_kit_vertical
8
+ {
7
9
  display: flex;
8
10
  align-items: baseline;
9
11
 
10
- &[class*=_vertical] {
12
+ &.pb_icon_stat_value_kit_vertical {
11
13
  flex-direction: column;
12
14
 
13
- &[class*=_center] {
15
+ &.text_align_center {
14
16
  align-items: center;
15
17
 
16
- [class^=pb_title],
17
- [class^=pb_body],
18
- [class^=pb_caption] {
18
+ .pb_title_kit,
19
+ .pb_body_kit,
20
+ .pb_caption_kit_md {
19
21
  text-align: center;
20
22
  }
21
23
  }
22
24
 
23
- &[class*=_right] {
25
+ &.text_align_right {
24
26
  align-items: flex-end;
25
27
 
26
- [class^=pb_title],
27
- [class^=pb_body],
28
- [class^=pb_caption] {
28
+ .pb_title_kit,
29
+ .pb_body_kit,
30
+ .pb_caption_kit_md {
29
31
  text-align: right;
30
32
  }
31
33
  }
32
-
33
- [class^=pb_icon_circle] {
34
- margin-bottom: $space-xs;
35
- }
36
34
  }
37
35
 
38
- &[class*=_horizontal] {
36
+ &.pb_icon_stat_value_kit_horizontal {
39
37
  align-items: center;
40
38
 
41
- &[class*=_center] {
39
+ &.text_align_center {
42
40
  justify-content: center;
43
41
  }
44
42
 
45
- &[class*=_right] {
43
+ &.text_align_right {
46
44
  justify-content: flex-end;
47
45
  }
48
-
49
- [class^=pb_icon_circle] {
50
- margin-right: $space-sm;
51
- }
52
46
  }
53
47
  }
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import classnames from 'classnames'
3
3
 
4
4
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
5
- import { globalProps } from '../utilities/globalProps'
5
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
6
6
 
7
7
  import Body from '../pb_body/_body'
8
8
  import Caption from '../pb_caption/_caption'
@@ -33,8 +33,7 @@ type IconStatValueProps = {
33
33
  | "yellow"
34
34
  | "orange"
35
35
  | "green"
36
- | "lighter",
37
- }
36
+ } & GlobalProps
38
37
 
39
38
  const IconStatValue = (props: IconStatValueProps): React.ReactElement => {
40
39
  const {
@@ -50,13 +49,13 @@ const IconStatValue = (props: IconStatValueProps): React.ReactElement => {
50
49
  text = '',
51
50
  unit = '',
52
51
  value = 0,
53
- variant = 'lighter',
52
+ variant = 'default',
54
53
  } = props
55
54
  const ariaProps = buildAriaProps(aria)
56
55
  const dataProps = buildDataProps(data)
57
56
  const htmlProps = buildHtmlProps(htmlOptions)
58
57
  const classes = classnames(
59
- buildCss('pb_icon_stat_value_kit', orientation, size, variant), globalProps(props),
58
+ buildCss('pb_icon_stat_value_kit', orientation), globalProps(props),
60
59
  className
61
60
  )
62
61
  const titleSize = function(size: "sm" | "md" | "lg") {
@@ -101,6 +100,8 @@ const IconStatValue = (props: IconStatValueProps): React.ReactElement => {
101
100
  <IconCircle
102
101
  dark={dark}
103
102
  icon={icon}
103
+ marginBottom={orientation == 'vertical' ? 'xs' : undefined}
104
+ marginRight={orientation == 'horizontal' ? 'sm' : undefined}
104
105
  size={size}
105
106
  variant={variant}
106
107
  />
@@ -3,6 +3,8 @@
3
3
  <%= pb_rails("icon_circle", props: {
4
4
  dark: object.dark,
5
5
  icon: object.icon,
6
+ margin_right: object.icon_margin_right,
7
+ margin_bottom: object.icon_margin_bottom,
6
8
  size: object.size,
7
9
  variant: object.variant }) %>
8
10
 
@@ -9,8 +9,8 @@ module Playbook
9
9
  values: %w[sm md lg],
10
10
  default: "sm"
11
11
  prop :variant, type: Playbook::Props::Enum,
12
- values: %w[default royal blue purple teal red yellow green orange lighter],
13
- default: "lighter"
12
+ values: %w[default royal blue purple teal red yellow green orange],
13
+ default: "default"
14
14
 
15
15
  prop :orientation, type: Playbook::Props::Enum,
16
16
  values: %w[vertical horizontal],
@@ -25,7 +25,7 @@ module Playbook
25
25
  prop :value
26
26
 
27
27
  def classname
28
- generate_classname("pb_icon_stat_value_kit", orientation, size, variant)
28
+ generate_classname("pb_icon_stat_value_kit", orientation)
29
29
  end
30
30
 
31
31
  def value_string
@@ -41,6 +41,14 @@ module Playbook
41
41
  3
42
42
  end
43
43
  end
44
+
45
+ def icon_margin_right
46
+ orientation === "horizontal" && "sm"
47
+ end
48
+
49
+ def icon_margin_bottom
50
+ orientation === "vertical" && "xs"
51
+ end
44
52
  end
45
53
  end
46
54
  end
@@ -18,7 +18,7 @@ describe("IconStatValue Kit", () => {
18
18
  )
19
19
 
20
20
  const kit = screen.getByTestId(testId)
21
- expect(kit).toHaveClass("pb_icon_stat_value_kit_horizontal_sm_lighter")
21
+ expect(kit).toHaveClass("pb_icon_stat_value_kit_horizontal")
22
22
  })
23
23
 
24
24
  test("renders icon", () => {
@@ -99,9 +99,10 @@ describe("IconStatValue Kit", () => {
99
99
  value={64.18}
100
100
  />
101
101
  )
102
-
102
+ const size = sizeProp === "sm" ? "3" : sizeProp === "md" ? "2" : "1"
103
103
  const kit = screen.getByTestId(testId)
104
- expect(kit).toHaveClass(`pb_icon_stat_value_kit_horizontal_${sizeProp}_lighter`)
104
+ const title = kit.querySelector(".pb_title_kit")
105
+ expect(title).toHaveClass(`pb_title_${size}`)
105
106
 
106
107
  cleanup()
107
108
  })
@@ -115,8 +116,7 @@ describe("IconStatValue Kit", () => {
115
116
  "teal",
116
117
  "red",
117
118
  "yellow",
118
- "green",
119
- "lighter"].forEach(
119
+ "green"].forEach(
120
120
  (colorProp) => {
121
121
  render(
122
122
  <IconStatValue
@@ -128,9 +128,10 @@ describe("IconStatValue Kit", () => {
128
128
  variant={colorProp}
129
129
  />
130
130
  )
131
-
131
+
132
132
  const kit = screen.getByTestId(testId)
133
- expect(kit).toHaveClass(`pb_icon_stat_value_kit_horizontal_sm_${colorProp}`)
133
+ const iconCircle = kit.querySelector(`.pb_icon_circle_kit_size_sm_${colorProp}`)
134
+ expect(iconCircle).toBeInTheDocument()
134
135
 
135
136
  cleanup()
136
137
  })
@@ -149,7 +150,7 @@ describe("IconStatValue Kit", () => {
149
150
  )
150
151
 
151
152
  const kit = screen.getByTestId(testId)
152
- expect(kit).toHaveClass("pb_icon_stat_value_kit_vertical_sm_lighter")
153
+ expect(kit).toHaveClass("pb_icon_stat_value_kit_vertical")
153
154
  })
154
155
 
155
156
  })
@@ -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}