@elastic/eslint-plugin-eui 2.5.0 → 2.6.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.
package/README.md CHANGED
@@ -160,8 +160,13 @@ Ensure that appropriate aria-attributes are set for `EuiBetaBadge`, `EuiButtonIc
160
160
  Ensure `EuiTooltip` components are anchored to elements that can receive keyboard focus, making them accessible to all users. When using non-interactive elements (like `span`or `EuiText`) as tooltip anchors, they must include `tabIndex={0}` to be keyboard-focusable. For better accessibility, prefer using semantic interactive components (like `EuiButton` or `EuiLink`) which are focusable by default.
161
161
 
162
162
  ### `@elastic/eui/accessible-interactive-element`
163
+
163
164
  Ensure interactive EUI components (like e.g. `EuiLink`, `EuiButton`, `EuiRadio`) remain accessible by prohibiting `tabIndex={-1}`, which removes them from keyboard navigation.
164
165
 
166
+ ### `@elastic/eui/require-table-caption`
167
+
168
+ Ensure `EuiInMemoryTable`, `EuiBasicTable` have a `tableCaption` property for accessibility.
169
+
165
170
  ## Testing
166
171
 
167
172
  ### Running unit tests
package/lib/cjs/index.js CHANGED
@@ -12,6 +12,7 @@ var _no_unnamed_interactive_element = require("./rules/a11y/no_unnamed_interacti
12
12
  var _tooltip_focusable_anchor = require("./rules/a11y/tooltip_focusable_anchor");
13
13
  var _callout_announce_on_mount = require("./rules/a11y/callout_announce_on_mount");
14
14
  var _accessible_interactive_element = require("./rules/a11y/accessible_interactive_element");
15
+ var _require_table_caption = require("./rules/a11y/require_table_caption");
15
16
  /*
16
17
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
17
18
  * or more contributor license agreements. Licensed under the Elastic License
@@ -33,7 +34,8 @@ const config = {
33
34
  'callout-announce-on-mount': _callout_announce_on_mount.CallOutAnnounceOnMount,
34
35
  'no-unnamed-interactive-element': _no_unnamed_interactive_element.NoUnnamedInteractiveElement,
35
36
  'tooltip-focusable-anchor': _tooltip_focusable_anchor.TooltipFocusableAnchor,
36
- 'accessible-interactive-element': _accessible_interactive_element.AccessibleInteractiveElements
37
+ 'accessible-interactive-element': _accessible_interactive_element.AccessibleInteractiveElements,
38
+ 'require-table-caption': _require_table_caption.RequireTableCaption
37
39
  },
38
40
  configs: {
39
41
  recommended: {
@@ -50,7 +52,8 @@ const config = {
50
52
  '@elastic/eui/callout-announce-on-mount': 'warn',
51
53
  '@elastic/eui/no-unnamed-interactive-element': 'warn',
52
54
  '@elastic/eui/tooltip-focusable-anchor': 'warn',
53
- '@elastic/eui/accessible-interactive-element': 'warn'
55
+ '@elastic/eui/accessible-interactive-element': 'warn',
56
+ '@elastic/eui/require-table-caption': 'warn'
54
57
  }
55
58
  }
56
59
  }
@@ -0,0 +1,3 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ export declare const RequireTableCaption: ESLintUtils.RuleModule<"missingTableCaption", [], unknown, ESLintUtils.RuleListener>;
3
+ //# sourceMappingURL=require_table_caption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require_table_caption.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/require_table_caption.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAiB,MAAM,0BAA0B,CAAC;AAKtE,eAAO,MAAM,mBAAmB,sFA+C9B,CAAC"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RequireTableCaption = void 0;
7
+ var _utils = require("@typescript-eslint/utils");
8
+ /*
9
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
10
+ * or more contributor license agreements. Licensed under the Elastic License
11
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
12
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
13
+ * Side Public License, v 1.
14
+ */
15
+
16
+ const TABLE_COMPONENTS = ['EuiInMemoryTable', 'EuiBasicTable'];
17
+ const TABLE_CAPTION_PROP = 'tableCaption';
18
+ const RequireTableCaption = exports.RequireTableCaption = _utils.ESLintUtils.RuleCreator.withoutDocs({
19
+ create(context) {
20
+ return {
21
+ JSXOpeningElement(node) {
22
+ if (node.name.type !== 'JSXIdentifier') {
23
+ return;
24
+ }
25
+ const component = node.name.name;
26
+ if (!TABLE_COMPONENTS.includes(component)) {
27
+ return;
28
+ }
29
+ const hasTableCaption = node.attributes.some(attr => attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && attr.name.name === TABLE_CAPTION_PROP);
30
+ if (!hasTableCaption) {
31
+ context.report({
32
+ node,
33
+ messageId: 'missingTableCaption',
34
+ data: {
35
+ component
36
+ }
37
+ });
38
+ }
39
+ }
40
+ };
41
+ },
42
+ defaultOptions: [],
43
+ meta: {
44
+ type: 'problem',
45
+ docs: {
46
+ description: `Ensure ${TABLE_COMPONENTS.join(', ')} have a \`${TABLE_CAPTION_PROP}\` prop for accessibility.`
47
+ },
48
+ schema: [],
49
+ messages: {
50
+ missingTableCaption: ['{{component}} must include a `tableCaption` prop for accessibility.', '', 'Example:', ' <{{component}} tableCaption="Descriptive caption for the table" ... />'].join('\n')
51
+ }
52
+ }
53
+ });
package/lib/esm/index.js CHANGED
@@ -19,6 +19,7 @@ const no_unnamed_interactive_element_1 = require("./rules/a11y/no_unnamed_intera
19
19
  const tooltip_focusable_anchor_1 = require("./rules/a11y/tooltip_focusable_anchor");
20
20
  const callout_announce_on_mount_1 = require("./rules/a11y/callout_announce_on_mount");
21
21
  const accessible_interactive_element_1 = require("./rules/a11y/accessible_interactive_element");
22
+ const require_table_caption_1 = require("./rules/a11y/require_table_caption");
22
23
  const config = {
23
24
  rules: {
24
25
  'href-or-on-click': href_or_on_click_1.HrefOnClick,
@@ -33,6 +34,7 @@ const config = {
33
34
  'no-unnamed-interactive-element': no_unnamed_interactive_element_1.NoUnnamedInteractiveElement,
34
35
  'tooltip-focusable-anchor': tooltip_focusable_anchor_1.TooltipFocusableAnchor,
35
36
  'accessible-interactive-element': accessible_interactive_element_1.AccessibleInteractiveElements,
37
+ 'require-table-caption': require_table_caption_1.RequireTableCaption,
36
38
  },
37
39
  configs: {
38
40
  recommended: {
@@ -50,6 +52,7 @@ const config = {
50
52
  '@elastic/eui/no-unnamed-interactive-element': 'warn',
51
53
  '@elastic/eui/tooltip-focusable-anchor': 'warn',
52
54
  '@elastic/eui/accessible-interactive-element': 'warn',
55
+ '@elastic/eui/require-table-caption': 'warn',
53
56
  },
54
57
  },
55
58
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAGH,+DAAuD;AACvD,iFAA2E;AAC3E,uDAAkD;AAElD,8FAAuF;AACvF,0FAAoF;AACpF,wFAA4F;AAC5F,0EAAoE;AACpE,gFAA0E;AAC1E,gGAA0F;AAC1F,oFAA+E;AAC/E,sFAAgF;AAChF,gGAA4F;AAE5F,MAAM,MAAM,GAAG;IACb,KAAK,EAAE;QACL,kBAAkB,EAAE,8BAAW;QAC/B,2BAA2B,EAAE,kDAAsB;QACnD,cAAc,EAAE,yBAAU;QAC1B,+BAA+B,EAAE,yDAAyB;QAC1D,6BAA6B,EAAE,sDAAwB;QACvD,4BAA4B,EAAE,8DAAiC;QAC/D,qBAAqB,EAAE,sCAAgB;QACvC,wBAAwB,EAAG,4CAAmB;QAC9C,2BAA2B,EAAE,kDAAsB;QACnD,gCAAgC,EAAE,4DAA2B;QAC7D,0BAA0B,EAAE,iDAAsB;QAClD,gCAAgC,EAAE,8DAA6B;KAChE;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,4BAA4B,CAAC;YACvC,KAAK,EAAE;gBACL,+BAA+B,EAAE,MAAM;gBACvC,wCAAwC,EAAE,MAAM;gBAChD,2BAA2B,EAAE,MAAM;gBACnC,4CAA4C,EAAE,MAAM;gBACpD,0CAA0C,EAAE,MAAM;gBAClD,yCAAyC,EAAE,MAAM;gBACjD,kCAAkC,EAAE,MAAM;gBAC1C,qCAAqC,EAAE,MAAM;gBAC7C,wCAAwC,EAAE,MAAM;gBAChD,6CAA6C,EAAE,MAAM;gBACrD,uCAAuC,EAAE,MAAM;gBAC/C,6CAA6C,EAAE,MAAM;aACtD;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAGH,+DAAuD;AACvD,iFAA2E;AAC3E,uDAAkD;AAElD,8FAAuF;AACvF,0FAAoF;AACpF,wFAA4F;AAC5F,0EAAoE;AACpE,gFAA0E;AAC1E,gGAA0F;AAC1F,oFAA+E;AAC/E,sFAAgF;AAChF,gGAA4F;AAC5F,8EAAyE;AAEzE,MAAM,MAAM,GAAG;IACb,KAAK,EAAE;QACL,kBAAkB,EAAE,8BAAW;QAC/B,2BAA2B,EAAE,kDAAsB;QACnD,cAAc,EAAE,yBAAU;QAC1B,+BAA+B,EAAE,yDAAyB;QAC1D,6BAA6B,EAAE,sDAAwB;QACvD,4BAA4B,EAAE,8DAAiC;QAC/D,qBAAqB,EAAE,sCAAgB;QACvC,wBAAwB,EAAG,4CAAmB;QAC9C,2BAA2B,EAAE,kDAAsB;QACnD,gCAAgC,EAAE,4DAA2B;QAC7D,0BAA0B,EAAE,iDAAsB;QAClD,gCAAgC,EAAE,8DAA6B;QAC/D,uBAAuB,EAAE,2CAAmB;KAC7C;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,4BAA4B,CAAC;YACvC,KAAK,EAAE;gBACL,+BAA+B,EAAE,MAAM;gBACvC,wCAAwC,EAAE,MAAM;gBAChD,2BAA2B,EAAE,MAAM;gBACnC,4CAA4C,EAAE,MAAM;gBACpD,0CAA0C,EAAE,MAAM;gBAClD,yCAAyC,EAAE,MAAM;gBACjD,kCAAkC,EAAE,MAAM;gBAC1C,qCAAqC,EAAE,MAAM;gBAC7C,wCAAwC,EAAE,MAAM;gBAChD,6CAA6C,EAAE,MAAM;gBACrD,uCAAuC,EAAE,MAAM;gBAC/C,6CAA6C,EAAE,MAAM;gBACrD,oCAAoC,EAAE,MAAM;aAC7C;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ export declare const RequireTableCaption: ESLintUtils.RuleModule<"missingTableCaption", [], unknown, ESLintUtils.RuleListener>;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
4
+ * or more contributor license agreements. Licensed under the Elastic License
5
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
6
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
7
+ * Side Public License, v 1.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.RequireTableCaption = void 0;
11
+ const utils_1 = require("@typescript-eslint/utils");
12
+ const TABLE_COMPONENTS = ['EuiInMemoryTable', 'EuiBasicTable'];
13
+ const TABLE_CAPTION_PROP = 'tableCaption';
14
+ exports.RequireTableCaption = utils_1.ESLintUtils.RuleCreator.withoutDocs({
15
+ create(context) {
16
+ return {
17
+ JSXOpeningElement(node) {
18
+ if (node.name.type !== 'JSXIdentifier') {
19
+ return;
20
+ }
21
+ const component = node.name.name;
22
+ if (!TABLE_COMPONENTS.includes(component)) {
23
+ return;
24
+ }
25
+ const hasTableCaption = node.attributes.some((attr) => attr.type === 'JSXAttribute' &&
26
+ attr.name.type === 'JSXIdentifier' &&
27
+ attr.name.name === TABLE_CAPTION_PROP);
28
+ if (!hasTableCaption) {
29
+ context.report({
30
+ node,
31
+ messageId: 'missingTableCaption',
32
+ data: { component }
33
+ });
34
+ }
35
+ },
36
+ };
37
+ },
38
+ defaultOptions: [],
39
+ meta: {
40
+ type: 'problem',
41
+ docs: {
42
+ description: `Ensure ${TABLE_COMPONENTS.join(', ')} have a \`${TABLE_CAPTION_PROP}\` prop for accessibility.`,
43
+ },
44
+ schema: [],
45
+ messages: {
46
+ missingTableCaption: [
47
+ '{{component}} must include a `tableCaption` prop for accessibility.',
48
+ '',
49
+ 'Example:',
50
+ ' <{{component}} tableCaption="Descriptive caption for the table" ... />',
51
+ ].join('\n'),
52
+ },
53
+ },
54
+ });
55
+ //# sourceMappingURL=require_table_caption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require_table_caption.js","sourceRoot":"","sources":["../../../../src/rules/a11y/require_table_caption.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,oDAAsE;AAEtE,MAAM,gBAAgB,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;AAC/D,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE7B,QAAA,mBAAmB,GAAG,mBAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACrE,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAgC;gBAChD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBACvC,OAAO;gBACT,CAAC;gBAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAEjC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC1C,OAAO;gBACT,CAAC;gBAED,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAC1C,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,CAAC,IAAI,KAAK,cAAc;oBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oBAClC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,kBAAkB,CACxC,CAAC;gBAEF,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,qBAAqB;wBAChC,IAAI,EAAE,EAAE,SAAS,EAAE;qBACpB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IACD,cAAc,EAAE,EAAE;IAClB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,UAAU,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,kBAAkB,4BAA4B;SAC9G;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,mBAAmB,EAAE;gBACnB,qEAAqE;gBACrE,EAAE;gBACF,UAAU;gBACV,0EAA0E;aAC3E,CAAC,IAAI,CAAC,IAAI,CAAC;SACb;KACF;CACF,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elastic/eslint-plugin-eui",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -43,7 +43,8 @@
43
43
  "typescript": "^5.8.3"
44
44
  },
45
45
  "scripts": {
46
- "test": "jest src",
46
+ "test": "yarn test-unit",
47
+ "test-unit": "jest src",
47
48
  "build": "yarn build:clean && yarn build:compile && yarn build:compile:esm && yarn build:types",
48
49
  "build:clean": "rimraf lib/",
49
50
  "build:compile:esm": "tsc --project ./tsconfig.esm.json",