@wordpress/components 30.2.1-next.0f6f9d12c.0 → 30.2.1-next.f34ab90e9.0

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 (133) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/build/menu-item/index.js +1 -0
  3. package/build/menu-item/index.js.map +1 -1
  4. package/build/validated-form-controls/components/checkbox-control.js +5 -3
  5. package/build/validated-form-controls/components/checkbox-control.js.map +1 -1
  6. package/build/validated-form-controls/components/combobox-control.js +5 -3
  7. package/build/validated-form-controls/components/combobox-control.js.map +1 -1
  8. package/build/validated-form-controls/components/custom-select-control.js +5 -3
  9. package/build/validated-form-controls/components/custom-select-control.js.map +1 -1
  10. package/build/validated-form-controls/components/input-control.js +5 -3
  11. package/build/validated-form-controls/components/input-control.js.map +1 -1
  12. package/build/validated-form-controls/components/number-control.js +5 -3
  13. package/build/validated-form-controls/components/number-control.js.map +1 -1
  14. package/build/validated-form-controls/components/radio-control.js +5 -3
  15. package/build/validated-form-controls/components/radio-control.js.map +1 -1
  16. package/build/validated-form-controls/components/range-control.js +5 -3
  17. package/build/validated-form-controls/components/range-control.js.map +1 -1
  18. package/build/validated-form-controls/components/select-control.js +5 -3
  19. package/build/validated-form-controls/components/select-control.js.map +1 -1
  20. package/build/validated-form-controls/components/text-control.js +5 -3
  21. package/build/validated-form-controls/components/text-control.js.map +1 -1
  22. package/build/validated-form-controls/components/textarea-control.js +5 -3
  23. package/build/validated-form-controls/components/textarea-control.js.map +1 -1
  24. package/build/validated-form-controls/components/toggle-control.js +5 -3
  25. package/build/validated-form-controls/components/toggle-control.js.map +1 -1
  26. package/build/validated-form-controls/components/toggle-group-control.js +5 -3
  27. package/build/validated-form-controls/components/toggle-group-control.js.map +1 -1
  28. package/build/validated-form-controls/components/types.js.map +1 -1
  29. package/build/validated-form-controls/control-with-error.js +57 -22
  30. package/build/validated-form-controls/control-with-error.js.map +1 -1
  31. package/build/validated-form-controls/validity-indicator.js +45 -0
  32. package/build/validated-form-controls/validity-indicator.js.map +1 -0
  33. package/build-module/menu-item/index.js +1 -0
  34. package/build-module/menu-item/index.js.map +1 -1
  35. package/build-module/validated-form-controls/components/checkbox-control.js +5 -3
  36. package/build-module/validated-form-controls/components/checkbox-control.js.map +1 -1
  37. package/build-module/validated-form-controls/components/combobox-control.js +5 -3
  38. package/build-module/validated-form-controls/components/combobox-control.js.map +1 -1
  39. package/build-module/validated-form-controls/components/custom-select-control.js +5 -3
  40. package/build-module/validated-form-controls/components/custom-select-control.js.map +1 -1
  41. package/build-module/validated-form-controls/components/input-control.js +5 -3
  42. package/build-module/validated-form-controls/components/input-control.js.map +1 -1
  43. package/build-module/validated-form-controls/components/number-control.js +5 -3
  44. package/build-module/validated-form-controls/components/number-control.js.map +1 -1
  45. package/build-module/validated-form-controls/components/radio-control.js +5 -3
  46. package/build-module/validated-form-controls/components/radio-control.js.map +1 -1
  47. package/build-module/validated-form-controls/components/range-control.js +5 -3
  48. package/build-module/validated-form-controls/components/range-control.js.map +1 -1
  49. package/build-module/validated-form-controls/components/select-control.js +5 -3
  50. package/build-module/validated-form-controls/components/select-control.js.map +1 -1
  51. package/build-module/validated-form-controls/components/text-control.js +5 -3
  52. package/build-module/validated-form-controls/components/text-control.js.map +1 -1
  53. package/build-module/validated-form-controls/components/textarea-control.js +5 -3
  54. package/build-module/validated-form-controls/components/textarea-control.js.map +1 -1
  55. package/build-module/validated-form-controls/components/toggle-control.js +5 -3
  56. package/build-module/validated-form-controls/components/toggle-control.js.map +1 -1
  57. package/build-module/validated-form-controls/components/toggle-group-control.js +5 -3
  58. package/build-module/validated-form-controls/components/toggle-group-control.js.map +1 -1
  59. package/build-module/validated-form-controls/components/types.js.map +1 -1
  60. package/build-module/validated-form-controls/control-with-error.js +57 -21
  61. package/build-module/validated-form-controls/control-with-error.js.map +1 -1
  62. package/build-module/validated-form-controls/validity-indicator.js +37 -0
  63. package/build-module/validated-form-controls/validity-indicator.js.map +1 -0
  64. package/build-style/style-rtl.css +34 -22
  65. package/build-style/style.css +34 -22
  66. package/build-types/menu-item/index.d.ts.map +1 -1
  67. package/build-types/validated-form-controls/components/checkbox-control.d.ts.map +1 -1
  68. package/build-types/validated-form-controls/components/combobox-control.d.ts.map +1 -1
  69. package/build-types/validated-form-controls/components/custom-select-control.d.ts.map +1 -1
  70. package/build-types/validated-form-controls/components/input-control.d.ts.map +1 -1
  71. package/build-types/validated-form-controls/components/number-control.d.ts.map +1 -1
  72. package/build-types/validated-form-controls/components/radio-control.d.ts.map +1 -1
  73. package/build-types/validated-form-controls/components/range-control.d.ts.map +1 -1
  74. package/build-types/validated-form-controls/components/select-control.d.ts.map +1 -1
  75. package/build-types/validated-form-controls/components/stories/checkbox-control.story.d.ts.map +1 -1
  76. package/build-types/validated-form-controls/components/stories/combobox-control.story.d.ts.map +1 -1
  77. package/build-types/validated-form-controls/components/stories/custom-select-control.story.d.ts.map +1 -1
  78. package/build-types/validated-form-controls/components/stories/input-control.story.d.ts.map +1 -1
  79. package/build-types/validated-form-controls/components/stories/number-control.story.d.ts.map +1 -1
  80. package/build-types/validated-form-controls/components/stories/overview.story.d.ts +13 -0
  81. package/build-types/validated-form-controls/components/stories/overview.story.d.ts.map +1 -1
  82. package/build-types/validated-form-controls/components/stories/radio-control.story.d.ts.map +1 -1
  83. package/build-types/validated-form-controls/components/stories/range-control.story.d.ts.map +1 -1
  84. package/build-types/validated-form-controls/components/stories/select-control.story.d.ts.map +1 -1
  85. package/build-types/validated-form-controls/components/stories/text-control.story.d.ts.map +1 -1
  86. package/build-types/validated-form-controls/components/stories/textarea-control.story.d.ts.map +1 -1
  87. package/build-types/validated-form-controls/components/stories/toggle-control.story.d.ts.map +1 -1
  88. package/build-types/validated-form-controls/components/stories/toggle-group-control.story.d.ts.map +1 -1
  89. package/build-types/validated-form-controls/components/text-control.d.ts.map +1 -1
  90. package/build-types/validated-form-controls/components/textarea-control.d.ts.map +1 -1
  91. package/build-types/validated-form-controls/components/toggle-control.d.ts.map +1 -1
  92. package/build-types/validated-form-controls/components/toggle-group-control.d.ts.map +1 -1
  93. package/build-types/validated-form-controls/components/types.d.ts +21 -10
  94. package/build-types/validated-form-controls/components/types.d.ts.map +1 -1
  95. package/build-types/validated-form-controls/control-with-error.d.ts +4 -5
  96. package/build-types/validated-form-controls/control-with-error.d.ts.map +1 -1
  97. package/build-types/validated-form-controls/validity-indicator.d.ts +5 -0
  98. package/build-types/validated-form-controls/validity-indicator.d.ts.map +1 -0
  99. package/package.json +19 -19
  100. package/src/calendar/style.scss +22 -22
  101. package/src/menu-item/index.tsx +1 -0
  102. package/src/utils/theme-variables.scss +1 -0
  103. package/src/validated-form-controls/components/checkbox-control.tsx +5 -3
  104. package/src/validated-form-controls/components/combobox-control.tsx +5 -3
  105. package/src/validated-form-controls/components/custom-select-control.tsx +5 -3
  106. package/src/validated-form-controls/components/input-control.tsx +5 -3
  107. package/src/validated-form-controls/components/number-control.tsx +5 -3
  108. package/src/validated-form-controls/components/radio-control.tsx +5 -3
  109. package/src/validated-form-controls/components/range-control.tsx +5 -3
  110. package/src/validated-form-controls/components/select-control.tsx +5 -3
  111. package/src/validated-form-controls/components/stories/checkbox-control.story.tsx +17 -6
  112. package/src/validated-form-controls/components/stories/combobox-control.story.tsx +17 -6
  113. package/src/validated-form-controls/components/stories/custom-select-control.story.tsx +17 -6
  114. package/src/validated-form-controls/components/stories/input-control.story.tsx +51 -18
  115. package/src/validated-form-controls/components/stories/number-control.story.tsx +17 -6
  116. package/src/validated-form-controls/components/stories/overview.mdx +1 -1
  117. package/src/validated-form-controls/components/stories/overview.story.tsx +122 -14
  118. package/src/validated-form-controls/components/stories/radio-control.story.tsx +17 -6
  119. package/src/validated-form-controls/components/stories/range-control.story.tsx +17 -6
  120. package/src/validated-form-controls/components/stories/select-control.story.tsx +17 -6
  121. package/src/validated-form-controls/components/stories/text-control.story.tsx +17 -6
  122. package/src/validated-form-controls/components/stories/textarea-control.story.tsx +17 -6
  123. package/src/validated-form-controls/components/stories/toggle-control.story.tsx +17 -6
  124. package/src/validated-form-controls/components/stories/toggle-group-control.story.tsx +17 -6
  125. package/src/validated-form-controls/components/text-control.tsx +5 -3
  126. package/src/validated-form-controls/components/textarea-control.tsx +5 -3
  127. package/src/validated-form-controls/components/toggle-control.tsx +5 -3
  128. package/src/validated-form-controls/components/toggle-group-control.tsx +5 -3
  129. package/src/validated-form-controls/components/types.ts +21 -12
  130. package/src/validated-form-controls/control-with-error.tsx +77 -26
  131. package/src/validated-form-controls/style.scss +19 -5
  132. package/src/validated-form-controls/validity-indicator.tsx +48 -0
  133. package/tsconfig.tsbuildinfo +1 -1
