@wordpress/components 30.9.0 → 31.0.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 (233) hide show
  1. package/CHANGELOG.md +26 -4
  2. package/build/alignment-matrix-control/cell.js +131 -3
  3. package/build/alignment-matrix-control/cell.js.map +4 -4
  4. package/build/alignment-matrix-control/index.js +134 -6
  5. package/build/alignment-matrix-control/index.js.map +3 -3
  6. package/build/angle-picker-control/angle-circle.js +119 -15
  7. package/build/angle-picker-control/angle-circle.js.map +4 -4
  8. package/build/angle-picker-control/index.js +12 -7
  9. package/build/angle-picker-control/index.js.map +3 -3
  10. package/build/dropdown-menu/index.js +1 -1
  11. package/build/dropdown-menu/index.js.map +2 -2
  12. package/build/form-token-field/index.js +1 -13
  13. package/build/form-token-field/index.js.map +3 -3
  14. package/build/menu/styles.js +17 -17
  15. package/build/menu/styles.js.map +2 -2
  16. package/build/menu-item/index.js +1 -1
  17. package/build/menu-item/index.js.map +2 -2
  18. package/build/notice/index.js +1 -1
  19. package/build/notice/index.js.map +2 -2
  20. package/build/query-controls/index.js +0 -1
  21. package/build/query-controls/index.js.map +2 -2
  22. package/build/snackbar/index.js +1 -1
  23. package/build/snackbar/index.js.map +1 -1
  24. package/build/validated-form-controls/components/checkbox-control.js +0 -10
  25. package/build/validated-form-controls/components/checkbox-control.js.map +2 -2
  26. package/build/validated-form-controls/components/combobox-control.js +1 -11
  27. package/build/validated-form-controls/components/combobox-control.js.map +2 -2
  28. package/build/validated-form-controls/components/custom-select-control.js +0 -10
  29. package/build/validated-form-controls/components/custom-select-control.js.map +2 -2
  30. package/build/validated-form-controls/components/form-token-field.js +2 -13
  31. package/build/validated-form-controls/components/form-token-field.js.map +2 -2
  32. package/build/validated-form-controls/components/input-control.js +0 -10
  33. package/build/validated-form-controls/components/input-control.js.map +2 -2
  34. package/build/validated-form-controls/components/number-control.js +0 -10
  35. package/build/validated-form-controls/components/number-control.js.map +2 -2
  36. package/build/validated-form-controls/components/radio-control.js +0 -10
  37. package/build/validated-form-controls/components/radio-control.js.map +2 -2
  38. package/build/validated-form-controls/components/range-control.js +0 -10
  39. package/build/validated-form-controls/components/range-control.js.map +2 -2
  40. package/build/validated-form-controls/components/select-control.js +0 -10
  41. package/build/validated-form-controls/components/select-control.js.map +2 -2
  42. package/build/validated-form-controls/components/text-control.js +0 -10
  43. package/build/validated-form-controls/components/text-control.js.map +2 -2
  44. package/build/validated-form-controls/components/textarea-control.js +0 -10
  45. package/build/validated-form-controls/components/textarea-control.js.map +2 -2
  46. package/build/validated-form-controls/components/toggle-control.js +0 -10
  47. package/build/validated-form-controls/components/toggle-control.js.map +2 -2
  48. package/build/validated-form-controls/components/toggle-group-control.js +0 -10
  49. package/build/validated-form-controls/components/toggle-group-control.js.map +2 -2
  50. package/build/validated-form-controls/control-with-error.js +53 -58
  51. package/build/validated-form-controls/control-with-error.js.map +2 -2
  52. package/build-module/alignment-matrix-control/cell.js +131 -3
  53. package/build-module/alignment-matrix-control/cell.js.map +3 -3
  54. package/build-module/alignment-matrix-control/index.js +134 -6
  55. package/build-module/alignment-matrix-control/index.js.map +3 -3
  56. package/build-module/angle-picker-control/angle-circle.js +109 -15
  57. package/build-module/angle-picker-control/angle-circle.js.map +3 -3
  58. package/build-module/angle-picker-control/index.js +12 -7
  59. package/build-module/angle-picker-control/index.js.map +2 -2
  60. package/build-module/dropdown-menu/index.js +1 -1
  61. package/build-module/dropdown-menu/index.js.map +2 -2
  62. package/build-module/form-token-field/index.js +1 -13
  63. package/build-module/form-token-field/index.js.map +2 -2
  64. package/build-module/menu/styles.js +17 -17
  65. package/build-module/menu/styles.js.map +2 -2
  66. package/build-module/menu-item/index.js +1 -1
  67. package/build-module/menu-item/index.js.map +2 -2
  68. package/build-module/notice/index.js +1 -1
  69. package/build-module/notice/index.js.map +2 -2
  70. package/build-module/query-controls/index.js +0 -1
  71. package/build-module/query-controls/index.js.map +2 -2
  72. package/build-module/snackbar/index.js +1 -1
  73. package/build-module/snackbar/index.js.map +1 -1
  74. package/build-module/validated-form-controls/components/checkbox-control.js +0 -10
  75. package/build-module/validated-form-controls/components/checkbox-control.js.map +2 -2
  76. package/build-module/validated-form-controls/components/combobox-control.js +1 -11
  77. package/build-module/validated-form-controls/components/combobox-control.js.map +2 -2
  78. package/build-module/validated-form-controls/components/custom-select-control.js +0 -10
  79. package/build-module/validated-form-controls/components/custom-select-control.js.map +2 -2
  80. package/build-module/validated-form-controls/components/form-token-field.js +2 -13
  81. package/build-module/validated-form-controls/components/form-token-field.js.map +2 -2
  82. package/build-module/validated-form-controls/components/input-control.js +0 -10
  83. package/build-module/validated-form-controls/components/input-control.js.map +2 -2
  84. package/build-module/validated-form-controls/components/number-control.js +0 -10
  85. package/build-module/validated-form-controls/components/number-control.js.map +2 -2
  86. package/build-module/validated-form-controls/components/radio-control.js +0 -10
  87. package/build-module/validated-form-controls/components/radio-control.js.map +2 -2
  88. package/build-module/validated-form-controls/components/range-control.js +0 -10
  89. package/build-module/validated-form-controls/components/range-control.js.map +2 -2
  90. package/build-module/validated-form-controls/components/select-control.js +0 -10
  91. package/build-module/validated-form-controls/components/select-control.js.map +2 -2
  92. package/build-module/validated-form-controls/components/text-control.js +0 -10
  93. package/build-module/validated-form-controls/components/text-control.js.map +2 -2
  94. package/build-module/validated-form-controls/components/textarea-control.js +0 -10
  95. package/build-module/validated-form-controls/components/textarea-control.js.map +2 -2
  96. package/build-module/validated-form-controls/components/toggle-control.js +0 -10
  97. package/build-module/validated-form-controls/components/toggle-control.js.map +2 -2
  98. package/build-module/validated-form-controls/components/toggle-group-control.js +0 -10
  99. package/build-module/validated-form-controls/components/toggle-group-control.js.map +2 -2
  100. package/build-module/validated-form-controls/control-with-error.js +53 -58
  101. package/build-module/validated-form-controls/control-with-error.js.map +2 -2
  102. package/build-style/style-rtl.css +21 -33
  103. package/build-style/style.css +21 -33
  104. package/build-types/alignment-matrix-control/cell.d.ts.map +1 -1
  105. package/build-types/alignment-matrix-control/index.d.ts.map +1 -1
  106. package/build-types/angle-picker-control/angle-circle.d.ts +1 -1
  107. package/build-types/angle-picker-control/angle-circle.d.ts.map +1 -1
  108. package/build-types/angle-picker-control/index.d.ts.map +1 -1
  109. package/build-types/form-token-field/index.d.ts.map +1 -1
  110. package/build-types/form-token-field/stories/index.story.d.ts.map +1 -1
  111. package/build-types/form-token-field/types.d.ts +0 -6
  112. package/build-types/form-token-field/types.d.ts.map +1 -1
  113. package/build-types/notice/index.d.ts.map +1 -1
  114. package/build-types/notice/stories/index.story.d.ts.map +1 -1
  115. package/build-types/query-controls/index.d.ts.map +1 -1
  116. package/build-types/validated-form-controls/components/checkbox-control.d.ts +1 -1
  117. package/build-types/validated-form-controls/components/checkbox-control.d.ts.map +1 -1
  118. package/build-types/validated-form-controls/components/combobox-control.d.ts +2 -3
  119. package/build-types/validated-form-controls/components/combobox-control.d.ts.map +1 -1
  120. package/build-types/validated-form-controls/components/custom-select-control.d.ts +1 -2
  121. package/build-types/validated-form-controls/components/custom-select-control.d.ts.map +1 -1
  122. package/build-types/validated-form-controls/components/form-token-field.d.ts +1 -2
  123. package/build-types/validated-form-controls/components/form-token-field.d.ts.map +1 -1
  124. package/build-types/validated-form-controls/components/input-control.d.ts +1 -2
  125. package/build-types/validated-form-controls/components/input-control.d.ts.map +1 -1
  126. package/build-types/validated-form-controls/components/number-control.d.ts +1 -1
  127. package/build-types/validated-form-controls/components/number-control.d.ts.map +1 -1
  128. package/build-types/validated-form-controls/components/radio-control.d.ts +1 -1
  129. package/build-types/validated-form-controls/components/radio-control.d.ts.map +1 -1
  130. package/build-types/validated-form-controls/components/range-control.d.ts +1 -1
  131. package/build-types/validated-form-controls/components/range-control.d.ts.map +1 -1
  132. package/build-types/validated-form-controls/components/select-control.d.ts +2 -3
  133. package/build-types/validated-form-controls/components/select-control.d.ts.map +1 -1
  134. package/build-types/validated-form-controls/components/stories/checkbox-control.story.d.ts.map +1 -1
  135. package/build-types/validated-form-controls/components/stories/combobox-control.story.d.ts.map +1 -1
  136. package/build-types/validated-form-controls/components/stories/custom-select-control.story.d.ts.map +1 -1
  137. package/build-types/validated-form-controls/components/stories/form-token-field.story.d.ts.map +1 -1
  138. package/build-types/validated-form-controls/components/stories/input-control.story.d.ts.map +1 -1
  139. package/build-types/validated-form-controls/components/stories/number-control.story.d.ts.map +1 -1
  140. package/build-types/validated-form-controls/components/stories/overview.story.d.ts +7 -0
  141. package/build-types/validated-form-controls/components/stories/overview.story.d.ts.map +1 -1
  142. package/build-types/validated-form-controls/components/stories/radio-control.story.d.ts.map +1 -1
  143. package/build-types/validated-form-controls/components/stories/range-control.story.d.ts.map +1 -1
  144. package/build-types/validated-form-controls/components/stories/select-control.story.d.ts.map +1 -1
  145. package/build-types/validated-form-controls/components/stories/text-control.story.d.ts.map +1 -1
  146. package/build-types/validated-form-controls/components/stories/textarea-control.story.d.ts.map +1 -1
  147. package/build-types/validated-form-controls/components/stories/toggle-control.story.d.ts.map +1 -1
  148. package/build-types/validated-form-controls/components/stories/toggle-group-control.story.d.ts.map +1 -1
  149. package/build-types/validated-form-controls/components/text-control.d.ts +1 -1
  150. package/build-types/validated-form-controls/components/text-control.d.ts.map +1 -1
  151. package/build-types/validated-form-controls/components/textarea-control.d.ts +1 -1
  152. package/build-types/validated-form-controls/components/textarea-control.d.ts.map +1 -1
  153. package/build-types/validated-form-controls/components/toggle-control.d.ts +1 -1
  154. package/build-types/validated-form-controls/components/toggle-control.d.ts.map +1 -1
  155. package/build-types/validated-form-controls/components/toggle-group-control.d.ts +1 -1
  156. package/build-types/validated-form-controls/components/toggle-group-control.d.ts.map +1 -1
  157. package/build-types/validated-form-controls/components/types.d.ts +1 -9
  158. package/build-types/validated-form-controls/components/types.d.ts.map +1 -1
  159. package/build-types/validated-form-controls/control-with-error.d.ts +4 -5
  160. package/build-types/validated-form-controls/control-with-error.d.ts.map +1 -1
  161. package/package.json +20 -20
  162. package/src/alignment-matrix-control/cell.tsx +14 -3
  163. package/src/alignment-matrix-control/index.tsx +15 -6
  164. package/src/alignment-matrix-control/style.module.scss +84 -0
  165. package/src/angle-picker-control/angle-circle.tsx +27 -12
  166. package/src/angle-picker-control/index.tsx +8 -7
  167. package/src/angle-picker-control/style.module.scss +40 -0
  168. package/src/button/style.scss +1 -1
  169. package/src/dropdown-menu/index.tsx +1 -1
  170. package/src/dropdown-menu/style.scss +1 -1
  171. package/src/form-token-field/README.md +0 -2
  172. package/src/form-token-field/index.tsx +1 -13
  173. package/src/form-token-field/stories/index.story.tsx +0 -2
  174. package/src/form-token-field/test/index.tsx +0 -1
  175. package/src/form-token-field/types.ts +0 -6
  176. package/src/guide/style.scss +3 -3
  177. package/src/menu/styles.ts +2 -2
  178. package/src/menu-item/index.tsx +1 -1
  179. package/src/menu-item/test/__snapshots__/index.js.snap +4 -4
  180. package/src/modal/style.scss +5 -5
  181. package/src/notice/index.tsx +53 -46
  182. package/src/notice/stories/index.story.tsx +17 -1
  183. package/src/notice/style.scss +3 -20
  184. package/src/query-controls/index.tsx +0 -1
  185. package/src/snackbar/index.tsx +1 -1
  186. package/src/validated-form-controls/components/checkbox-control.tsx +1 -14
  187. package/src/validated-form-controls/components/combobox-control.tsx +1 -14
  188. package/src/validated-form-controls/components/custom-select-control.tsx +1 -19
  189. package/src/validated-form-controls/components/form-token-field.tsx +4 -21
  190. package/src/validated-form-controls/components/input-control.tsx +1 -14
  191. package/src/validated-form-controls/components/number-control.tsx +1 -16
  192. package/src/validated-form-controls/components/radio-control.tsx +2 -18
  193. package/src/validated-form-controls/components/range-control.tsx +1 -14
  194. package/src/validated-form-controls/components/select-control.tsx +1 -23
  195. package/src/validated-form-controls/components/stories/checkbox-control.story.tsx +11 -20
  196. package/src/validated-form-controls/components/stories/combobox-control.story.tsx +8 -17
  197. package/src/validated-form-controls/components/stories/custom-select-control.story.tsx +8 -17
  198. package/src/validated-form-controls/components/stories/form-token-field.story.tsx +14 -26
  199. package/src/validated-form-controls/components/stories/input-control.story.tsx +25 -50
  200. package/src/validated-form-controls/components/stories/number-control.story.tsx +10 -19
  201. package/src/validated-form-controls/components/stories/overview.mdx +3 -3
  202. package/src/validated-form-controls/components/stories/overview.story.tsx +94 -79
  203. package/src/validated-form-controls/components/stories/radio-control.story.tsx +11 -20
  204. package/src/validated-form-controls/components/stories/range-control.story.tsx +8 -17
  205. package/src/validated-form-controls/components/stories/select-control.story.tsx +9 -18
  206. package/src/validated-form-controls/components/stories/text-control.story.tsx +11 -17
  207. package/src/validated-form-controls/components/stories/textarea-control.story.tsx +12 -16
  208. package/src/validated-form-controls/components/stories/toggle-control.story.tsx +11 -20
  209. package/src/validated-form-controls/components/stories/toggle-group-control.story.tsx +8 -17
  210. package/src/validated-form-controls/components/text-control.tsx +1 -14
  211. package/src/validated-form-controls/components/textarea-control.tsx +1 -14
  212. package/src/validated-form-controls/components/toggle-control.tsx +1 -14
  213. package/src/validated-form-controls/components/toggle-group-control.tsx +1 -14
  214. package/src/validated-form-controls/components/types.ts +1 -9
  215. package/src/validated-form-controls/control-with-error.tsx +57 -84
  216. package/src/validated-form-controls/style.scss +7 -7
  217. package/src/validated-form-controls/test/control-with-error.tsx +66 -5
  218. package/tsconfig.json +1 -0
  219. package/tsconfig.tsbuildinfo +1 -1
  220. package/build/alignment-matrix-control/styles.js +0 -105
  221. package/build/alignment-matrix-control/styles.js.map +0 -7
  222. package/build/angle-picker-control/styles/angle-picker-control-styles.js +0 -88
  223. package/build/angle-picker-control/styles/angle-picker-control-styles.js.map +0 -7
  224. package/build-module/alignment-matrix-control/styles.js +0 -67
  225. package/build-module/alignment-matrix-control/styles.js.map +0 -7
  226. package/build-module/angle-picker-control/styles/angle-picker-control-styles.js +0 -50
  227. package/build-module/angle-picker-control/styles/angle-picker-control-styles.js.map +0 -7
  228. package/build-types/alignment-matrix-control/styles.d.ts +0 -21
  229. package/build-types/alignment-matrix-control/styles.d.ts.map +0 -1
  230. package/build-types/angle-picker-control/styles/angle-picker-control-styles.d.ts +0 -18
  231. package/build-types/angle-picker-control/styles/angle-picker-control-styles.d.ts.map +0 -1
  232. package/src/alignment-matrix-control/styles.ts +0 -113
  233. package/src/angle-picker-control/styles/angle-picker-control-styles.tsx +0 -58
