', errors: [expectedError] },
// Custom label component.
{ code: '', options: [{ labelComponents: ['CustomLabel'] }], errors: [expectedError] },
+ { code: '', options: [{ labelComponents: ['???Label'] }], errors: [expectedError] },
{ code: '', options: [{ labelAttributes: ['label'], labelComponents: ['CustomLabel'] }], errors: [expectedError] },
{ code: '', settings: componentsSettings, errors: [expectedError] },
// Custom label attributes.
diff --git a/docs/rules/label-has-associated-control.md b/docs/rules/label-has-associated-control.md
index 9017f3e0..eacab54d 100644
--- a/docs/rules/label-has-associated-control.md
+++ b/docs/rules/label-has-associated-control.md
@@ -103,11 +103,11 @@ This rule takes one optional object argument of type object:
}
```
-`labelComponents` is a list of custom React Component names that should be checked for an associated control.
+`labelComponents` is a list of custom React Component names that should be checked for an associated control.[Glob format](https://linuxhint.com/bash_globbing_tutorial/) is also supported for specifying names (e.g., `Label*` matches `LabelComponent` but not `CustomLabel`, `????Label` matches `LinkLabel` but not `CustomLabel`).
`labelAttributes` is a list of attributes to check on the label component and its children for a label. Use this if you have a custom component that uses a string passed on a prop to render an HTML `label`, for example.
-`controlComponents` is a list of custom React Components names that will output an input element. [Glob format](https://linuxhint.com/bash_globbing_tutorial/) is also supported for specifying names (e.g., `Label*` matches `LabelComponent` but not `CustomLabel`, `????Label` matches `LinkLabel` but not `CustomLabel`).
+`controlComponents` is a list of custom React Components names that will output an input element. [Glob format](https://linuxhint.com/bash_globbing_tutorial/) is also supported for specifying names (e.g., `Input*` matches `InputCustom` but not `CustomInput`, `????Input` matches `TextInput` but not `CustomInput`).
`assert` asserts that the label has htmlFor, a nested label, both or either. Available options: `'htmlFor', 'nesting', 'both', 'either'`.
diff --git a/src/rules/label-has-associated-control.js b/src/rules/label-has-associated-control.js
index 8920e64e..8b3487db 100644
--- a/src/rules/label-has-associated-control.js
+++ b/src/rules/label-has-associated-control.js
@@ -11,6 +11,7 @@
import { hasProp, getProp, getPropValue } from 'jsx-ast-utils';
import type { JSXElement } from 'ast-types-flow';
+import minimatch from 'minimatch';
import { generateObjSchema, arraySchema } from '../util/schemas';
import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint';
import getElementType from '../util/getElementType';
@@ -66,13 +67,13 @@ export default ({
const options = context.options[0] || {};
const labelComponents = options.labelComponents || [];
const assertType = options.assert || 'either';
- const componentNames = ['label'].concat(labelComponents);
+ const labelComponentNames = ['label'].concat(labelComponents);
const elementType = getElementType(context);
const rule = (node: JSXElement) => {
- if (componentNames.indexOf(elementType(node.openingElement)) === -1) {
- return;
- }
+ const isLabelComponent = labelComponentNames.some((name) => minimatch(elementType(node.openingElement), name));
+ if (!isLabelComponent) return;
+
const controlComponents = [
'input',
'meter',