@@ -1,9 +1,9 @@
1
1
  /* Root of the component. */
2
2
  // Internal variables
3
3
  $wp-components-calendar-outline-focus: var(--wp-admin-border-width-focus) solid $components-color-accent;
4
- $wp-components-calendar-button-height: 2rem;
5
- $wp-components-calendar-button-width: 2rem;
6
- $wp-components-calendar-nav-height: 2rem;
4
+ $wp-components-calendar-button-height: $grid-unit-40;
5
+ $wp-components-calendar-button-width: $grid-unit-40;
6
+ $wp-components-calendar-nav-height: $grid-unit-40;
7
7
  $wp-components-calendar-range-middle-background-color: color-mix(in srgb, $components-color-accent 4%, transparent);
8
8
  $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-color-accent 16%, transparent);
9
9
 
@@ -13,10 +13,10 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
13
13
  position: relative; /* Required to position the navigation toolbar. */
14
14
  box-sizing: border-box;
15
15
  display: inline flow-root;
16
- color: $gray-900;
17
- background-color: $white;
18
- font-size: 13px;
19
- font-weight: 400;
16
+ color: $components-color-foreground;
17
+ background-color: $components-color-background;
18
+ font-size: $font-size-medium;
19
+ font-weight: $font-weight-regular;
20
20
  z-index: 0; // Create a stacking context and render on top of the background.
