@elastic/eslint-plugin-eui 2.11.1 → 2.13.0-snapshot.1779110362015
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 +95 -0
- package/lib/cjs/index.js +14 -2
- package/lib/cjs/rules/a11y/tooltip_button_icon_wrap.d.ts +3 -0
- package/lib/cjs/rules/a11y/tooltip_button_icon_wrap.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/tooltip_button_icon_wrap.js +104 -0
- package/lib/cjs/rules/a11y/tooltip_no_interactive_content.d.ts +3 -0
- package/lib/cjs/rules/a11y/tooltip_no_interactive_content.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/tooltip_no_interactive_content.js +113 -0
- package/lib/cjs/rules/href_or_on_click.js +1 -1
- package/lib/cjs/rules/prefer_tooltip_trigger_focus_test_utility.d.ts +3 -0
- package/lib/cjs/rules/prefer_tooltip_trigger_focus_test_utility.d.ts.map +1 -0
- package/lib/cjs/rules/prefer_tooltip_trigger_focus_test_utility.js +80 -0
- package/lib/cjs/rules/require_href_for_link.d.ts +3 -0
- package/lib/cjs/rules/require_href_for_link.d.ts.map +1 -0
- package/lib/cjs/rules/require_href_for_link.js +59 -0
- package/lib/cjs/utils/constants.d.ts +7 -0
- package/lib/cjs/utils/constants.d.ts.map +1 -1
- package/lib/cjs/utils/constants.js +10 -2
- package/lib/esm/index.js +13 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/rules/a11y/tooltip_button_icon_wrap.d.ts +2 -0
- package/lib/esm/rules/a11y/tooltip_button_icon_wrap.js +123 -0
- package/lib/esm/rules/a11y/tooltip_button_icon_wrap.js.map +1 -0
- package/lib/esm/rules/a11y/tooltip_no_interactive_content.d.ts +2 -0
- package/lib/esm/rules/a11y/tooltip_no_interactive_content.js +115 -0
- package/lib/esm/rules/a11y/tooltip_no_interactive_content.js.map +1 -0
- package/lib/esm/rules/href_or_on_click.js +1 -1
- package/lib/esm/rules/href_or_on_click.js.map +1 -1
- package/lib/esm/rules/prefer_tooltip_trigger_focus_test_utility.d.ts +2 -0
- package/lib/esm/rules/prefer_tooltip_trigger_focus_test_utility.js +93 -0
- package/lib/esm/rules/prefer_tooltip_trigger_focus_test_utility.js.map +1 -0
- package/lib/esm/rules/require_href_for_link.d.ts +2 -0
- package/lib/esm/rules/require_href_for_link.js +54 -0
- package/lib/esm/rules/require_href_for_link.js.map +1 -0
- package/lib/esm/utils/constants.d.ts +7 -0
- package/lib/esm/utils/constants.js +45 -29
- package/lib/esm/utils/constants.js.map +1 -1
- package/package.json +3 -2
package/lib/esm/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const accessible_interactive_element_1 = require("./rules/a11y/accessible_intera
|
|
|
11
11
|
const callout_announce_on_mount_1 = require("./rules/a11y/callout_announce_on_mount");
|
|
12
12
|
const consistent_is_invalid_props_1 = require("./rules/a11y/consistent_is_invalid_props");
|
|
13
13
|
const href_or_on_click_1 = require("./rules/href_or_on_click");
|
|
14
|
+
const require_href_for_link_1 = require("./rules/require_href_for_link");
|
|
14
15
|
const no_css_color_1 = require("./rules/no_css_color");
|
|
15
16
|
const no_restricted_eui_imports_1 = require("./rules/no_restricted_eui_imports");
|
|
16
17
|
const no_static_z_index_1 = require("./rules/no_static_z_index");
|
|
@@ -21,8 +22,11 @@ const require_aria_label_for_modals_1 = require("./rules/a11y/require_aria_label
|
|
|
21
22
|
const require_table_caption_1 = require("./rules/a11y/require_table_caption");
|
|
22
23
|
const sr_output_disabled_tooltip_1 = require("./rules/a11y/sr_output_disabled_tooltip");
|
|
23
24
|
const tooltip_focusable_anchor_1 = require("./rules/a11y/tooltip_focusable_anchor");
|
|
25
|
+
const prefer_tooltip_trigger_focus_test_utility_1 = require("./rules/prefer_tooltip_trigger_focus_test_utility");
|
|
24
26
|
const badge_accessibility_rules_1 = require("./rules/a11y/badge_accessibility_rules");
|
|
25
27
|
const icon_accessibility_rules_1 = require("./rules/a11y/icon_accessibility_rules");
|
|
28
|
+
const tooltip_no_interactive_content_1 = require("./rules/a11y/tooltip_no_interactive_content");
|
|
29
|
+
const tooltip_button_icon_wrap_1 = require("./rules/a11y/tooltip_button_icon_wrap");
|
|
26
30
|
const config = {
|
|
27
31
|
rules: {
|
|
28
32
|
'accessible-interactive-element': accessible_interactive_element_1.AccessibleInteractiveElements,
|
|
@@ -39,8 +43,12 @@ const config = {
|
|
|
39
43
|
'require-table-caption': require_table_caption_1.RequireTableCaption,
|
|
40
44
|
'sr-output-disabled-tooltip': sr_output_disabled_tooltip_1.ScreenReaderOutputDisabledTooltip,
|
|
41
45
|
'tooltip-focusable-anchor': tooltip_focusable_anchor_1.TooltipFocusableAnchor,
|
|
46
|
+
'prefer-tooltip-trigger-focus-test-utility': prefer_tooltip_trigger_focus_test_utility_1.PreferTooltipTriggerFocusTestUtility,
|
|
42
47
|
'badge-accessibility-rules': badge_accessibility_rules_1.EuiBadgeAccessibilityRules,
|
|
43
|
-
'icon-accessibility-rules': icon_accessibility_rules_1.EuiIconAccessibilityRules
|
|
48
|
+
'icon-accessibility-rules': icon_accessibility_rules_1.EuiIconAccessibilityRules,
|
|
49
|
+
'require-href-for-link': require_href_for_link_1.RequireHrefForLink,
|
|
50
|
+
'tooltip-no-interactive-content': tooltip_no_interactive_content_1.TooltipNoInteractiveContent,
|
|
51
|
+
'tooltip-button-icon-wrap': tooltip_button_icon_wrap_1.TooltipButtonIconWrap,
|
|
44
52
|
},
|
|
45
53
|
configs: {
|
|
46
54
|
recommended: {
|
|
@@ -60,8 +68,12 @@ const config = {
|
|
|
60
68
|
'@elastic/eui/require-table-caption': 'warn',
|
|
61
69
|
'@elastic/eui/sr-output-disabled-tooltip': 'warn',
|
|
62
70
|
'@elastic/eui/tooltip-focusable-anchor': 'warn',
|
|
71
|
+
'@elastic/eui/prefer-tooltip-trigger-focus-test-utility': 'warn',
|
|
63
72
|
'@elastic/eui/badge-accessibility-rules': 'warn',
|
|
64
73
|
'@elastic/eui/icon-accessibility-rules': 'warn',
|
|
74
|
+
'@elastic/eui/require-href-for-link': 'warn',
|
|
75
|
+
'@elastic/eui/tooltip-no-interactive-content': 'warn',
|
|
76
|
+
'@elastic/eui/tooltip-button-icon-wrap': 'warn',
|
|
65
77
|
},
|
|
66
78
|
},
|
|
67
79
|
},
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAEH,gGAA4F;AAC5F,sFAAgF;AAChF,0FAAoF;AACpF,+DAAuD;AACvD,yEAAmE;AACnE,uDAAkD;AAClD,iFAA2E;AAC3E,iEAA2D;AAC3D,gGAA0F;AAC1F,gFAA0E;AAC1E,0EAAoE;AACpE,8FAAuF;AACvF,8EAAyE;AACzE,wFAA4F;AAC5F,oFAA+E;AAC/E,iHAAyG;AACzG,sFAAoF;AACpF,oFAAkF;AAClF,gGAA0F;AAC1F,oFAA8E;AAE9E,MAAM,MAAM,GAAG;IACb,KAAK,EAAE;QACL,gCAAgC,EAAE,8DAA6B;QAC/D,2BAA2B,EAAE,kDAAsB;QACnD,6BAA6B,EAAE,sDAAwB;QACvD,kBAAkB,EAAE,8BAAW;QAC/B,cAAc,EAAE,yBAAU;QAC1B,2BAA2B,EAAE,kDAAsB;QACnD,mBAAmB,EAAE,kCAAc;QACnC,gCAAgC,EAAE,4DAA2B;QAC7D,wBAAwB,EAAE,4CAAmB;QAC7C,qBAAqB,EAAE,sCAAgB;QACvC,+BAA+B,EAAE,yDAAyB;QAC1D,uBAAuB,EAAE,2CAAmB;QAC5C,4BAA4B,EAAE,8DAAiC;QAC/D,0BAA0B,EAAE,iDAAsB;QAClD,2CAA2C,EACzC,gFAAoC;QACtC,2BAA2B,EAAE,sDAA0B;QACvD,0BAA0B,EAAE,oDAAyB;QACrD,uBAAuB,EAAE,0CAAkB;QAC3C,gCAAgC,EAAE,4DAA2B;QAC7D,0BAA0B,EAAE,gDAAqB;KAClD;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,4BAA4B,CAAC;YACvC,KAAK,EAAE;gBACL,6CAA6C,EAAE,MAAM;gBACrD,wCAAwC,EAAE,MAAM;gBAChD,0CAA0C,EAAE,MAAM;gBAClD,+BAA+B,EAAE,MAAM;gBACvC,2BAA2B,EAAE,MAAM;gBACnC,wCAAwC,EAAE,MAAM;gBAChD,gCAAgC,EAAE,MAAM;gBACxC,6CAA6C,EAAE,MAAM;gBACrD,qCAAqC,EAAE,MAAM;gBAC7C,kCAAkC,EAAE,MAAM;gBAC1C,4CAA4C,EAAE,MAAM;gBACpD,oCAAoC,EAAE,MAAM;gBAC5C,yCAAyC,EAAE,MAAM;gBACjD,uCAAuC,EAAE,MAAM;gBAC/C,wDAAwD,EAAE,MAAM;gBAChE,wCAAwC,EAAE,MAAM;gBAChD,uCAAuC,EAAE,MAAM;gBAC/C,oCAAoC,EAAE,MAAM;gBAC5C,6CAA6C,EAAE,MAAM;gBACrD,uCAAuC,EAAE,MAAM;aAChD;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
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.TooltipButtonIconWrap = void 0;
|
|
11
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
12
|
+
const remove_attr_1 = require("../../utils/remove_attr");
|
|
13
|
+
const has_spread_1 = require("../../utils/has_spread");
|
|
14
|
+
const BUTTON_ICON = 'EuiButtonIcon';
|
|
15
|
+
const TOOLTIP = 'EuiToolTip';
|
|
16
|
+
function isWrappedByTooltip(node) {
|
|
17
|
+
let current = node.parent;
|
|
18
|
+
while (current) {
|
|
19
|
+
switch (current.type) {
|
|
20
|
+
case 'JSXElement': {
|
|
21
|
+
const el = current;
|
|
22
|
+
if (el.openingElement.name.type === 'JSXIdentifier' &&
|
|
23
|
+
el.openingElement.name.name === TOOLTIP) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
current = current.parent;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case 'JSXFragment':
|
|
30
|
+
case 'JSXExpressionContainer':
|
|
31
|
+
case 'LogicalExpression':
|
|
32
|
+
case 'ConditionalExpression':
|
|
33
|
+
current = current.parent;
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
exports.TooltipButtonIconWrap = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
42
|
+
create(context) {
|
|
43
|
+
return {
|
|
44
|
+
JSXElement(node) {
|
|
45
|
+
const { openingElement } = node;
|
|
46
|
+
if (openingElement.name.type !== 'JSXIdentifier' ||
|
|
47
|
+
openingElement.name.name !== BUTTON_ICON) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let titleAttr;
|
|
51
|
+
let ariaLabelAttr;
|
|
52
|
+
for (const attr of openingElement.attributes) {
|
|
53
|
+
if (attr.type !== 'JSXAttribute' ||
|
|
54
|
+
attr.name.type !== 'JSXIdentifier')
|
|
55
|
+
continue;
|
|
56
|
+
if (attr.name.name === 'title')
|
|
57
|
+
titleAttr = attr;
|
|
58
|
+
if (attr.name.name === 'aria-label')
|
|
59
|
+
ariaLabelAttr = attr;
|
|
60
|
+
}
|
|
61
|
+
if (titleAttr) {
|
|
62
|
+
const alreadyWrapped = isWrappedByTooltip(node);
|
|
63
|
+
context.report({
|
|
64
|
+
node: openingElement,
|
|
65
|
+
messageId: 'useEuiToolTipInsteadOfTitle',
|
|
66
|
+
fix: titleAttr.value
|
|
67
|
+
? (fixer) => {
|
|
68
|
+
const titleValue = context.sourceCode.getText(titleAttr.value);
|
|
69
|
+
const [removeStart, removeEnd] = (0, remove_attr_1.removeAttribute)(context, titleAttr);
|
|
70
|
+
if (alreadyWrapped) {
|
|
71
|
+
return fixer.removeRange([removeStart, removeEnd]);
|
|
72
|
+
}
|
|
73
|
+
return [
|
|
74
|
+
fixer.removeRange([removeStart, removeEnd]),
|
|
75
|
+
fixer.insertTextBefore(node, `<${TOOLTIP} content=${titleValue}>\n `),
|
|
76
|
+
fixer.insertTextAfter(node, `\n</${TOOLTIP}>`),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
: undefined,
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!isWrappedByTooltip(node) &&
|
|
84
|
+
!(0, has_spread_1.hasSpread)(openingElement.attributes)) {
|
|
85
|
+
context.report({
|
|
86
|
+
node: openingElement,
|
|
87
|
+
messageId: 'wrapWithEuiToolTip',
|
|
88
|
+
fix: ariaLabelAttr?.value
|
|
89
|
+
? (fixer) => {
|
|
90
|
+
const ariaLabelValue = context.sourceCode.getText(ariaLabelAttr.value);
|
|
91
|
+
return [
|
|
92
|
+
fixer.insertTextBefore(node, `<${TOOLTIP} content=${ariaLabelValue}>\n `),
|
|
93
|
+
fixer.insertTextAfter(node, `\n</${TOOLTIP}>`),
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
: undefined,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
meta: {
|
|
103
|
+
type: 'suggestion',
|
|
104
|
+
docs: {
|
|
105
|
+
description: `Ensure ${BUTTON_ICON} is wrapped with ${TOOLTIP} for sighted users`,
|
|
106
|
+
},
|
|
107
|
+
fixable: 'code',
|
|
108
|
+
schema: [],
|
|
109
|
+
messages: {
|
|
110
|
+
useEuiToolTipInsteadOfTitle: [
|
|
111
|
+
`Remove the \`title\` prop from ${BUTTON_ICON} and use ${TOOLTIP} instead.`,
|
|
112
|
+
'Browser-native tooltips are unstyled, have no delay control and are not keyboard-accessible.',
|
|
113
|
+
`Wrap with <${TOOLTIP} content={label}> and use \`aria-label\` for screen readers.`,
|
|
114
|
+
].join(' '),
|
|
115
|
+
wrapWithEuiToolTip: [
|
|
116
|
+
`${BUTTON_ICON} has no visible tooltip for sighted users.`,
|
|
117
|
+
`Wrap with <${TOOLTIP} content={ariaLabel}> using the button's \`aria-label\` as content.`,
|
|
118
|
+
].join(' '),
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
defaultOptions: [],
|
|
122
|
+
});
|
|
123
|
+
//# sourceMappingURL=tooltip_button_icon_wrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip_button_icon_wrap.js","sourceRoot":"","sources":["../../../../src/rules/a11y/tooltip_button_icon_wrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
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.TooltipNoInteractiveContent = void 0;
|
|
11
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
12
|
+
const constants_1 = require("../../utils/constants");
|
|
13
|
+
const TOOLTIP_COMPONENTS = ['EuiToolTip', 'EuiIconTip'];
|
|
14
|
+
const TOOLTIP_CONTENT_PROPS = ['content', 'title'];
|
|
15
|
+
const INTERACTIVE_HTML_ELEMENTS = [
|
|
16
|
+
'a',
|
|
17
|
+
'button',
|
|
18
|
+
'input',
|
|
19
|
+
'select',
|
|
20
|
+
'textarea',
|
|
21
|
+
];
|
|
22
|
+
const CONDITIONALLY_INTERACTIVE_SET = new Set(constants_1.CONDITIONALLY_INTERACTIVE_EUI_COMPONENTS);
|
|
23
|
+
const INTERACTIVE_ELEMENTS = new Set([
|
|
24
|
+
...INTERACTIVE_HTML_ELEMENTS,
|
|
25
|
+
...constants_1.INTERACTIVE_EUI_COMPONENTS.filter((c) => !CONDITIONALLY_INTERACTIVE_SET.has(c)),
|
|
26
|
+
]);
|
|
27
|
+
function findInteractiveElement(node) {
|
|
28
|
+
if (node.type === 'JSXElement') {
|
|
29
|
+
const el = node;
|
|
30
|
+
const { name } = el.openingElement;
|
|
31
|
+
if (name.type === 'JSXIdentifier' && INTERACTIVE_ELEMENTS.has(name.name)) {
|
|
32
|
+
return el.openingElement;
|
|
33
|
+
}
|
|
34
|
+
for (const child of el.children) {
|
|
35
|
+
const found = findInteractiveElement(child);
|
|
36
|
+
if (found)
|
|
37
|
+
return found;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (node.type === 'JSXFragment') {
|
|
41
|
+
for (const child of node.children) {
|
|
42
|
+
const found = findInteractiveElement(child);
|
|
43
|
+
if (found)
|
|
44
|
+
return found;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (node.type === 'JSXExpressionContainer') {
|
|
48
|
+
const { expression } = node;
|
|
49
|
+
if (expression.type !== 'JSXEmptyExpression') {
|
|
50
|
+
return findInteractiveElement(expression);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (node.type === 'LogicalExpression') {
|
|
54
|
+
const { left, right } = node;
|
|
55
|
+
return findInteractiveElement(left) ?? findInteractiveElement(right);
|
|
56
|
+
}
|
|
57
|
+
else if (node.type === 'ConditionalExpression') {
|
|
58
|
+
const { consequent, alternate } = node;
|
|
59
|
+
return (findInteractiveElement(consequent) ?? findInteractiveElement(alternate));
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
exports.TooltipNoInteractiveContent = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
64
|
+
create(context) {
|
|
65
|
+
return {
|
|
66
|
+
JSXElement(node) {
|
|
67
|
+
const { openingElement } = node;
|
|
68
|
+
if (openingElement.name.type !== 'JSXIdentifier' ||
|
|
69
|
+
!TOOLTIP_COMPONENTS.includes(openingElement.name.name)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const componentName = openingElement.name.name;
|
|
73
|
+
for (const attr of openingElement.attributes) {
|
|
74
|
+
if (attr.type !== 'JSXAttribute' ||
|
|
75
|
+
attr.name.type !== 'JSXIdentifier' ||
|
|
76
|
+
!TOOLTIP_CONTENT_PROPS.includes(attr.name.name)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const { expression } = attr.value;
|
|
83
|
+
if (expression.type === 'JSXEmptyExpression') {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const interactiveEl = findInteractiveElement(expression);
|
|
87
|
+
if (interactiveEl) {
|
|
88
|
+
context.report({
|
|
89
|
+
node: interactiveEl,
|
|
90
|
+
messageId: 'noInteractiveContent',
|
|
91
|
+
data: {
|
|
92
|
+
propName: attr.name.name,
|
|
93
|
+
componentName,
|
|
94
|
+
elementName: interactiveEl.name
|
|
95
|
+
.name,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
meta: {
|
|
104
|
+
type: 'problem',
|
|
105
|
+
docs: {
|
|
106
|
+
description: 'Disallow interactive elements in `EuiToolTip` and `EuiIconTip` content',
|
|
107
|
+
},
|
|
108
|
+
schema: [],
|
|
109
|
+
messages: {
|
|
110
|
+
noInteractiveContent: '{{ elementName }} inside {{ componentName }} {{ propName }} is not keyboard-reachable. Tooltip content renders in a portal with `role="tooltip"`. Use `EuiPopover` for interactive content instead.',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
defaultOptions: [],
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=tooltip_no_interactive_content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip_no_interactive_content.js","sourceRoot":"","sources":["../../../../src/rules/a11y/tooltip_no_interactive_content.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.HrefOnClick = void 0;
|
|
11
11
|
const utils_1 = require("@typescript-eslint/utils");
|
|
12
|
-
const componentNames = ['EuiButton', 'EuiButtonEmpty', '
|
|
12
|
+
const componentNames = ['EuiButton', 'EuiButtonEmpty', 'EuiBadge'];
|
|
13
13
|
exports.HrefOnClick = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
14
14
|
create(context) {
|
|
15
15
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"href_or_on_click.js","sourceRoot":"","sources":["../../../src/rules/href_or_on_click.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,oDAAiE;AAEjE,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"href_or_on_click.js","sourceRoot":"","sources":["../../../src/rules/href_or_on_click.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,oDAAiE;AAEjE,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,gBAAgB,EAAE,UAAU,CAAC,CAAC;AAEtD,QAAA,WAAW,GAAG,mBAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IAC7D,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAgC;gBAChD,uDAAuD;gBACvD,IACE,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oBAClC,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EACxC,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,6DAA6D;gBAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAClC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CACpE,CAAC;gBACF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CACrC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CACvE,CAAC;gBAEF,iDAAiD;gBACjD,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;oBAC1B,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,eAAe;wBAC1B,IAAI,EAAE;4BACJ,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;yBACrB;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,2EAA2E;SAC9E;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,aAAa,EACX,6MAA6M;SAChN;KACF;IACD,cAAc,EAAE,EAAE;CACnB,CAAC,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
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.PreferTooltipTriggerFocusTestUtility = void 0;
|
|
11
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
12
|
+
const TOOLTIP_ROLE_QUERIES = new Set([
|
|
13
|
+
'getByRole',
|
|
14
|
+
'queryByRole',
|
|
15
|
+
'findByRole',
|
|
16
|
+
]);
|
|
17
|
+
const isTooltipRoleQuery = (node) => {
|
|
18
|
+
const firstArg = node.arguments[0];
|
|
19
|
+
if (firstArg?.type !== 'Literal' || firstArg.value !== 'tooltip')
|
|
20
|
+
return false;
|
|
21
|
+
const callee = node.callee;
|
|
22
|
+
// `screen.getByRole('tooltip')` or destructured `getByRole('tooltip')`
|
|
23
|
+
if (callee.type === 'MemberExpression')
|
|
24
|
+
return (callee.property.type === 'Identifier' &&
|
|
25
|
+
TOOLTIP_ROLE_QUERIES.has(callee.property.name));
|
|
26
|
+
if (callee.type === 'Identifier')
|
|
27
|
+
return TOOLTIP_ROLE_QUERIES.has(callee.name);
|
|
28
|
+
return false;
|
|
29
|
+
};
|
|
30
|
+
const isFireEventFocus = (node) => node.callee.type === 'MemberExpression' &&
|
|
31
|
+
node.callee.object.type === 'Identifier' &&
|
|
32
|
+
node.callee.object.name === 'fireEvent' &&
|
|
33
|
+
node.callee.property.type === 'Identifier' &&
|
|
34
|
+
node.callee.property.name === 'focus';
|
|
35
|
+
const isEuiToolTipClassSelector = (node) => typeof node.value === 'string' && node.value.includes('euiToolTip');
|
|
36
|
+
const isTestBlock = (node) => {
|
|
37
|
+
const callee = node.callee;
|
|
38
|
+
return (callee.type === 'Identifier' &&
|
|
39
|
+
(callee.name === 'it' || callee.name === 'test'));
|
|
40
|
+
};
|
|
41
|
+
exports.PreferTooltipTriggerFocusTestUtility = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
42
|
+
create(context) {
|
|
43
|
+
const blockStack = [];
|
|
44
|
+
const currentBlock = () => blockStack[blockStack.length - 1];
|
|
45
|
+
return {
|
|
46
|
+
CallExpression(node) {
|
|
47
|
+
if (isTestBlock(node)) {
|
|
48
|
+
blockStack.push({ violations: [], hasTooltipSignal: false });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const block = currentBlock();
|
|
52
|
+
if (!block)
|
|
53
|
+
return;
|
|
54
|
+
if (isTooltipRoleQuery(node))
|
|
55
|
+
block.hasTooltipSignal = true;
|
|
56
|
+
if (isFireEventFocus(node))
|
|
57
|
+
block.violations.push(node);
|
|
58
|
+
},
|
|
59
|
+
Literal(node) {
|
|
60
|
+
const block = currentBlock();
|
|
61
|
+
if (!block)
|
|
62
|
+
return;
|
|
63
|
+
if (isEuiToolTipClassSelector(node))
|
|
64
|
+
block.hasTooltipSignal = true;
|
|
65
|
+
},
|
|
66
|
+
'CallExpression:exit'(node) {
|
|
67
|
+
if (!isTestBlock(node))
|
|
68
|
+
return;
|
|
69
|
+
const block = blockStack.pop();
|
|
70
|
+
if (!block?.hasTooltipSignal)
|
|
71
|
+
return;
|
|
72
|
+
for (const violation of block.violations) {
|
|
73
|
+
context.report({
|
|
74
|
+
node: violation,
|
|
75
|
+
messageId: 'preferTooltipTriggerFocusTestUtility',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
meta: {
|
|
82
|
+
type: 'suggestion',
|
|
83
|
+
docs: {
|
|
84
|
+
description: 'Prefer `focusEuiToolTipTrigger` over `fireEvent.focus` in tooltip tests. Plain `fireEvent.focus` does not simulate `:focus-visible` in jsdom and will not trigger the tooltip.',
|
|
85
|
+
},
|
|
86
|
+
schema: [],
|
|
87
|
+
messages: {
|
|
88
|
+
preferTooltipTriggerFocusTestUtility: 'Use `focusEuiToolTipTrigger` from EUI test utilities instead of `fireEvent.focus` when testing tooltip focus behavior.',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
defaultOptions: [],
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=prefer_tooltip_trigger_focus_test_utility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer_tooltip_trigger_focus_test_utility.js","sourceRoot":"","sources":["../../../src/rules/prefer_tooltip_trigger_focus_test_utility.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
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.RequireHrefForLink = void 0;
|
|
11
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
12
|
+
const has_spread_1 = require("../utils/has_spread");
|
|
13
|
+
exports.RequireHrefForLink = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
14
|
+
create(context) {
|
|
15
|
+
return {
|
|
16
|
+
JSXOpeningElement(node) {
|
|
17
|
+
if (node.name.type !== 'JSXIdentifier' ||
|
|
18
|
+
node.name.name !== 'EuiLink') {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Bail out if props are spread — we can't statically determine
|
|
22
|
+
// whether `href` is provided via the spread
|
|
23
|
+
if ((0, has_spread_1.hasSpread)(node.attributes)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Check if the node has `href` and `onClick` attributes
|
|
27
|
+
const hasHref = node.attributes.some((attr) => attr.type === 'JSXAttribute' && attr.name.name === 'href');
|
|
28
|
+
const hasOnClick = node.attributes.some((attr) => attr.type === 'JSXAttribute' && attr.name.name === 'onClick');
|
|
29
|
+
// Report an issue if `onClick` is present without `href`
|
|
30
|
+
if (hasOnClick && !hasHref) {
|
|
31
|
+
context.report({
|
|
32
|
+
node,
|
|
33
|
+
messageId: 'requireHrefForLink',
|
|
34
|
+
data: {
|
|
35
|
+
name: node.name.name,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
meta: {
|
|
43
|
+
type: 'suggestion',
|
|
44
|
+
docs: {
|
|
45
|
+
description: 'Recommend including `href` alongside `onClick` on EuiLink so that Ctrl/Cmd+Click (open link in new tab) works.',
|
|
46
|
+
},
|
|
47
|
+
schema: [],
|
|
48
|
+
messages: {
|
|
49
|
+
requireHrefForLink: '<{{name}}> has `onClick` but no `href`. Consider adding `href` so that the component renders as a link and supports Ctrl/Cmd+Click / "Open link in new tab".',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
defaultOptions: [],
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=require_href_for_link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require_href_for_link.js","sourceRoot":"","sources":["../../../src/rules/require_href_for_link.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,oDAAiE;AAEjE,oDAAgD;AAEnC,QAAA,kBAAkB,GAAG,mBAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACpE,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAgC;gBAChD,IACE,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oBAClC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,EAC5B,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,+DAA+D;gBAC/D,4CAA4C;gBAC5C,IAAI,IAAA,sBAAS,EAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC/B,OAAO;gBACT,CAAC;gBAED,wDAAwD;gBACxD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAClC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CACpE,CAAC;gBACF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CACrC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CACvE,CAAC;gBAEF,yDAAyD;gBACzD,IAAI,UAAU,IAAI,CAAC,OAAO,EAAE,CAAC;oBAC3B,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,oBAAoB;wBAC/B,IAAI,EAAE;4BACJ,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;yBACrB;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,gHAAgH;SACnH;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,kBAAkB,EAChB,8JAA8J;SACjK;KACF;IACD,cAAc,EAAE,EAAE;CACnB,CAAC,CAAC"}
|
|
@@ -24,3 +24,10 @@ export declare const NON_INTERACTIVE_HTML_TAGS: string[];
|
|
|
24
24
|
* This list should be kept up to date with EUI's interactive component offerings.
|
|
25
25
|
*/
|
|
26
26
|
export declare const INTERACTIVE_EUI_COMPONENTS: string[];
|
|
27
|
+
/**
|
|
28
|
+
* EUI components that are only interactive when `onClick` or `href` is provided.
|
|
29
|
+
* Without those props they render as a plain non-focusable element (span/div),
|
|
30
|
+
* so rules that need to distinguish unconditionally-interactive components should
|
|
31
|
+
* exclude these.
|
|
32
|
+
*/
|
|
33
|
+
export declare const CONDITIONALLY_INTERACTIVE_EUI_COMPONENTS: string[];
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Side Public License, v 1.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.INTERACTIVE_EUI_COMPONENTS = exports.NON_INTERACTIVE_HTML_TAGS = void 0;
|
|
10
|
+
exports.CONDITIONALLY_INTERACTIVE_EUI_COMPONENTS = exports.INTERACTIVE_EUI_COMPONENTS = exports.NON_INTERACTIVE_HTML_TAGS = void 0;
|
|
11
11
|
/**
|
|
12
12
|
* A list of standard HTML tags that are considered **non-interactive** elements.
|
|
13
13
|
*
|
|
@@ -75,45 +75,61 @@ exports.NON_INTERACTIVE_HTML_TAGS = [
|
|
|
75
75
|
* This list should be kept up to date with EUI's interactive component offerings.
|
|
76
76
|
*/
|
|
77
77
|
exports.INTERACTIVE_EUI_COMPONENTS = [
|
|
78
|
-
'
|
|
78
|
+
'EuiBadge',
|
|
79
|
+
'EuiBasicTable',
|
|
80
|
+
'EuiBetaBadge',
|
|
81
|
+
'EuiBreadcrumbs',
|
|
79
82
|
'EuiButton',
|
|
80
83
|
'EuiButtonEmpty',
|
|
84
|
+
'EuiButtonGroup',
|
|
81
85
|
'EuiButtonIcon',
|
|
86
|
+
'EuiCard',
|
|
87
|
+
'EuiCheckableCard',
|
|
88
|
+
'EuiCheckbox',
|
|
89
|
+
'EuiColorPicker',
|
|
90
|
+
'EuiComboBox',
|
|
91
|
+
'EuiContextMenuItem',
|
|
92
|
+
'EuiDatePicker',
|
|
93
|
+
'EuiDualRange',
|
|
82
94
|
'EuiFacetButton',
|
|
95
|
+
'EuiFieldNumber',
|
|
96
|
+
'EuiFieldPassword',
|
|
97
|
+
'EuiFieldSearch',
|
|
98
|
+
'EuiFieldText',
|
|
99
|
+
'EuiFilterButton',
|
|
100
|
+
'EuiFilterSelectItem',
|
|
101
|
+
'EuiFilterSelectable',
|
|
83
102
|
'EuiHeaderLink',
|
|
84
|
-
'EuiHeaderSectionItemButton',
|
|
85
103
|
'EuiHeaderLogo',
|
|
104
|
+
'EuiHeaderSectionItemButton',
|
|
105
|
+
'EuiInMemoryTable',
|
|
106
|
+
'EuiKeyPadMenuItem',
|
|
107
|
+
'EuiLink',
|
|
86
108
|
'EuiListGroupItem',
|
|
109
|
+
'EuiPagination',
|
|
87
110
|
'EuiPinnableListGroup',
|
|
111
|
+
'EuiRadio',
|
|
112
|
+
'EuiRange',
|
|
113
|
+
'EuiSelect',
|
|
114
|
+
'EuiSelectable',
|
|
88
115
|
'EuiSideNav',
|
|
89
|
-
'EuiBreadcrumbs',
|
|
90
|
-
'EuiTab',
|
|
91
|
-
'EuiContextMenuItem',
|
|
92
|
-
'EuiKeyPadMenuItem',
|
|
93
|
-
'EuiPagination',
|
|
94
|
-
'EuiTreeView',
|
|
95
116
|
'EuiStepHorizontal',
|
|
96
|
-
'
|
|
97
|
-
'EuiCheckableCard',
|
|
98
|
-
'EuiBasicTable',
|
|
99
|
-
'EuiInMemoryTable',
|
|
100
|
-
'EuiFilterButton',
|
|
101
|
-
'EuiFilterSelectItem',
|
|
102
|
-
'EuiFilterSelectable',
|
|
103
|
-
'EuiBadge',
|
|
104
|
-
'EuiBetaBadge',
|
|
105
|
-
'EuiSelectable',
|
|
106
|
-
'EuiComboBox',
|
|
117
|
+
'EuiSuperDatePicker',
|
|
107
118
|
'EuiSuperSelect',
|
|
108
|
-
'EuiSelect',
|
|
109
|
-
'EuiCheckbox',
|
|
110
|
-
'EuiRadio',
|
|
111
119
|
'EuiSwitch',
|
|
112
|
-
'
|
|
113
|
-
'
|
|
114
|
-
'
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
'EuiTab',
|
|
121
|
+
'EuiTextArea',
|
|
122
|
+
'EuiTreeView'
|
|
123
|
+
];
|
|
124
|
+
/**
|
|
125
|
+
* EUI components that are only interactive when `onClick` or `href` is provided.
|
|
126
|
+
* Without those props they render as a plain non-focusable element (span/div),
|
|
127
|
+
* so rules that need to distinguish unconditionally-interactive components should
|
|
128
|
+
* exclude these.
|
|
129
|
+
*/
|
|
130
|
+
exports.CONDITIONALLY_INTERACTIVE_EUI_COMPONENTS = [
|
|
131
|
+
'EuiBadge',
|
|
132
|
+
'EuiBetaBadge',
|
|
133
|
+
'EuiCard',
|
|
118
134
|
];
|
|
119
135
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/utils/constants.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH;;;;;;;;;;;;GAYG;AACU,QAAA,yBAAyB,GAAG;IACvC,KAAK;IACL,MAAM;IACN,GAAG;IACH,SAAS;IACT,OAAO;IACP,YAAY;IACZ,IAAI;IACJ,SAAS;IACT,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,YAAY;IACZ,QAAQ;IACR,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,MAAM;IACN,KAAK;IACL,IAAI;IACJ,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,KAAK;IACL,KAAK;IACL,OAAO;IACP,OAAO;IACP,IAAI;IACJ,OAAO;IACP,IAAI;IACJ,OAAO;IACP,IAAI;IACJ,IAAI;CACL,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,0BAA0B,GAAG;IACxC,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/utils/constants.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH;;;;;;;;;;;;GAYG;AACU,QAAA,yBAAyB,GAAG;IACvC,KAAK;IACL,MAAM;IACN,GAAG;IACH,SAAS;IACT,OAAO;IACP,YAAY;IACZ,IAAI;IACJ,SAAS;IACT,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,YAAY;IACZ,QAAQ;IACR,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,MAAM;IACN,KAAK;IACL,IAAI;IACJ,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,KAAK;IACL,KAAK;IACL,OAAO;IACP,OAAO;IACP,IAAI;IACJ,OAAO;IACP,IAAI;IACJ,OAAO;IACP,IAAI;IACJ,IAAI;CACL,CAAC;AAEF;;;;;;;;;;GAUG;AACU,QAAA,0BAA0B,GAAG;IACxC,UAAU;IACV,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,SAAS;IACT,kBAAkB;IAClB,aAAa;IACb,gBAAgB;IAChB,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;IAClB,gBAAgB;IAChB,cAAc;IACd,iBAAiB;IACjB,qBAAqB;IACrB,qBAAqB;IACrB,eAAe;IACf,eAAe;IACf,4BAA4B;IAC5B,kBAAkB;IAClB,mBAAmB;IACnB,SAAS;IACT,kBAAkB;IAClB,eAAe;IACf,sBAAsB;IACtB,UAAU;IACV,UAAU;IACV,WAAW;IACX,eAAe;IACf,YAAY;IACZ,mBAAmB;IACnB,oBAAoB;IACpB,gBAAgB;IAChB,WAAW;IACX,QAAQ;IACR,aAAa;IACb,aAAa;CACd,CAAC;AAEF;;;;;GAKG;AACU,QAAA,wCAAwC,GAAG;IACtD,UAAU;IACV,cAAc;IACd,SAAS;CACV,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elastic/eslint-plugin-eui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0-snapshot.1779110362015",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -57,5 +57,6 @@
|
|
|
57
57
|
"!**/*.test.js",
|
|
58
58
|
"!**/*.test.js.map",
|
|
59
59
|
"!**/*.test.d.ts"
|
|
60
|
-
]
|
|
60
|
+
],
|
|
61
|
+
"stableVersion": "2.13.0"
|
|
61
62
|
}
|