@wordpress/components 30.2.1-next.f34ab90e9.0 → 30.2.2-next.e256d081a.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 (36) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/build/context/context-connect.js.map +1 -1
  3. package/build/tabs/styles.js +5 -5
  4. package/build/tabs/styles.js.map +1 -1
  5. package/build/utils/font-size.js.map +1 -1
  6. package/build/utils/get-valid-children.js.map +1 -1
  7. package/build/validated-form-controls/control-with-error.js +16 -16
  8. package/build/validated-form-controls/control-with-error.js.map +1 -1
  9. package/build-module/context/context-connect.js.map +1 -1
  10. package/build-module/tabs/styles.js +6 -6
  11. package/build-module/tabs/styles.js.map +1 -1
  12. package/build-module/utils/font-size.js.map +1 -1
  13. package/build-module/utils/get-valid-children.js.map +1 -1
  14. package/build-module/validated-form-controls/control-with-error.js +16 -16
  15. package/build-module/validated-form-controls/control-with-error.js.map +1 -1
  16. package/build-types/context/context-connect.d.ts +2 -2
  17. package/build-types/context/context-connect.d.ts.map +1 -1
  18. package/build-types/tabs/styles.d.ts.map +1 -1
  19. package/build-types/utils/font-size.d.ts +2 -2
  20. package/build-types/utils/font-size.d.ts.map +1 -1
  21. package/build-types/utils/get-valid-children.d.ts +2 -2
  22. package/build-types/utils/get-valid-children.d.ts.map +1 -1
  23. package/build-types/validated-form-controls/components/stories/overview.story.d.ts.map +1 -1
  24. package/build-types/validated-form-controls/control-with-error.d.ts.map +1 -1
  25. package/build-types/validated-form-controls/test/control-with-error.d.ts +2 -0
  26. package/build-types/validated-form-controls/test/control-with-error.d.ts.map +1 -0
  27. package/package.json +19 -19
  28. package/src/context/context-connect.ts +2 -2
  29. package/src/tabs/styles.ts +2 -1
  30. package/src/tools-panel/stories/index.story.tsx +3 -3
  31. package/src/utils/font-size.ts +2 -2
  32. package/src/utils/get-valid-children.ts +4 -2
  33. package/src/validated-form-controls/components/stories/overview.story.tsx +109 -27
  34. package/src/validated-form-controls/control-with-error.tsx +19 -18
  35. package/src/validated-form-controls/test/control-with-error.tsx +224 -0
  36. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"names":["__","cloneElement","forwardRef","useEffect","useState","withIgnoreIMEEvents","ValidityIndicator","Fragment","_Fragment","jsxs","_jsxs","jsx","_jsx","appendRequiredIndicator","label","required","markWhenOptional","children","UnforwardedControlWithError","onValidate","customValidity","getValidityTarget","forwardedRef","errorMessage","setErrorMessage","statusMessage","setStatusMessage","isTouched","setIsTouched","validityTarget","showValidationMessage","validationMessage","addEventListener","removeEventListener","type","setCustomValidity","undefined","timer","setTimeout","message","clearTimeout","_customValidity$messa","onBlur","event","relatedTarget","currentTarget","contains","validity","valid","onChange","args","props","onKeyDown","key","className","ref","ControlWithError"],"sources":["@wordpress/components/src/validated-form-controls/control-with-error.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * External dependencies\n */\nimport {\n\tcloneElement,\n\tforwardRef,\n\tuseEffect,\n\tuseState,\n} from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events';\nimport type { ValidatedControlProps } from './components/types';\nimport { ValidityIndicator } from './validity-indicator';\n\nfunction appendRequiredIndicator(\n\tlabel: React.ReactNode,\n\trequired: boolean | undefined,\n\tmarkWhenOptional: boolean | undefined\n) {\n\tif ( required && ! markWhenOptional ) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ label } { `(${ __( 'Required' ) })` }\n\t\t\t</>\n\t\t);\n\t}\n\tif ( ! required && markWhenOptional ) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ label } { `(${ __( 'Optional' ) })` }\n\t\t\t</>\n\t\t);\n\t}\n\treturn label;\n}\n\n/**\n * HTML elements that support the Constraint Validation API.\n *\n * Here, we exclude HTMLButtonElement because although it does technically support the API,\n * normal buttons are actually exempted from any validation.\n * @see https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Form_validation\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement/willValidate\n */\ntype ValidityTarget =\n\t| HTMLFieldSetElement\n\t| HTMLInputElement\n\t| HTMLSelectElement\n\t| HTMLTextAreaElement;\n\nfunction UnforwardedControlWithError< C extends React.ReactElement >(\n\t{\n\t\trequired,\n\t\tmarkWhenOptional,\n\t\tonValidate,\n\t\tcustomValidity,\n\t\tgetValidityTarget,\n\t\tchildren,\n\t}: {\n\t\t/**\n\t\t * Whether the control is required.\n\t\t */\n\t\trequired?: boolean;\n\t\t/**\n\t\t * Label the control as \"optional\" when _not_ `required`, instead of the inverse.\n\t\t */\n\t\tmarkWhenOptional?: boolean;\n\t\t/**\n\t\t * The callback to run when the input should be validated.\n\t\t */\n\t\tonValidate?: () => void;\n\t\tcustomValidity?: ValidatedControlProps< unknown >[ 'customValidity' ];\n\t\t/**\n\t\t * A function that returns the actual element on which the validity data should be applied.\n\t\t */\n\t\tgetValidityTarget: () => ValidityTarget | null | undefined;\n\t\t/**\n\t\t * The control component to apply validation to.\n\t\t */\n\t\tchildren: C;\n\t},\n\tforwardedRef: React.ForwardedRef< HTMLDivElement >\n) {\n\tconst [ errorMessage, setErrorMessage ] = useState< string | undefined >();\n\tconst [ statusMessage, setStatusMessage ] = useState<\n\t\t| {\n\t\t\t\ttype: 'validating' | 'valid';\n\t\t\t\tmessage?: string;\n\t\t }\n\t\t| undefined\n\t>();\n\tconst [ isTouched, setIsTouched ] = useState( false );\n\n\t// Ensure that error messages are visible after user attemps to submit a form\n\t// with multiple invalid fields.\n\tuseEffect( () => {\n\t\tconst validityTarget = getValidityTarget();\n\t\tconst showValidationMessage = () =>\n\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\n\t\tvalidityTarget?.addEventListener( 'invalid', showValidationMessage );\n\n\t\treturn () => {\n\t\t\tvalidityTarget?.removeEventListener(\n\t\t\t\t'invalid',\n\t\t\t\tshowValidationMessage\n\t\t\t);\n\t\t};\n\t} );\n\n\tuseEffect( () => {\n\t\tif ( ! isTouched ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst validityTarget = getValidityTarget();\n\n\t\tif ( ! customValidity?.type ) {\n\t\t\tvalidityTarget?.setCustomValidity( '' );\n\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\t\t\tsetStatusMessage( undefined );\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( customValidity.type ) {\n\t\t\tcase 'validating': {\n\t\t\t\t// Wait before showing a validating state.\n\t\t\t\tconst timer = setTimeout( () => {\n\t\t\t\t\tsetStatusMessage( {\n\t\t\t\t\t\ttype: 'validating',\n\t\t\t\t\t\tmessage: customValidity.message,\n\t\t\t\t\t} );\n\t\t\t\t}, 1000 );\n\n\t\t\t\treturn () => clearTimeout( timer );\n\t\t\t}\n\t\t\tcase 'valid': {\n\t\t\t\tvalidityTarget?.setCustomValidity( '' );\n\t\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\n\t\t\t\tsetStatusMessage( {\n\t\t\t\t\ttype: 'valid',\n\t\t\t\t\tmessage: customValidity.message,\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'invalid': {\n\t\t\t\tvalidityTarget?.setCustomValidity(\n\t\t\t\t\tcustomValidity.message ?? ''\n\t\t\t\t);\n\t\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\n\t\t\t\tsetStatusMessage( undefined );\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t}, [\n\t\tisTouched,\n\t\tcustomValidity?.type,\n\t\tcustomValidity?.message,\n\t\tgetValidityTarget,\n\t] );\n\n\tconst onBlur = ( event: React.FocusEvent< HTMLDivElement > ) => {\n\t\t// Only consider \"blurred from the component\" if focus has fully left the wrapping div.\n\t\t// This prevents unnecessary blurs from components with multiple focusable elements.\n\t\tif (\n\t\t\t! event.relatedTarget ||\n\t\t\t! event.currentTarget.contains( event.relatedTarget )\n\t\t) {\n\t\t\tsetIsTouched( true );\n\n\t\t\tconst validityTarget = getValidityTarget();\n\n\t\t\t// Prevents a double flash of the native error tooltip when the control is already showing one.\n\t\t\tif ( ! validityTarget?.validity.valid ) {\n\t\t\t\tif ( ! errorMessage ) {\n\t\t\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tonValidate?.();\n\t\t}\n\t};\n\n\tconst onChange = ( ...args: unknown[] ) => {\n\t\tchildren.props.onChange?.( ...args );\n\n\t\t// Only validate incrementally if the field has blurred at least once,\n\t\t// or currently has an error message.\n\t\tif ( isTouched || errorMessage ) {\n\t\t\tonValidate?.();\n\t\t}\n\t};\n\n\tconst onKeyDown = ( event: React.KeyboardEvent< HTMLDivElement > ) => {\n\t\t// Ensures that custom validators are triggered when the user submits by pressing Enter,\n\t\t// without ever blurring the control.\n\t\tif ( event.key === 'Enter' ) {\n\t\t\tonValidate?.();\n\t\t}\n\t};\n\n\treturn (\n\t\t// Disable reason: Just listening to a bubbled event, not for interaction.\n\t\t// eslint-disable-next-line jsx-a11y/no-static-element-interactions\n\t\t<div\n\t\t\tclassName=\"components-validated-control\"\n\t\t\tref={ forwardedRef }\n\t\t\tonBlur={ onBlur }\n\t\t\tonKeyDown={ withIgnoreIMEEvents( onKeyDown ) }\n\t\t>\n\t\t\t{ cloneElement( children, {\n\t\t\t\tlabel: appendRequiredIndicator(\n\t\t\t\t\tchildren.props.label,\n\t\t\t\t\trequired,\n\t\t\t\t\tmarkWhenOptional\n\t\t\t\t),\n\t\t\t\tonChange,\n\t\t\t\trequired,\n\t\t\t} ) }\n\t\t\t<div aria-live=\"polite\">\n\t\t\t\t{ errorMessage && (\n\t\t\t\t\t<ValidityIndicator\n\t\t\t\t\t\ttype=\"invalid\"\n\t\t\t\t\t\tmessage={ errorMessage }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t\t{ ! errorMessage && statusMessage && (\n\t\t\t\t\t<ValidityIndicator\n\t\t\t\t\t\ttype={ statusMessage.type }\n\t\t\t\t\t\tmessage={ statusMessage.message }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport const ControlWithError = forwardRef( UnforwardedControlWithError );\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["usePrevious","__","cloneElement","forwardRef","useEffect","useState","withIgnoreIMEEvents","ValidityIndicator","Fragment","_Fragment","jsxs","_jsxs","jsx","_jsx","appendRequiredIndicator","label","required","markWhenOptional","children","UnforwardedControlWithError","onValidate","customValidity","getValidityTarget","forwardedRef","errorMessage","setErrorMessage","statusMessage","setStatusMessage","isTouched","setIsTouched","previousCustomValidityType","type","validityTarget","showValidationMessage","validationMessage","addEventListener","removeEventListener","setCustomValidity","undefined","timer","setTimeout","message","clearTimeout","_customValidity$messa","onBlur","event","relatedTarget","currentTarget","contains","onChange","args","props","onKeyDown","key","className","ref","ControlWithError"],"sources":["@wordpress/components/src/validated-form-controls/control-with-error.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { usePrevious } from '@wordpress/compose';\nimport { __ } from '@wordpress/i18n';\nimport {\n\tcloneElement,\n\tforwardRef,\n\tuseEffect,\n\tuseState,\n} from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events';\nimport type { ValidatedControlProps } from './components/types';\nimport { ValidityIndicator } from './validity-indicator';\n\nfunction appendRequiredIndicator(\n\tlabel: React.ReactNode,\n\trequired: boolean | undefined,\n\tmarkWhenOptional: boolean | undefined\n) {\n\tif ( required && ! markWhenOptional ) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ label } { `(${ __( 'Required' ) })` }\n\t\t\t</>\n\t\t);\n\t}\n\tif ( ! required && markWhenOptional ) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ label } { `(${ __( 'Optional' ) })` }\n\t\t\t</>\n\t\t);\n\t}\n\treturn label;\n}\n\n/**\n * HTML elements that support the Constraint Validation API.\n *\n * Here, we exclude HTMLButtonElement because although it does technically support the API,\n * normal buttons are actually exempted from any validation.\n * @see https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Form_validation\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement/willValidate\n */\ntype ValidityTarget =\n\t| HTMLFieldSetElement\n\t| HTMLInputElement\n\t| HTMLSelectElement\n\t| HTMLTextAreaElement;\n\nfunction UnforwardedControlWithError< C extends React.ReactElement >(\n\t{\n\t\trequired,\n\t\tmarkWhenOptional,\n\t\tonValidate,\n\t\tcustomValidity,\n\t\tgetValidityTarget,\n\t\tchildren,\n\t}: {\n\t\t/**\n\t\t * Whether the control is required.\n\t\t */\n\t\trequired?: boolean;\n\t\t/**\n\t\t * Label the control as \"optional\" when _not_ `required`, instead of the inverse.\n\t\t */\n\t\tmarkWhenOptional?: boolean;\n\t\t/**\n\t\t * The callback to run when the input should be validated.\n\t\t */\n\t\tonValidate?: () => void;\n\t\tcustomValidity?: ValidatedControlProps< unknown >[ 'customValidity' ];\n\t\t/**\n\t\t * A function that returns the actual element on which the validity data should be applied.\n\t\t */\n\t\tgetValidityTarget: () => ValidityTarget | null | undefined;\n\t\t/**\n\t\t * The control component to apply validation to.\n\t\t */\n\t\tchildren: C;\n\t},\n\tforwardedRef: React.ForwardedRef< HTMLDivElement >\n) {\n\tconst [ errorMessage, setErrorMessage ] = useState< string | undefined >();\n\tconst [ statusMessage, setStatusMessage ] = useState<\n\t\t| {\n\t\t\t\ttype: 'validating' | 'valid';\n\t\t\t\tmessage?: string;\n\t\t }\n\t\t| undefined\n\t>();\n\tconst [ isTouched, setIsTouched ] = useState( false );\n\tconst previousCustomValidityType = usePrevious( customValidity?.type );\n\n\t// Ensure that error messages are visible after user attemps to submit a form\n\t// with multiple invalid fields.\n\tuseEffect( () => {\n\t\tconst validityTarget = getValidityTarget();\n\t\tconst showValidationMessage = () =>\n\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\n\t\tvalidityTarget?.addEventListener( 'invalid', showValidationMessage );\n\n\t\treturn () => {\n\t\t\tvalidityTarget?.removeEventListener(\n\t\t\t\t'invalid',\n\t\t\t\tshowValidationMessage\n\t\t\t);\n\t\t};\n\t} );\n\n\tuseEffect( (): ReturnType< React.EffectCallback > => {\n\t\tif ( ! isTouched ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst validityTarget = getValidityTarget();\n\n\t\tif ( ! customValidity?.type ) {\n\t\t\tvalidityTarget?.setCustomValidity( '' );\n\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\t\t\tsetStatusMessage( undefined );\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( customValidity.type ) {\n\t\t\tcase 'validating': {\n\t\t\t\t// Wait before showing a validating state.\n\t\t\t\tconst timer = setTimeout( () => {\n\t\t\t\t\tvalidityTarget?.setCustomValidity( '' );\n\t\t\t\t\tsetErrorMessage( undefined );\n\n\t\t\t\t\tsetStatusMessage( {\n\t\t\t\t\t\ttype: 'validating',\n\t\t\t\t\t\tmessage: customValidity.message,\n\t\t\t\t\t} );\n\t\t\t\t}, 1000 );\n\n\t\t\t\treturn () => clearTimeout( timer );\n\t\t\t}\n\t\t\tcase 'valid': {\n\t\t\t\t// Ensures that we wait for any async responses before showing\n\t\t\t\t// a synchronously valid state.\n\t\t\t\tif ( previousCustomValidityType === 'valid' ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tvalidityTarget?.setCustomValidity( '' );\n\t\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\n\t\t\t\tsetStatusMessage( {\n\t\t\t\t\ttype: 'valid',\n\t\t\t\t\tmessage: customValidity.message,\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'invalid': {\n\t\t\t\tvalidityTarget?.setCustomValidity(\n\t\t\t\t\tcustomValidity.message ?? ''\n\t\t\t\t);\n\t\t\t\tsetErrorMessage( validityTarget?.validationMessage );\n\n\t\t\t\tsetStatusMessage( undefined );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}, [\n\t\tisTouched,\n\t\tcustomValidity?.type,\n\t\tcustomValidity?.message,\n\t\tgetValidityTarget,\n\t\tpreviousCustomValidityType,\n\t] );\n\n\tconst onBlur = ( event: React.FocusEvent< HTMLDivElement > ) => {\n\t\tif ( isTouched ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Only consider \"blurred from the component\" if focus has fully left the wrapping div.\n\t\t// This prevents unnecessary blurs from components with multiple focusable elements.\n\t\tif (\n\t\t\t! event.relatedTarget ||\n\t\t\t! event.currentTarget.contains( event.relatedTarget )\n\t\t) {\n\t\t\tsetIsTouched( true );\n\t\t\tonValidate?.();\n\t\t}\n\t};\n\n\tconst onChange = ( ...args: unknown[] ) => {\n\t\tchildren.props.onChange?.( ...args );\n\n\t\t// Only validate incrementally if the field has blurred at least once,\n\t\t// or currently has an error message.\n\t\tif ( isTouched || errorMessage ) {\n\t\t\tonValidate?.();\n\t\t}\n\t};\n\n\tconst onKeyDown = ( event: React.KeyboardEvent< HTMLDivElement > ) => {\n\t\t// Ensures that custom validators are triggered when the user submits by pressing Enter,\n\t\t// without ever blurring the control.\n\t\tif ( event.key === 'Enter' ) {\n\t\t\tonValidate?.();\n\t\t}\n\t};\n\n\treturn (\n\t\t// Disable reason: Just listening to a bubbled event, not for interaction.\n\t\t// eslint-disable-next-line jsx-a11y/no-static-element-interactions\n\t\t<div\n\t\t\tclassName=\"components-validated-control\"\n\t\t\tref={ forwardedRef }\n\t\t\tonBlur={ onBlur }\n\t\t\tonKeyDown={ withIgnoreIMEEvents( onKeyDown ) }\n\t\t>\n\t\t\t{ cloneElement( children, {\n\t\t\t\tlabel: appendRequiredIndicator(\n\t\t\t\t\tchildren.props.label,\n\t\t\t\t\trequired,\n\t\t\t\t\tmarkWhenOptional\n\t\t\t\t),\n\t\t\t\tonChange,\n\t\t\t\trequired,\n\t\t\t} ) }\n\t\t\t<div aria-live=\"polite\">\n\t\t\t\t{ errorMessage && (\n\t\t\t\t\t<ValidityIndicator\n\t\t\t\t\t\ttype=\"invalid\"\n\t\t\t\t\t\tmessage={ errorMessage }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t\t{ ! errorMessage && statusMessage && (\n\t\t\t\t\t<ValidityIndicator\n\t\t\t\t\t\ttype={ statusMessage.type }\n\t\t\t\t\t\tmessage={ statusMessage.message }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport const ControlWithError = forwardRef( UnforwardedControlWithError );\n"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { ForwardedRef, ReactChild, ReactNode } from 'react';
4
+ import type { ForwardedRef, ReactElement, ReactNode } from 'react';
5
5
  import type { WordPressComponentFromProps } from '.';
6
6
  type AcceptsTwoArgs<F extends (...args: any) => any, ErrorMessage = never> = Parameters<F>['length'] extends 2 ? {} : ErrorMessage;
7
7
  /**
@@ -28,7 +28,7 @@ export declare function contextConnectWithoutRef<P>(Component: (props: P) => JSX
28
28
  * @param Component The component to retrieve a namespace from.
29
29
  * @return The connected namespaces.
30
30
  */
31
- export declare function getConnectNamespace(Component: ReactChild | undefined | {}): string[];
31
+ export declare function getConnectNamespace(Component: ReactElement | number | string | undefined | {}): string[];
32
32
  /**
33
33
  * Checks to see if a component is connected within the Context system.
34
34
  *
@@ -1 +1 @@
1
- {"version":3,"file":"context-connect.d.ts","sourceRoot":"","sources":["../../src/context/context-connect.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAajE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,GAAG,CAAC;AAErD,KAAK,cAAc,CAClB,CAAC,SAAS,CAAE,GAAG,IAAI,EAAE,GAAG,KAAM,GAAG,EACjC,YAAY,GAAG,KAAK,IACjB,UAAU,CAAE,CAAC,CAAE,CAAE,QAAQ,CAAE,SAAS,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;AAM9D;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,CAAC,SAAS,CAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAE,GAAG,CAAE,KAAM,GAAG,CAAC,OAAO,GAAG,IAAI,EAExE,SAAS,EAAE,CAAC,GACX,cAAc,CACb,CAAC,EACD,8HAA8H,CAC9H,EACF,SAAS,EAAE,MAAM,2MAGjB;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAE,CAAC,EAC1C,SAAS,EAAE,CAAE,KAAK,EAAE,CAAC,KAAM,GAAG,CAAC,OAAO,GAAG,IAAI,EAC7C,SAAS,EAAE,MAAM,yCAGjB;AAgDD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,UAAU,GAAG,SAAS,GAAG,EAAE,GACpC,MAAM,EAAE,CAoBV;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,GACtB,OAAO,CAeT"}
1
+ {"version":3,"file":"context-connect.d.ts","sourceRoot":"","sources":["../../src/context/context-connect.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAanE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,GAAG,CAAC;AAErD,KAAK,cAAc,CAClB,CAAC,SAAS,CAAE,GAAG,IAAI,EAAE,GAAG,KAAM,GAAG,EACjC,YAAY,GAAG,KAAK,IACjB,UAAU,CAAE,CAAC,CAAE,CAAE,QAAQ,CAAE,SAAS,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;AAM9D;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,CAAC,SAAS,CAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAE,GAAG,CAAE,KAAM,GAAG,CAAC,OAAO,GAAG,IAAI,EAExE,SAAS,EAAE,CAAC,GACX,cAAc,CACb,CAAC,EACD,8HAA8H,CAC9H,EACF,SAAS,EAAE,MAAM,2MAGjB;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAE,CAAC,EAC1C,SAAS,EAAE,CAAE,KAAK,EAAE,CAAC,KAAM,GAAG,CAAC,OAAO,GAAG,IAAI,EAC7C,SAAS,EAAE,MAAM,yCAGjB;AAgDD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,EAAE,GACxD,MAAM,EAAE,CAoBV;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,GACtB,OAAO,CAeT"}
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/tabs/styles.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAS1C,eAAO,MAAM,aAAa;;;;;;UAuIzB,CAAC;AAEF,eAAO,MAAM,GAAG;;;;;;UAgFf,CAAC;AAEF,eAAO,MAAM,WAAW;;SA9MR,MACf,WAAS;2GAyNT,CAAC;AAEF,eAAO,MAAM,UAAU;;UAuBtB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;UAapB,CAAC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/tabs/styles.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAS1C,eAAO,MAAM,aAAa;;;;;;UAuIzB,CAAC;AAEF,eAAO,MAAM,GAAG;;;;;;UAiFf,CAAC;AAEF,eAAO,MAAM,WAAW;;SA/Md,MAAO,WACb;2GA0NH,CAAC;AAEF,eAAO,MAAM,UAAU;;UAuBtB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;UAapB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { CSSProperties, ReactText } from 'react';
4
+ import type { CSSProperties } from 'react';
5
5
  export type HeadingSize = 1 | 2 | 3 | 4 | 5 | 6 | '1' | '2' | '3' | '4' | '5' | '6';
6
6
  export declare const BASE_FONT_SIZE = 13;
7
7
  export declare const PRESET_FONT_SIZES: {
@@ -14,5 +14,5 @@ export declare const PRESET_FONT_SIZES: {
14
14
  };
15
15
  export declare const HEADING_FONT_SIZES: HeadingSize[];
16
16
  export declare function getFontSize(size?: CSSProperties['fontSize'] | keyof typeof PRESET_FONT_SIZES): string;
17
- export declare function getHeadingFontSize(size?: ReactText): string;
17
+ export declare function getHeadingFontSize(size?: number | string): string;
18
18
  //# sourceMappingURL=font-size.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"font-size.d.ts","sourceRoot":"","sources":["../../src/utils/font-size.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOtD,MAAM,MAAM,WAAW,GACpB,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAEP,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,eAAO,MAAM,iBAAiB;;;;;;;CAO7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,eAG5B,CAAC;AAEJ,wBAAgB,WAAW,CAC1B,IAAI,GACD,aAAa,CAAE,UAAU,CAAE,GAC3B,MAAM,OAAO,iBAAkC,GAChD,MAAM,CAiBR;AAED,wBAAgB,kBAAkB,CAAE,IAAI,GAAE,SAAa,GAAI,MAAM,CAOhE"}
1
+ {"version":3,"file":"font-size.d.ts","sourceRoot":"","sources":["../../src/utils/font-size.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAO3C,MAAM,MAAM,WAAW,GACpB,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAEP,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,eAAO,MAAM,iBAAiB;;;;;;;CAO7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,eAG5B,CAAC;AAEJ,wBAAgB,WAAW,CAC1B,IAAI,GACD,aAAa,CAAE,UAAU,CAAE,GAC3B,MAAM,OAAO,iBAAkC,GAChD,MAAM,CAiBR;AAED,wBAAgB,kBAAkB,CAAE,IAAI,GAAE,MAAM,GAAG,MAAU,GAAI,MAAM,CAOtE"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { ReactNode, ReactChild, ReactFragment, ReactPortal } from 'react';
4
+ import type { ReactNode, ReactElement, ReactPortal } from 'react';
5
5
  /**
6
6
  * Gets a collection of available children elements from a React component's children prop.
7
7
  *
@@ -9,5 +9,5 @@ import type { ReactNode, ReactChild, ReactFragment, ReactPortal } from 'react';
9
9
  *
10
10
  * @return An array of available children.
11
11
  */
12
- export declare function getValidChildren(children: ReactNode): Array<ReactChild | ReactFragment | ReactPortal>;
12
+ export declare function getValidChildren(children: ReactNode): Array<ReactElement | number | string | Iterable<ReactNode> | ReactPortal>;
13
13
  //# sourceMappingURL=get-valid-children.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-valid-children.d.ts","sourceRoot":"","sources":["../../src/utils/get-valid-children.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAO/E;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,SAAS,GACjB,KAAK,CAAE,UAAU,GAAG,aAAa,GAAG,WAAW,CAAE,CAQnD"}
1
+ {"version":3,"file":"get-valid-children.d.ts","sourceRoot":"","sources":["../../src/utils/get-valid-children.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAOlE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,SAAS,GACjB,KAAK,CACP,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAE,SAAS,CAAE,GAAG,WAAW,CACpE,CAQA"}
@@ -1 +1 @@
1
- {"version":3,"file":"overview.story.d.ts","sourceRoot":"","sources":["../../../../src/validated-form-controls/components/stories/overview.story.tsx"],"names":[],"mappings":"AAKA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,IAAI,CAAC;AAE3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAE,OAAO,gBAAgB,CAIxC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAE,OAAO,gBAAgB,CAAE,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,KA0DlC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,KAmCrC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAE,OAAO,qBAAqB,CA8DnE,CAAC"}
1
+ {"version":3,"file":"overview.story.d.ts","sourceRoot":"","sources":["../../../../src/validated-form-controls/components/stories/overview.story.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AASvD;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,IAAI,CAAC;AAE3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAE,OAAO,gBAAgB,CAIxC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAE,OAAO,gBAAgB,CAAE,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,KA0DlC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,KAmCrC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAE,OAAO,qBAAqB,CA8DnE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"control-with-error.d.ts","sourceRoot":"","sources":["../../src/validated-form-controls/control-with-error.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAyBhE;;;;;;;GAOG;AACH,KAAK,cAAc,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,CAAC;AAgMvB,eAAO,MAAM,gBAAgB;IArL3B;;OAEG;eACQ,OAAO;IAClB;;OAEG;uBACgB,OAAO;IAC1B;;OAEG;iBACU,MAAM,IAAI;qBACN,qBAAqB,CAAE,OAAO,CAAE,CAAE,gBAAgB,CAAE;IACrE;;OAEG;uBACgB,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS;IAC1D;;OAEG;;kDAkKoE,CAAC"}
1
+ {"version":3,"file":"control-with-error.d.ts","sourceRoot":"","sources":["../../src/validated-form-controls/control-with-error.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAyBhE;;;;;;;GAOG;AACH,KAAK,cAAc,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,CAAC;AAoMvB,eAAO,MAAM,gBAAgB;IAzL3B;;OAEG;eACQ,OAAO;IAClB;;OAEG;uBACgB,OAAO;IAC1B;;OAEG;iBACU,MAAM,IAAI;qBACN,qBAAqB,CAAE,OAAO,CAAE,CAAE,gBAAgB,CAAE;IACrE;;OAEG;uBACgB,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS;IAC1D;;OAEG;;kDAsKoE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=control-with-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-with-error.d.ts","sourceRoot":"","sources":["../../../src/validated-form-controls/test/control-with-error.tsx"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/components",
3
- "version": "30.2.1-next.f34ab90e9.0",
3
+ "version": "30.2.2-next.e256d081a.0",
4
4
  "description": "UI components for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -44,23 +44,23 @@
44
44
  "@types/gradient-parser": "1.1.0",
45
45
  "@types/highlight-words-core": "1.2.1",
46
46
  "@use-gesture/react": "^10.3.1",
47
- "@wordpress/a11y": "^4.29.1-next.f34ab90e9.0",
48
- "@wordpress/compose": "^7.29.1-next.f34ab90e9.0",
49
- "@wordpress/date": "^5.29.1-next.f34ab90e9.0",
50
- "@wordpress/deprecated": "^4.29.1-next.f34ab90e9.0",
51
- "@wordpress/dom": "^4.29.1-next.f34ab90e9.0",
52
- "@wordpress/element": "^6.29.1-next.f34ab90e9.0",
53
- "@wordpress/escape-html": "^3.29.1-next.f34ab90e9.0",
54
- "@wordpress/hooks": "^4.29.1-next.f34ab90e9.0",
55
- "@wordpress/html-entities": "^4.29.1-next.f34ab90e9.0",
56
- "@wordpress/i18n": "^6.2.1-next.f34ab90e9.0",
57
- "@wordpress/icons": "^10.29.1-next.f34ab90e9.0",
58
- "@wordpress/is-shallow-equal": "^5.29.1-next.f34ab90e9.0",
59
- "@wordpress/keycodes": "^4.29.1-next.f34ab90e9.0",
60
- "@wordpress/primitives": "^4.29.1-next.f34ab90e9.0",
61
- "@wordpress/private-apis": "^1.29.1-next.f34ab90e9.0",
62
- "@wordpress/rich-text": "^7.29.1-next.f34ab90e9.0",
63
- "@wordpress/warning": "^3.29.1-next.f34ab90e9.0",
47
+ "@wordpress/a11y": "^4.29.1-next.e256d081a.0",
48
+ "@wordpress/compose": "^7.29.1-next.e256d081a.0",
49
+ "@wordpress/date": "^5.30.1-next.e256d081a.0",
50
+ "@wordpress/deprecated": "^4.29.1-next.e256d081a.0",
51
+ "@wordpress/dom": "^4.29.1-next.e256d081a.0",
52
+ "@wordpress/element": "^6.29.1-next.e256d081a.0",
53
+ "@wordpress/escape-html": "^3.29.1-next.e256d081a.0",
54
+ "@wordpress/hooks": "^4.29.1-next.e256d081a.0",
55
+ "@wordpress/html-entities": "^4.29.1-next.e256d081a.0",
56
+ "@wordpress/i18n": "^6.2.1-next.e256d081a.0",
57
+ "@wordpress/icons": "^10.29.1-next.e256d081a.0",
58
+ "@wordpress/is-shallow-equal": "^5.29.1-next.e256d081a.0",
59
+ "@wordpress/keycodes": "^4.29.1-next.e256d081a.0",
60
+ "@wordpress/primitives": "^4.29.1-next.e256d081a.0",
61
+ "@wordpress/private-apis": "^1.29.1-next.e256d081a.0",
62
+ "@wordpress/rich-text": "^7.29.1-next.e256d081a.0",
63
+ "@wordpress/warning": "^3.29.1-next.e256d081a.0",
64
64
  "change-case": "^4.1.2",
65
65
  "clsx": "^2.1.1",
66
66
  "colord": "^2.7.0",
@@ -86,5 +86,5 @@
86
86
  "publishConfig": {
87
87
  "access": "public"
88
88
  },
89
- "gitHead": "91f58004986ec6faf118825f925ac7873d171986"
89
+ "gitHead": "7d529ba9a461795d5f1572d3856de33f744287c2"
90
90
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { ForwardedRef, ReactChild, ReactNode } from 'react';
4
+ import type { ForwardedRef, ReactElement, ReactNode } from 'react';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -114,7 +114,7 @@ function _contextConnect<
114
114
  * @return The connected namespaces.
115
115
  */
116
116
  export function getConnectNamespace(
117
- Component: ReactChild | undefined | {}
117
+ Component: ReactElement | number | string | undefined | {}
118
118
  ): string[] {
119
119
  if ( ! Component ) {
120
120
  return [];
@@ -7,7 +7,7 @@ import * as Ariakit from '@ariakit/react';
7
7
  /**
8
8
  * Internal dependencies
9
9
  */
10
- import { COLORS, CONFIG } from '../utils';
10
+ import { COLORS, CONFIG, font } from '../utils';
11
11
  import { space } from '../utils/space';
12
12
  import Icon from '../icon';
13
13
 
@@ -163,6 +163,7 @@ export const Tab = styled( Ariakit.Tab )`
163
163
  cursor: pointer;
164
164
  line-height: 1.2; // Characters in some languages (e.g. Japanese) may have a native higher line-height.
165
165
  font-weight: 400;
166
+ font-size: ${ font( 'default.fontSize' ) };
166
167
  color: ${ COLORS.theme.foreground };
167
168
 
168
169
  &[aria-disabled='true'] {
@@ -54,7 +54,7 @@ export const Default: StoryFn< typeof ToolsPanel > = ( {
54
54
  const [ height, setHeight ] = useState< string | undefined >();
55
55
  const [ minHeight, setMinHeight ] = useState< string | undefined >();
56
56
  const [ width, setWidth ] = useState< string | undefined >();
57
- const [ scale, setScale ] = useState< React.ReactText | undefined >();
57
+ const [ scale, setScale ] = useState< number | string | undefined >();
58
58
 
59
59
  const resetAll: typeof resetAllProp = ( filters ) => {
60
60
  setHeight( undefined );
@@ -414,7 +414,7 @@ export const WithConditionalDefaultControl: StoryFn< typeof ToolsPanel > = ( {
414
414
  } ) => {
415
415
  const [ attributes, setAttributes ] = useState< {
416
416
  height?: string;
417
- scale?: React.ReactText;
417
+ scale?: number | string;
418
418
  } >( {} );
419
419
  const { height, scale } = attributes;
420
420
 
@@ -512,7 +512,7 @@ export const WithConditionallyRenderedControl: StoryFn<
512
512
  > = ( { resetAll: resetAllProp, panelId, ...props } ) => {
513
513
  const [ attributes, setAttributes ] = useState< {
514
514
  height?: string;
515
- scale?: React.ReactText;
515
+ scale?: number | string;
516
516
  } >( {} );
517
517
  const { height, scale } = attributes;
518
518
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { CSSProperties, ReactText } from 'react';
4
+ import type { CSSProperties } from 'react';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -61,7 +61,7 @@ export function getFontSize(
61
61
  return `calc(${ ratio } * ${ CONFIG.fontSize })`;
62
62
  }
63
63
 
64
- export function getHeadingFontSize( size: ReactText = 3 ): string {
64
+ export function getHeadingFontSize( size: number | string = 3 ): string {
65
65
  if ( ! HEADING_FONT_SIZES.includes( size as HeadingSize ) ) {
66
66
  return getFontSize( size );
67
67
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { ReactNode, ReactChild, ReactFragment, ReactPortal } from 'react';
4
+ import type { ReactNode, ReactElement, ReactPortal } from 'react';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -17,7 +17,9 @@ import { Children, isValidElement } from '@wordpress/element';
17
17
  */
18
18
  export function getValidChildren(
19
19
  children: ReactNode
20
- ): Array< ReactChild | ReactFragment | ReactPortal > {
20
+ ): Array<
21
+ ReactElement | number | string | Iterable< ReactNode > | ReactPortal
22
+ > {
21
23
  if ( typeof children === 'string' ) {
22
24
  return [ children ];
23
25
  }
@@ -1,12 +1,14 @@
1
1
  /**
2
- * WordPress dependencies
2
+ * External dependencies
3
3
  */
4
- import { useRef, useCallback, useState } from '@wordpress/element';
4
+ import type { Meta, StoryObj } from '@storybook/react';
5
+ import { expect, userEvent, waitFor, within } from '@storybook/test';
5
6
 
6
7
  /**
7
- * External dependencies
8
+ * WordPress dependencies
8
9
  */
9
- import type { Meta, StoryObj } from '@storybook/react';
10
+ import { useRef, useCallback, useState } from '@wordpress/element';
11
+ import { debounce } from '@wordpress/compose';
10
12
 
11
13
  /**
12
14
  * Internal dependencies
@@ -14,7 +16,6 @@ import type { Meta, StoryObj } from '@storybook/react';
14
16
  import { ValidatedInputControl } from '..';
15
17
  import { formDecorator } from './story-utils';
16
18
  import type { ControlWithError } from '../../control-with-error';
17
- import { debounce } from '@wordpress/compose';
18
19
 
19
20
  const meta: Meta< typeof ControlWithError > = {
20
21
  title: 'Components/Selection & Input/Validated Form Controls/Overview',
@@ -166,24 +167,19 @@ export const AsyncValidation: StoryObj< typeof ValidatedInputControl > = {
166
167
  } );
167
168
 
168
169
  clearTimeout( timeoutRef.current );
169
- timeoutRef.current = setTimeout(
170
- () => {
171
- if ( v?.toString().toLowerCase() === 'error' ) {
172
- setCustomValidity( {
173
- type: 'invalid',
174
- message: 'The word "error" is not allowed.',
175
- } );
176
- } else {
177
- setCustomValidity( {
178
- type: 'valid',
179
- message: 'Validated',
180
- } );
181
- }
182
- },
183
- // Mimics a random server response time.
184
- // eslint-disable-next-line no-restricted-syntax
185
- Math.random() < 0.5 ? 1500 : 300
186
- );
170
+ timeoutRef.current = setTimeout( () => {
171
+ if ( v?.toString().toLowerCase() === 'error' ) {
172
+ setCustomValidity( {
173
+ type: 'invalid',
174
+ message: 'The word "error" is not allowed.',
175
+ } );
176
+ } else {
177
+ setCustomValidity( {
178
+ type: 'valid',
179
+ message: 'Validated',
180
+ } );
181
+ }
182
+ }, 1500 );
187
183
  }, 500 ),
188
184
  []
189
185
  );
@@ -200,9 +196,95 @@ export const AsyncValidation: StoryObj< typeof ValidatedInputControl > = {
200
196
  />
201
197
  );
202
198
  },
199
+ args: {
200
+ label: 'Text',
201
+ help: 'The word "error" will trigger an error asynchronously.',
202
+ required: true,
203
+ },
203
204
  };
204
- AsyncValidation.args = {
205
- label: 'Text',
206
- help: 'The word "error" will trigger an error asynchronously.',
207
- required: true,
205
+
206
+ // Not exported - Only for testing purposes.
207
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
208
+ const AsyncValidationWithTest: StoryObj< typeof ValidatedInputControl > = {
209
+ ...AsyncValidation,
210
+ play: async ( { canvasElement } ) => {
211
+ const canvas = within( canvasElement );
212
+ await userEvent.click( canvas.getByRole( 'textbox' ) );
213
+ await userEvent.type( canvas.getByRole( 'textbox' ), 'valid text', {
214
+ delay: 10,
215
+ } );
216
+ await userEvent.tab();
217
+
218
+ await waitFor(
219
+ () => {
220
+ expect( canvas.getByText( 'Validated' ) ).toBeVisible();
221
+ },
222
+ { timeout: 2500 }
223
+ );
224
+
225
+ await new Promise( ( resolve ) => setTimeout( resolve, 500 ) );
226
+ await userEvent.clear( canvas.getByRole( 'textbox' ) );
227
+
228
+ // Should show validating state when transitioning from valid to invalid.
229
+ await waitFor(
230
+ () => {
231
+ expect( canvas.getByText( 'Validating...' ) ).toBeVisible();
232
+ },
233
+ { timeout: 2500 }
234
+ );
235
+
236
+ await waitFor(
237
+ () => {
238
+ expect(
239
+ canvas.getByText( 'Please fill out this field.' )
240
+ ).toBeVisible();
241
+ },
242
+ { timeout: 2500 }
243
+ );
244
+
245
+ // Should not show validating state if there were no changes
246
+ // after a valid/invalid state was already shown.
247
+ await new Promise( ( resolve ) => setTimeout( resolve, 1500 ) );
248
+ await expect(
249
+ canvas.queryByText( 'Validating...' )
250
+ ).not.toBeInTheDocument();
251
+
252
+ await userEvent.type( canvas.getByRole( 'textbox' ), 'e', {
253
+ delay: 10,
254
+ } );
255
+
256
+ // Should not show valid state if server has not yet responded.
257
+ await expect(
258
+ canvas.queryByText( 'Validated' )
259
+ ).not.toBeInTheDocument();
260
+
261
+ // Should show validating state when transitioning from invalid to valid.
262
+ await waitFor(
263
+ () => {
264
+ expect( canvas.getByText( 'Validating...' ) ).toBeVisible();
265
+ },
266
+ { timeout: 2500 }
267
+ );
268
+
269
+ await waitFor(
270
+ () => {
271
+ expect( canvas.getByText( 'Validated' ) ).toBeVisible();
272
+ },
273
+ { timeout: 2500 }
274
+ );
275
+
276
+ await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) );
277
+ await userEvent.type( canvas.getByRole( 'textbox' ), 'rror', {
278
+ delay: 10,
279
+ } );
280
+
281
+ await waitFor(
282
+ () => {
283
+ expect(
284
+ canvas.getByText( 'The word "error" is not allowed.' )
285
+ ).toBeVisible();
286
+ },
287
+ { timeout: 2500 }
288
+ );
289
+ },
208
290
  };
@@ -1,11 +1,8 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
+ import { usePrevious } from '@wordpress/compose';
4
5
  import { __ } from '@wordpress/i18n';
5
-
6
- /**
7
- * External dependencies
8
- */
9
6
  import {
10
7
  cloneElement,
11
8
  forwardRef,
@@ -98,6 +95,7 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
98
95
  | undefined
99
96
  >();
100
97
  const [ isTouched, setIsTouched ] = useState( false );
98
+ const previousCustomValidityType = usePrevious( customValidity?.type );
101
99
 
102
100
  // Ensure that error messages are visible after user attemps to submit a form
103
101
  // with multiple invalid fields.
@@ -116,7 +114,7 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
116
114
  };
117
115
  } );
118
116
 
119
- useEffect( () => {
117
+ useEffect( (): ReturnType< React.EffectCallback > => {
120
118
  if ( ! isTouched ) {
121
119
  return;
122
120
  }
@@ -134,6 +132,9 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
134
132
  case 'validating': {
135
133
  // Wait before showing a validating state.
136
134
  const timer = setTimeout( () => {
135
+ validityTarget?.setCustomValidity( '' );
136
+ setErrorMessage( undefined );
137
+
137
138
  setStatusMessage( {
138
139
  type: 'validating',
139
140
  message: customValidity.message,
@@ -143,6 +144,12 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
143
144
  return () => clearTimeout( timer );
144
145
  }
145
146
  case 'valid': {
147
+ // Ensures that we wait for any async responses before showing
148
+ // a synchronously valid state.
149
+ if ( previousCustomValidityType === 'valid' ) {
150
+ break;
151
+ }
152
+
146
153
  validityTarget?.setCustomValidity( '' );
147
154
  setErrorMessage( validityTarget?.validationMessage );
148
155
 
@@ -150,7 +157,7 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
150
157
  type: 'valid',
151
158
  message: customValidity.message,
152
159
  } );
153
- return;
160
+ break;
154
161
  }
155
162
  case 'invalid': {
156
163
  validityTarget?.setCustomValidity(
@@ -159,7 +166,7 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
159
166
  setErrorMessage( validityTarget?.validationMessage );
160
167
 
161
168
  setStatusMessage( undefined );
162
- return undefined;
169
+ break;
163
170
  }
164
171
  }
165
172
  }, [
@@ -167,9 +174,14 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
167
174
  customValidity?.type,
168
175
  customValidity?.message,
169
176
  getValidityTarget,
177
+ previousCustomValidityType,
170
178
  ] );
171
179
 
172
180
  const onBlur = ( event: React.FocusEvent< HTMLDivElement > ) => {
181
+ if ( isTouched ) {
182
+ return;
183
+ }
184
+
173
185
  // Only consider "blurred from the component" if focus has fully left the wrapping div.
174
186
  // This prevents unnecessary blurs from components with multiple focusable elements.
175
187
  if (
@@ -177,17 +189,6 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
177
189
  ! event.currentTarget.contains( event.relatedTarget )
178
190
  ) {
179
191
  setIsTouched( true );
180
-
181
- const validityTarget = getValidityTarget();
182
-
183
- // Prevents a double flash of the native error tooltip when the control is already showing one.
184
- if ( ! validityTarget?.validity.valid ) {
185
- if ( ! errorMessage ) {
186
- setErrorMessage( validityTarget?.validationMessage );
187
- }
188
- return;
189
- }
190
-
191
192
  onValidate?.();
192
193
  }
193
194
  };