21
21
 
22
22
  *,
@@ -35,7 +35,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
35
35
  // date follows the same color as the button's text, since the button
36
36
  // inherits its text color.
37
37
  &:has(.components-calendar__day-button:disabled) {
38
- color: $gray-600;
38
+ color: $components-color-disabled;
39
39
  }
40
40
  &:has(.components-calendar__day-button:hover:not(:disabled)),
41
41
  &:has(.components-calendar__day-button:focus-visible) {
@@ -57,7 +57,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
57
57
  height: $wp-components-calendar-button-height;
58
58
 
59
59
  border: none;
60
- border-radius: 2px;
60
+ border-radius: $radius-small;
61
61
 
62
62
  font: inherit;
63
63
  font-variant-numeric: tabular-nums;
@@ -73,7 +73,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
73
73
  z-index: -1;
74
74
  inset: 0;
75
75
  border: none; // No default border to avoid polluting high-contrast mode.
76
- border-radius: 2px;
76
+ border-radius: $radius-small;
77
77
  }
78
78
 
79
79
  // Use the button's ::after to show the selection preview.
@@ -117,7 +117,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
117
117
  .components-calendar__button-next,
118
118
  .components-calendar__button-previous {
119
119
  border: none;
120
- border-radius: 2px;
120
+ border-radius: $radius-small;
121
121
  background: none;
122
122
  padding: 0;
123
123
  margin: 0;
@@ -139,7 +139,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
139
139
  &[aria-disabled="true"] {
140
140
  cursor: revert;
141
141
 
142
- color: $gray-600;
142
+ color: $components-color-disabled;
143
143
  }
144
144
 
145
145
  &:focus-visible {
@@ -150,8 +150,8 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
150
150
  .components-calendar__chevron {
151
151
  display: inline-block;
152
152
  fill: currentColor;
153
- width: 16px;
154
- height: 16px;
153
+ width: $grid-unit-20;
154
+ height: $grid-unit-20;
155
155
  }
156
156
 
157
157
  .components-calendar[dir="rtl"]
@@ -167,7 +167,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
167
167
  align-content: center;
168
168
 
169
169
  height: $wp-components-calendar-nav-height;
170
- margin-bottom: 12px;
170
+ margin-bottom: $grid-unit-15;
171
171
  }
172
172
 
173
173
  .components-calendar__months {
@@ -175,13 +175,13 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
175
175
  display: flex;
176
176
  justify-content: center;
177
177
  flex-wrap: wrap;
178
- gap: 1rem;
178
+ gap: $grid-unit-20;
179
179
  max-width: fit-content;
180
180
  }
181
181
 
182
182
  .components-calendar__month-grid {
183
183
  border-collapse: separate;
184
- border-spacing: 0 4px;
184
+ border-spacing: 0 $grid-unit-05;
185
185
  }
186
186
 
187
187
  .components-calendar__nav {
@@ -202,7 +202,7 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
202
202
  height: $wp-components-calendar-button-height;
203
203
  padding: 0;
204
204
 
205
- color: $gray-700;
205
+ color: $components-color-gray-700;
206
206
  text-align: center;
207
207
  text-transform: uppercase;
208
208
  }
@@ -227,12 +227,12 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
227
227
  .components-calendar__day-button,
228
228
  .components-calendar__day-button:hover:not(:disabled)
229
229
  ) {
230
- color: $white;
230
+ color: $components-color-foreground-inverted;
231
231
  }