@@ -10,48 +10,33 @@ import { useMergeRefs } from '@wordpress/compose';
10
10
  import { ControlWithError } from '../control-with-error';
11
11
  import NumberControl from '../../number-control';
12
12
  import type { ValidatedControlProps } from './types';
13
- import type { NumberControlProps } from '../../number-control/types';
14
-
15
- type Value = NumberControlProps[ 'value' ];
16
13
 
17
14
  const UnforwardedValidatedNumberControl = (
18
15
  {
19
16
  required,
20
- onValidate,
21
17
  customValidity,
22
- onChange,
23
18
  markWhenOptional,
24
19
  ...restProps
25
20
  }: Omit<
26
21
  React.ComponentProps< typeof NumberControl >,
27
22
  '__next40pxDefaultSize'
28
23
  > &
29
- ValidatedControlProps< Value >,
24
+ ValidatedControlProps,
30
25
  forwardedRef: React.ForwardedRef< HTMLInputElement >
31
26
  ) => {
32
27
  const validityTargetRef = useRef< HTMLInputElement >( null );
33
28
  const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
34
- const valueRef = useRef< Value >( restProps.value );
35
29
 
36
30
  return (
37
31
  <ControlWithError
38
32
  required={ required }
39
33
  markWhenOptional={ markWhenOptional }
40
- onValidate={ () => {
41
- return onValidate?.( valueRef.current );
42
- } }
43
34
  customValidity={ customValidity }
44
35
  getValidityTarget={ () => validityTargetRef.current }
45
36
  >
46
37
  <NumberControl
47
38
  __next40pxDefaultSize
48
39
  ref={ mergedRefs }
49
- // TODO: Upstream limitation - When form is submitted when value is undefined, it will
50
- // automatically set a clamped value (as defined by `min` attribute, so 0 by default).
51
- onChange={ ( value, ...args ) => {
52
- valueRef.current = value;
53
- onChange?.( value, ...args );
54
- } }
55
40
  { ...restProps }
56
41
  />
57
42
  </ControlWithError>
@@ -10,25 +10,18 @@ import { forwardRef, useRef } from '@wordpress/element';
10
10
  import { ControlWithError } from '../control-with-error';
11
11
  import type { ValidatedControlProps } from './types';
12
12
  import RadioControl from '../../radio-control';
13
- import type { RadioControlProps } from '../../radio-control/types';
14
-
15
- type Value = RadioControlProps[ 'selected' ];
16
13
 
17
14
  const UnforwardedValidatedRadioControl = (
18
15
  {
19
16
  required,
20
- onValidate,
21
17
  customValidity,
22
- onChange,
23
18
  markWhenOptional,
24
19
  ...restProps
25
- }: React.ComponentProps< typeof RadioControl > &
26
- ValidatedControlProps< Value >,
20
+ }: React.ComponentProps< typeof RadioControl > & ValidatedControlProps,
27
21
  forwardedRef: React.ForwardedRef< HTMLDivElement >
28
22
  ) => {
29
23
  const validityTargetRef = useRef< HTMLDivElement >( null );
30
24
  const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
31
- const valueRef = useRef< Value >( restProps.selected );
32
25
 
33
26
  return (
34
27
  <ControlWithError
@@ -36,9 +29,6 @@ const UnforwardedValidatedRadioControl = (
36
29
  markWhenOptional={ markWhenOptional }
37
30
  // TODO: Upstream limitation - RadioControl does not accept a ref.
38
31
  ref={ mergedRefs }
39
- onValidate={ () => {
40
- return onValidate?.( valueRef.current );
41
- } }
42
32
  customValidity={ customValidity }
43
33
  getValidityTarget={ () =>
44
34
  validityTargetRef.current?.querySelector< HTMLInputElement >(
@@ -46,13 +36,7 @@ const UnforwardedValidatedRadioControl = (
46
36
  )
47
37
  }
48
38
  >
49
- <RadioControl
50
- onChange={ ( value ) => {
51
- valueRef.current = value;
52
- onChange?.( value );
53
- } }
54
- { ...restProps }
55
- />
39
+ <RadioControl { ...restProps } />
56
40
  </ControlWithError>
57
41
  );
58
42
  };
@@ -10,36 +10,27 @@ import { forwardRef, useRef } from '@wordpress/element';
10
10
  import { ControlWithError } from '../control-with-error';
11
11
  import type { ValidatedControlProps } from './types';
12
12
  import RangeControl from '../../range-control';
13
- import type { RangeControlProps } from '../../range-control/types';
14
-
15
- type Value = RangeControlProps[ 'value' ];
16
13
 
17
14
  const UnforwardedValidatedRangeControl = (
18
15
  {
19
16
  required,
20
- onValidate,
21
17
  customValidity,
22
- onChange,
23
18
  markWhenOptional,
24
19
  ...restProps
25
20
  }: Omit<
26
21
  React.ComponentProps< typeof RangeControl >,
27
22
  '__next40pxDefaultSize' | '__nextHasNoMarginBottom'
28
23
  > &
29
- ValidatedControlProps< Value >,
24
+ ValidatedControlProps,
30
25
  forwardedRef: React.ForwardedRef< HTMLInputElement >
31
26
  ) => {
32
27
  const validityTargetRef = useRef< HTMLInputElement >( null );
33
28
  const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
34
- const valueRef = useRef< Value >( restProps.value );
35
29
 
36
30
  return (
37
31
  <ControlWithError
38
32
  required={ required }
39
33
  markWhenOptional={ markWhenOptional }
40
- onValidate={ () => {
41
- return onValidate?.( valueRef.current );
42
- } }
43
34
  customValidity={ customValidity }
44
35
  getValidityTarget={ () => validityTargetRef.current }
45
36
  >
@@ -47,10 +38,6 @@ const UnforwardedValidatedRangeControl = (
47
38
  __next40pxDefaultSize
48
39
  __nextHasNoMarginBottom
49
40
  ref={ mergedRefs }
50
- onChange={ ( value ) => {
51
- valueRef.current = value;
52
- onChange?.( value );
53
- } }
54
41
  { ...restProps }
55
42
  />
56
43
  </ControlWithError>
@@ -10,25 +10,11 @@ import { useMergeRefs } from '@wordpress/compose';
10
10
  import { ControlWithError } from '../control-with-error';
11
11
  import SelectControl from '../../select-control';
12
12
  import type { ValidatedControlProps } from './types';
13
- import type { SelectControlProps as _SelectControlProps } from '../../select-control/types';
14
-
15
- // Only support single value selection
16
- type SelectControlProps = Omit<
17
- _SelectControlProps,
18
- 'multiple' | 'onChange' | 'value'
19
- > & {
20
- onChange?: ( value: string ) => void;
21
- value?: string;
22
- };
23
-
24
- type Value = SelectControlProps[ 'value' ];
25
13
 
26
14
  const UnforwardedValidatedSelectControl = (
27
15
  {
28
16
  required,
29
- onValidate,
30
17
  customValidity,
31
- onChange,
32
18
  markWhenOptional,
33
19
  ...restProps
34
20
  }: Omit<
@@ -41,20 +27,16 @@ const UnforwardedValidatedSelectControl = (
41
27
  > & {
42
28
  value?: string;
43
29
  onChange: ( value: string ) => void;
44
- } & ValidatedControlProps< Value >,
30
+ } & ValidatedControlProps,
45
31
  forwardedRef: React.ForwardedRef< HTMLSelectElement >
46
32
  ) => {
47
33
  const validityTargetRef = useRef< HTMLSelectElement >( null );
48
34
  const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
49
- const valueRef = useRef< Value >( restProps.value );
50
35
 
51
36
  return (
52
37
  <ControlWithError
53
38
  required={ required }
54
39
  markWhenOptional={ markWhenOptional }
55
- onValidate={ () => {
56
- return onValidate?.( valueRef.current );
57
- } }
58
40
  customValidity={ customValidity }
59
41
  getValidityTarget={ () => validityTargetRef.current }
60
42
  >
@@ -62,10 +44,6 @@ const UnforwardedValidatedSelectControl = (
62
44
  __nextHasNoMarginBottom
63
45
  __next40pxDefaultSize
64
46
  ref={ mergedRefs }
65
- onChange={ ( value ) => {
66
- valueRef.current = value;
67
- onChange?.( value );
68
- } }
69
47
  { ...restProps }
70
48
  />
71
49
  </ControlWithError>
@@ -32,32 +32,23 @@ 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 );
41
35
 
42
36
  return (
43
37
  <ValidatedCheckboxControl
44
38
  { ...args }
45
39
  checked={ checked }
46
- onChange={ ( value ) => {
47
- setChecked( value );
48
- onChange?.( value );
40
+ onChange={ ( newValue ) => {
41
+ setChecked( newValue );
42
+ onChange?.( newValue );
49
43
  } }
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
+ customValidity={
45
+ checked
46
+ ? {
47
+ type: 'invalid',
48
+ message: 'This checkbox may not be checked.',
49
+ }
50
+ : undefined
51
+ }
61
52
  />
62
53
  );
63
54
  },
@@ -35,12 +35,6 @@ 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 );
44
38
 
45
39
  return (
46
40
  <ValidatedComboboxControl
@@ -50,17 +44,14 @@ export const Default: StoryObj< typeof ValidatedComboboxControl > = {
50
44
  setValue( newValue );
51
45
  onChange?.( newValue );
52
46
  } }
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
+ customValidity={
48
+ value === 'a'
49
+ ? {
50
+ type: 'invalid',
51
+ message: 'Option A is not allowed.',
52
+ }
53
+ : undefined
54
+ }
64
55
  />
65
56
  );
66
57
  },
@@ -35,12 +35,6 @@ 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 );
44
38
 
45
39
  return (
46
40
  <ValidatedCustomSelectControl
@@ -50,17 +44,14 @@ export const Default: StoryObj< typeof ValidatedCustomSelectControl > = {
50
44
  setValue( newValue.selectedItem );
51
45
  onChange?.( newValue );
52
46
  } }
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
+ customValidity={
48
+ value?.key === 'a'
49
+ ? {
50
+ type: 'invalid',
51
+ message: 'Option A is not allowed.',
52
+ }
53
+ : undefined
54
+ }
64
55
  />
65
56
  );
66
57
  },
@@ -36,39 +36,27 @@ export default meta;
36
36
  export const Default: StoryObj< typeof ValidatedFormTokenField > = {
37
37
  render: function Template( { onChange, ...args } ) {
38
38
  const [ value, setValue ] = useState< ( string | TokenItem )[] >( [] );
39
- const [ customValidity, setCustomValidity ] =
40
- useState<
41
- React.ComponentProps<
42
- typeof ValidatedFormTokenField
43
- >[ 'customValidity' ]
44
- >( undefined );
45
39
 
46
40
  return (
47
41
  <ValidatedFormTokenField
48
42
  { ...args }
49
43
  value={ value }
50
- onChange={ ( newValue, ...rest ) => {
44
+ onChange={ ( newValue ) => {
51
45
  setValue( newValue );
52
- onChange?.( newValue, ...rest );
46
+ onChange?.( newValue );
53
47
  } }
54
- onValidate={ ( v ) => {
55
- if (
56
- v?.some( ( token ) => {
57
- const tokenValue =
58
- typeof token === 'string' ? token : token.value;
59
- return tokenValue.toLowerCase() === 'error';
60
- } )
61
- ) {
62
- setCustomValidity( {
63
- type: 'invalid',
64
- message: 'The tag "error" is not allowed.',
65
- } );
66
- return;
67
- }
68
-
69
- setCustomValidity( undefined );
70
- } }
71
- customValidity={ customValidity }
48
+ customValidity={
49
+ value?.some( ( token ) => {
50
+ const tokenValue =
51
+ typeof token === 'string' ? token : token.value;
52
+ return tokenValue.toLowerCase() === 'error';
53
+ } )
54
+ ? {
55
+ type: 'invalid',
56
+ message: 'The tag "error" is not allowed.',
57
+ }
58
+ : undefined
59
+ }
72
60
  />
73
61
  );
74
62
  },
@@ -42,16 +42,7 @@ export default meta;
42
42
 
43
43
  export const Default: StoryObj< typeof ValidatedInputControl > = {
44
44
  render: function Template( { onChange, ...args } ) {
45
- const [ value, setValue ] =
46
- useState<
47
- React.ComponentProps< typeof ValidatedInputControl >[ 'value' ]
48
- >( '' );
49
- const [ customValidity, setCustomValidity ] =
50
- useState<
51
- React.ComponentProps<
52
- typeof ValidatedInputControl
53
- >[ 'customValidity' ]
54
- >( undefined );
45
+ const [ value, setValue ] = useState< string | undefined >( '' );
55
46
 
56
47
  return (
57
48
  <ValidatedInputControl
@@ -61,17 +52,14 @@ export const Default: StoryObj< typeof ValidatedInputControl > = {
61
52
  setValue( newValue );
62
53
  onChange?.( newValue, ...rest );
63
54
  } }
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 }
55
+ customValidity={
56
+ value?.toLowerCase() === 'error'
57
+ ? {
58
+ type: 'invalid',
59
+ message: 'The word "error" is not allowed.',
60
+ }
61
+ : undefined
62
+ }
75
63
  />
76
64
  );
77
65
  },
@@ -89,17 +77,8 @@ Default.args = {
89
77
  */
90
78
  export const Password: StoryObj< typeof ValidatedInputControl > = {
91
79
  render: function Template( { onChange, ...args } ) {
92
- const [ value, setValue ] =
93
- useState<
94
- React.ComponentProps< typeof ValidatedInputControl >[ 'value' ]
95
- >( '' );
80
+ const [ value, setValue ] = useState< string | undefined >( '' );
96
81
  const [ visible, setVisible ] = useState( false );
97
- const [ customValidity, setCustomValidity ] =
98
- useState<
99
- React.ComponentProps<
100
- typeof ValidatedInputControl
101
- >[ 'customValidity' ]
102
- >( undefined );
103
82
 
104
83
  return (
105
84
  <ValidatedInputControl
@@ -122,34 +101,30 @@ export const Password: StoryObj< typeof ValidatedInputControl > = {
122
101
  setValue( newValue );
123
102
  onChange?.( newValue, ...rest );
124
103
  } }
125
- onValidate={ ( v ) => {
126
- if ( ! /\d/.test( v ?? '' ) ) {
127
- setCustomValidity( {
128
- type: 'invalid',
104
+ customValidity={ ( () => {
105
+ if ( ! /\d/.test( value ?? '' ) ) {
106
+ return {
107
+ type: 'invalid' as const,
129
108
  message:
130
109
  'Password must include at least one number.',
131
- } );
132
- return;
110
+ };
133
111
  }
134
- if ( ! /[A-Z]/.test( v ?? '' ) ) {
135
- setCustomValidity( {
136
- type: 'invalid',
112
+ if ( ! /[A-Z]/.test( value ?? '' ) ) {
113
+ return {
114
+ type: 'invalid' as const,
137
115
  message:
138
116
  'Password must include at least one capital letter.',
139
- } );
140
- return;
117
+ };
141
118
  }
142
- if ( ! /[!@£$%^&*#]/.test( v ?? '' ) ) {
143
- setCustomValidity( {
144
- type: 'invalid',
119
+ if ( ! /[!@£$%^&*#]/.test( value ?? '' ) ) {
120
+ return {
121
+ type: 'invalid' as const,
145
122
  message:
146
123
  'Password must include at least one symbol.',
147
- } );
148
- return;
124
+ };
149
125
  }
150
- setCustomValidity( undefined );
151
- } }
152
- customValidity={ customValidity }
126
+ return undefined;
127
+ } )() }
153
128
  />
154
129
  );
155
130
  },
@@ -37,32 +37,23 @@ 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 );
46
40
 
47
41
  return (
48
42
  <ValidatedNumberControl
49
43
  { ...args }
50
44
  value={ value }
51
- onChange={ ( newValue, ...rest ) => {
45
+ onChange={ ( newValue, extra ) => {
52
46
  setValue( newValue );
53
- onChange?.( newValue, ...rest );
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
- }
47
+ onChange?.( newValue, extra );
64
48
  } }
65
- customValidity={ customValidity }
49
+ customValidity={
50
+ value && parseInt( value.toString(), 10 ) % 2 !== 0
51
+ ? {
52
+ type: 'invalid',
53
+ message: 'Choose an even number.',
54
+ }
55
+ : undefined
56
+ }
66
57
  />
67
58
  );
68
59
  },
@@ -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', 'onValidate', 'customValidity' ] } />
19
+ <ArgTypes of={ ValidatedInputControl } include={ [ 'required', 'markWhenOptional', 'customValidity' ] } />
20
20
 
21
21
  ## Implementation
22
22
 
@@ -32,14 +32,14 @@ These components are designed to work with the native HTML5 [Constraint Validati
32
32
 
33
33
  ### No easy access to underlying validation APIs
34
34
 
35
- - The consumer does not have a simple way to trigger their custom validators at an arbitrary point in time. Currently, the validation timings for custom validators are handled by the component — first on `blur`, and then on every `change` after the field is considered "touched". Note that this limitation only applies to **custom** validators, not the standard attribute-based validators like `required` or `pattern`, which can be triggered at any time using the `reportValidity()` method on either the underlying control element or the wrapping `<form>` element.
35
+ - The consumer does not have a simple way to show validation messages at an arbitrary point in time, unless the fields are wrapped in a `form` element. Currently, when to show validation messages to the user are handled by the component — any messages are first made visible on `blur` after the field is considered "touched", or if the user tries to submit the enclosing `form`. Messages can also be triggered to show at any time by calling the `reportValidity()` method on the wrapping `<form>` element.
36
36
  - The consumer does not have direct access to the [`validity` object](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState) of the underlying element.
37
37
 
38
38
  We don't foresee these being needed much, but it is technically possible by the consumer accessing the target element's validation APIs via `ref`. Better docs or ergonomics can be added when we have actual use cases.
39
39
 
40
40
  ### Delegate elements
41
41
 
42
- The implementations for `ToggleGroupControl` and `CustomSelectControl` use a "delegate" element for validation, due to upstream limitations that prevent us from using the actual underlying elements for constraint validation. A delegate element in this context is a visually hidden form element that we "delegate" the Constraint Validation API concerns to.
42
+ The implementations for `ToggleGroupControl`, `CustomSelectControl`, and `FormTokenField` use a "delegate" element for validation, due to upstream limitations that prevent us from using the actual underlying elements for constraint validation. A delegate element in this context is a visually hidden form element that we "delegate" the Constraint Validation API concerns to.
43
43
 
44
44
  This is not ideal, but lets us maintain a consistent mechanism to scroll to the invalid field when attempting to submit, and block the form from submitting. It is hopefully fine as a stopgap, given the low amount of actual validation that will need happen on these two specific components.
45
45