232
232
 
233
233
  .components-calendar__day-button {
234
234
  &::before {
235
- background-color: $gray-900;
235
+ background-color: $components-color-foreground;
236
236
  // Render a transparent border to highlight the selected day in
237
237
  // forced-colors (high-contrast) mode, since the background is not
238
238
  // visible.
@@ -240,11 +240,11 @@ $wp-components-calendar-preview-border-color: color-mix(in srgb, $components-col
240
240
  }
241
241
 
242
242
  &:disabled::before {
243
- background-color: $gray-600;
243
+ background-color: $components-color-disabled;
244
244
  }
245
245
 
246
246
  &:hover:not(:disabled)::before {
247
- background-color: $gray-800;
247
+ background-color: $components-color-gray-800;
248
248
  }
249
249
  }
250
250
  }
@@ -67,6 +67,7 @@ function UnforwardedMenuItem(
67
67
  role={ role }
68
68
  icon={ iconPosition === 'left' ? icon : undefined }
69
69
  className={ className }
70
+ accessibleWhenDisabled
70
71
  { ...buttonProps }
71
72
  >
72
73
  <span className="components-menu-item__item">{ children }</span>
@@ -29,3 +29,4 @@ $components-color-light-gray-placeholder: color-mix(in srgb, $components-color-b
29
29
 
30
30
  // Semantic aliases (prefer these over raw gray values when applicable).
31
31
  $components-color-border: #{ $components-color-gray-600 };
32
+ $components-color-disabled: #{ $components-color-gray-600 };
@@ -17,7 +17,8 @@ type Value = CheckboxControlProps[ 'checked' ];
17
17
  const UnforwardedValidatedCheckboxControl = (
18
18
  {
19
19
  required,
20
- customValidator,
20
+ onValidate,
21
+ customValidity,
21
22
  onChange,
22
23
  markWhenOptional,
23
24
  ...restProps
@@ -37,9 +38,10 @@ const UnforwardedValidatedCheckboxControl = (
37
38
  required={ required }
38
39
  markWhenOptional={ markWhenOptional }
39
40
  ref={ mergedRefs }
40
- customValidator={ () => {
41
- return customValidator?.( valueRef.current );
41
+ onValidate={ () => {
42
+ return onValidate?.( valueRef.current );
42
43
  } }
44
+ customValidity={ customValidity }
43
45
  getValidityTarget={ () =>
44
46
  validityTargetRef.current?.querySelector< HTMLInputElement >(
45
47
  'input[type="checkbox"]'
@@ -17,7 +17,8 @@ type Value = ComboboxControlProps[ 'value' ];
17
17
  const UnforwardedValidatedComboboxControl = (
18
18
  {
19
19
  required,
20
- customValidator,
20
+ onValidate,
21
+ customValidity,
21
22
  onChange,
22
23
  markWhenOptional,
23
24
  ...restProps
@@ -50,9 +51,10 @@ const UnforwardedValidatedComboboxControl = (
50
51
  required={ required }
51
52
  markWhenOptional={ markWhenOptional }
52
53
  ref={ mergedRefs }
53
- customValidator={ () => {
54
- return customValidator?.( valueRef.current );
54
+ onValidate={ () => {
55
+ return onValidate?.( valueRef.current );
55
56
  } }
57
+ customValidity={ customValidity }
56
58
  getValidityTarget={ () =>
57
59
  validityTargetRef.current?.querySelector< HTMLInputElement >(
58
60
  'input[role="combobox"]'
@@ -21,7 +21,8 @@ type Value = CustomSelectControlProps[ 'value' ];
21
21
  const UnforwardedValidatedCustomSelectControl = (
22
22
  {
23
23
  required,
24
- customValidator,
24
+ onValidate,
25
+ customValidity,
25
26
  onChange,
26
27
  markWhenOptional,
27
28
  ...restProps
@@ -43,9 +44,10 @@ const UnforwardedValidatedCustomSelectControl = (
43
44
  <ControlWithError
44
45
  required={ required }
45
46
  markWhenOptional={ markWhenOptional }
46
- customValidator={ () => {
47
- return customValidator?.( valueRef.current );
47
+ onValidate={ () => {
48
+ return onValidate?.( valueRef.current );
48
49
  } }
50
+ customValidity={ customValidity }
49
51
  getValidityTarget={ () => validityTargetRef.current }
50
52
  >
51
53
  <CustomSelectControl
@@ -17,7 +17,8 @@ type Value = InputControlProps[ 'value' ];
17
17
  const UnforwardedValidatedInputControl = (
18
18
  {
19
19
  required,
20
- customValidator,
20
+ onValidate,
21
+ customValidity,
21
22
  onChange,
22
23
  markWhenOptional,
23
24
  ...restProps
@@ -36,9 +37,10 @@ const UnforwardedValidatedInputControl = (
36
37
  <ControlWithError
37
38
  required={ required }
38
39
  markWhenOptional={ markWhenOptional }
39
- customValidator={ () => {
40
- return customValidator?.( valueRef.current );
40
+ onValidate={ () => {
41
+ return onValidate?.( valueRef.current );
41
42
  } }
43
+ customValidity={ customValidity }
42
44
  getValidityTarget={ () => validityTargetRef.current }
43
45
  >
44
46
  <InputControl
@@ -17,7 +17,8 @@ type Value = NumberControlProps[ 'value' ];
17
17
  const UnforwardedValidatedNumberControl = (
18
18
  {
19
19
  required,
20
- customValidator,
20
+ onValidate,
21
+ customValidity,
21
22
  onChange,
22
23
  markWhenOptional,
23
24
  ...restProps
@@ -36,9 +37,10 @@ const UnforwardedValidatedNumberControl = (
36
37
  <ControlWithError
37
38
  required={ required }
38
39
  markWhenOptional={ markWhenOptional }
39
- customValidator={ () => {
40
- return customValidator?.( valueRef.current );
40
+ onValidate={ () => {
41
+ return onValidate?.( valueRef.current );
41
42
  } }
43
+ customValidity={ customValidity }
42
44
  getValidityTarget={ () => validityTargetRef.current }
43
45
  >
44
46
  <NumberControl
@@ -17,7 +17,8 @@ type Value = RadioControlProps[ 'selected' ];
17
17
  const UnforwardedValidatedRadioControl = (
18
18
  {
19
19
  required,
20
- customValidator,
20
+ onValidate,
21
+ customValidity,
21
22
  onChange,
22
23
  markWhenOptional,
23
24
  ...restProps
@@ -35,9 +36,10 @@ const UnforwardedValidatedRadioControl = (
35
36
  markWhenOptional={ markWhenOptional }
36
37
  // TODO: Upstream limitation - RadioControl does not accept a ref.
37
38
  ref={ mergedRefs }
38
- customValidator={ () => {
39
- return customValidator?.( valueRef.current );
39
+ onValidate={ () => {
40
+ return onValidate?.( valueRef.current );
40
41
  } }
42
+ customValidity={ customValidity }
41
43
  getValidityTarget={ () =>
42
44
  validityTargetRef.current?.querySelector< HTMLInputElement >(
43
45
  'input[type="radio"]'
@@ -17,7 +17,8 @@ type Value = RangeControlProps[ 'value' ];
17
17
  const UnforwardedValidatedRangeControl = (
18
18
  {
19
19
  required,
20
- customValidator,
20
+ onValidate,
21
+ customValidity,
21
22
  onChange,
22
23
  markWhenOptional,
23
24
  ...restProps
@@ -36,9 +37,10 @@ const UnforwardedValidatedRangeControl = (
36
37
  <ControlWithError
37
38
  required={ required }
38
39
  markWhenOptional={ markWhenOptional }
39
- customValidator={ () => {
40
- return customValidator?.( valueRef.current );
40
+ onValidate={ () => {
41
+ return onValidate?.( valueRef.current );
41
42
  } }
43
+ customValidity={ customValidity }
42
44
  getValidityTarget={ () => validityTargetRef.current }
43
45
  >
44
46
  <RangeControl
@@ -26,7 +26,8 @@ type Value = SelectControlProps[ 'value' ];
26
26
  const UnforwardedValidatedSelectControl = (
27
27
  {
28
28
  required,
29
- customValidator,
29
+ onValidate,
30
+ customValidity,
30
31
  onChange,
31
32
  markWhenOptional,
32
33
  ...restProps
@@ -51,9 +52,10 @@ const UnforwardedValidatedSelectControl = (
51
52
  <ControlWithError
52
53
  required={ required }
53
54
  markWhenOptional={ markWhenOptional }
54
- customValidator={ () => {
55
- return customValidator?.( valueRef.current );
55
+ onValidate={ () => {
56
+ return onValidate?.( valueRef.current );
56
57
  } }
58
+ customValidity={ customValidity }
57
59
  getValidityTarget={ () => validityTargetRef.current }
58
60
  >
59
61
  <SelectControl
@@ -32,6 +32,12 @@ export default meta;
32
32
  export const Default: StoryObj< typeof ValidatedCheckboxControl > = {
33
33
  render: function Template( { onChange, ...args } ) {
34
34
  const [ checked, setChecked ] = useState( false );
35
+ const [ customValidity, setCustomValidity ] =
36
+ useState<
37
+ React.ComponentProps<
38
+ typeof ValidatedCheckboxControl
39
+ >[ 'customValidity' ]
40
+ >( undefined );
35
41
 
36
42
  return (
37
43
  <ValidatedCheckboxControl
@@ -41,6 +47,17 @@ export const Default: StoryObj< typeof ValidatedCheckboxControl > = {
41
47
  setChecked( value );
42
48
  onChange?.( value );
43
49
  } }
50
+ onValidate={ ( value ) => {
51
+ if ( value ) {
52
+ setCustomValidity( {
53
+ type: 'invalid',
54
+ message: 'This checkbox may not be checked.',
55
+ } );
56
+ } else {
57
+ setCustomValidity( undefined );
58
+ }
59
+ } }
60
+ customValidity={ customValidity }
44
61
  />
45
62
  );
46
63
  },
@@ -49,10 +66,4 @@ Default.args = {
49
66
  required: true,
50
67
  label: 'Checkbox',
51
68
  help: 'This checkbox may neither be checked nor unchecked.',
52
- customValidator: ( value ) => {
53
- if ( value ) {
54
- return 'This checkbox may not be checked.';
55
- }
56
- return undefined;
57
- },
58
69
  };
@@ -35,6 +35,12 @@ export const Default: StoryObj< typeof ValidatedComboboxControl > = {
35
35
  typeof ValidatedComboboxControl
36
36
  >[ 'value' ]
37
37
  >();
38
+ const [ customValidity, setCustomValidity ] =
39
+ useState<
40
+ React.ComponentProps<
41
+ typeof ValidatedComboboxControl
42
+ >[ 'customValidity' ]
43
+ >( undefined );
38
44
 
39
45
  return (
40
46
  <ValidatedComboboxControl
@@ -44,6 +50,17 @@ export const Default: StoryObj< typeof ValidatedComboboxControl > = {
44
50
  setValue( newValue );
45
51
  onChange?.( newValue );
46
52
  } }
53
+ onValidate={ ( v ) => {
54
+ if ( v === 'a' ) {
55
+ setCustomValidity( {
56
+ type: 'invalid',
57
+ message: 'Option A is not allowed.',
58
+ } );
59
+ } else {
60
+ setCustomValidity( undefined );
61
+ }
62
+ } }
63
+ customValidity={ customValidity }
47
64
  />
48
65
  );
49
66
  },
@@ -56,10 +73,4 @@ Default.args = {
56
73
  { value: 'a', label: 'Option A (not allowed)' },
57
74
  { value: 'b', label: 'Option B' },
58
75
  ],
59
- customValidator: ( value ) => {
60
- if ( value === 'a' ) {
61
- return 'Option A is not allowed.';
62
- }
63
- return undefined;
64
- },
65
76
  };
@@ -35,6 +35,12 @@ export const Default: StoryObj< typeof ValidatedCustomSelectControl > = {
35
35
  typeof ValidatedCustomSelectControl
36
36
  >[ 'value' ]
37
37
  >();
38
+ const [ customValidity, setCustomValidity ] =
39
+ useState<
40
+ React.ComponentProps<
41
+ typeof ValidatedCustomSelectControl
42
+ >[ 'customValidity' ]
43
+ >( undefined );
38
44
 
39
45
  return (
40
46
  <ValidatedCustomSelectControl
@@ -44,6 +50,17 @@ export const Default: StoryObj< typeof ValidatedCustomSelectControl > = {
44
50
  setValue( newValue.selectedItem );
45
51
  onChange?.( newValue );
46
52
  } }
53
+ onValidate={ ( v ) => {
54
+ if ( v?.key === 'a' ) {
55
+ setCustomValidity( {
56
+ type: 'invalid',
57
+ message: 'Option A is not allowed.',
58
+ } );
59
+ } else {
60
+ setCustomValidity( undefined );
61
+ }
62
+ } }
63
+ customValidity={ customValidity }
47
64
  />
48
65
  );
49
66
  },
@@ -56,10 +73,4 @@ Default.args = {
56
73
  { key: 'a', name: 'Option A (not allowed)' },
57
74
  { key: 'b', name: 'Option B' },
58
75
  ],
59
- customValidator: ( value ) => {
60
- if ( value?.key === 'a' ) {
61
- return 'Option A is not allowed.';
62
- }
63
- return undefined;
64
- },
65
76
  };
@@ -46,6 +46,12 @@ export const Default: StoryObj< typeof ValidatedInputControl > = {
46
46
  useState<
47
47
  React.ComponentProps< typeof ValidatedInputControl >[ 'value' ]
48
48
  >( '' );
49
+ const [ customValidity, setCustomValidity ] =
50
+ useState<
51
+ React.ComponentProps<
52
+ typeof ValidatedInputControl
53
+ >[ 'customValidity' ]
54
+ >( undefined );
49
55
 
50
56
  return (
51
57
  <ValidatedInputControl
@@ -55,6 +61,17 @@ export const Default: StoryObj< typeof ValidatedInputControl > = {
55
61
  setValue( newValue );
56
62
  onChange?.( newValue, ...rest );
57
63
  } }
64
+ onValidate={ ( v ) => {
65
+ if ( v?.toLowerCase() === 'error' ) {
66
+ setCustomValidity( {
67
+ type: 'invalid',
68
+ message: 'The word "error" is not allowed.',
69
+ } );
70
+ } else {
71
+ setCustomValidity( undefined );
72
+ }
73
+ } }
74
+ customValidity={ customValidity }
58
75
  />
59
76
  );
60
77
  },
@@ -63,12 +80,6 @@ Default.args = {
63
80
  required: true,
64
81
  label: 'Input',
65
82
  help: 'The word "error" will trigger an error.',
66
- customValidator: ( value ) => {
67
- if ( value?.toLowerCase() === 'error' ) {
68
- return 'The word "error" is not allowed.';
69
- }
70
- return undefined;
71
- },
72
83
  };
73
84
 
74
85
  /**
@@ -83,6 +94,12 @@ export const Password: StoryObj< typeof ValidatedInputControl > = {
83
94
  React.ComponentProps< typeof ValidatedInputControl >[ 'value' ]
84
95
  >( '' );
85
96
  const [ visible, setVisible ] = useState( false );
97
+ const [ customValidity, setCustomValidity ] =
98
+ useState<
99
+ React.ComponentProps<
100
+ typeof ValidatedInputControl
101
+ >[ 'customValidity' ]
102
+ >( undefined );
86
103
 
87
104
  return (
88
105
  <ValidatedInputControl
@@ -105,6 +122,34 @@ export const Password: StoryObj< typeof ValidatedInputControl > = {
105
122
  setValue( newValue );
106
123
  onChange?.( newValue, ...rest );
107
124
  } }
125
+ onValidate={ ( v ) => {
126
+ if ( ! /\d/.test( v ?? '' ) ) {
127
+ setCustomValidity( {
128
+ type: 'invalid',
129
+ message:
130
+ 'Password must include at least one number.',
131
+ } );
132
+ return;
133
+ }
134
+ if ( ! /[A-Z]/.test( v ?? '' ) ) {
135
+ setCustomValidity( {
136
+ type: 'invalid',
137
+ message:
138
+ 'Password must include at least one capital letter.',
139
+ } );
140
+ return;
141
+ }
142
+ if ( ! /[!@£$%^&*#]/.test( v ?? '' ) ) {
143
+ setCustomValidity( {
144
+ type: 'invalid',
145
+ message:
146
+ 'Password must include at least one symbol.',
147
+ } );
148
+ return;
149
+ }
150
+ setCustomValidity( undefined );
151
+ } }
152
+ customValidity={ customValidity }
108
153
  />
109
154
  );
110
155
  },
@@ -114,18 +159,6 @@ Password.args = {
114
159
  label: 'Password',
115
160
  help: 'Minimum 8 characters, include a number, capital letter, and symbol (!@£$%^&*#).',
116
161
  minLength: 8,
117
- customValidator: ( value ) => {
118
- if ( ! /\d/.test( value ?? '' ) ) {
119
- return 'Password must include at least one number.';
120
- }
121
- if ( ! /[A-Z]/.test( value ?? '' ) ) {
122
- return 'Password must include at least one capital letter.';
123
- }
124
- if ( ! /[!@£$%^&*#]/.test( value ?? '' ) ) {
125
- return 'Password must include at least one symbol.';
126
- }
127
- return undefined;
128
- },
129
162
  };
130
163
  Password.argTypes = {
131
164
  suffix: { control: false },
@@ -37,6 +37,12 @@ export const Default: StoryObj< typeof ValidatedNumberControl > = {
37
37
  useState<
38
38
  React.ComponentProps< typeof ValidatedNumberControl >[ 'value' ]
39
39
  >();
40
+ const [ customValidity, setCustomValidity ] =
41
+ useState<
42
+ React.ComponentProps<
43
+ typeof ValidatedNumberControl
44
+ >[ 'customValidity' ]
45
+ >( undefined );
40
46
 
41
47
  return (
42
48
  <ValidatedNumberControl
@@ -46,6 +52,17 @@ export const Default: StoryObj< typeof ValidatedNumberControl > = {
46
52
  setValue( newValue );
47
53
  onChange?.( newValue, ...rest );
48
54
  } }
55
+ onValidate={ ( v ) => {
56
+ if ( v && parseInt( v.toString(), 10 ) % 2 !== 0 ) {
57
+ setCustomValidity( {
58
+ type: 'invalid',
59
+ message: 'Choose an even number.',
60
+ } );
61
+ } else {
62
+ setCustomValidity( undefined );
63
+ }
64
+ } }
65
+ customValidity={ customValidity }
49
66
  />
50
67
  );
51
68
  },
@@ -54,10 +71,4 @@ Default.args = {
54
71
  required: true,
55
72
  label: 'Number',
56
73
  help: 'Odd numbers are not allowed.',
57
- customValidator: ( value ) => {
58
- if ( value && parseInt( value.toString(), 10 ) % 2 !== 0 ) {
59
- return 'Choose an even number.';
60
- }
61
- return undefined;
62
- },
63
74
  };
@@ -16,7 +16,7 @@ We are still gathering feedback and iterating. Please get in touch with `@WordPr
16
16
 
17
17
  Component APIs are the same as the underlying WordPress components, with the addition of some optional props:
18
18
 
19
- <ArgTypes of={ ValidatedInputControl } include={ [ 'required', 'markWhenOptional', 'customValidator' ] } />
19
+ <ArgTypes of={ ValidatedInputControl } include={ [ 'required', 'markWhenOptional', 'onValidate', 'customValidity' ] } />
20
20
 
21
21
  ## Implementation
22
22