click-events-have-key-events.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  4. var _ariaQuery = require("aria-query");
  5. var _jsxAstUtils = require("jsx-ast-utils");
  6. var _arrayIncludes = _interopRequireDefault(require("array-includes"));
  7. var _schemas = require("../util/schemas");
  8. var _isHiddenFromScreenReader = _interopRequireDefault(require("../util/isHiddenFromScreenReader"));
  9. var _isInteractiveElement = _interopRequireDefault(require("../util/isInteractiveElement"));
  10. var _isPresentationRole = _interopRequireDefault(require("../util/isPresentationRole"));
  11. /**
  12. * @fileoverview Enforce a clickable non-interactive element has at least 1 keyboard event listener.
  13. * @author Ethan Cohen
  14. */
  15. // ----------------------------------------------------------------------------
  16. // Rule Definition
  17. // ----------------------------------------------------------------------------
  18. var errorMessage = 'Visible, non-interactive elements with click handlers must have at least one keyboard listener.';
  19. var schema = (0, _schemas.generateObjSchema)();
  20. var domElements = (0, _toConsumableArray2["default"])(_ariaQuery.dom.keys());
  21. module.exports = {
  22. meta: {
  23. docs: {
  24. url: 'https://github.com/evcohen/eslint-plugin-jsx-a11y/tree/master/docs/rules/click-events-have-key-events.md'
  25. },
  26. schema: [schema]
  27. },
  28. create: function create(context) {
  29. return {
  30. JSXOpeningElement: function JSXOpeningElement(node) {
  31. var props = node.attributes;
  32. if ((0, _jsxAstUtils.getProp)(props, 'onclick') === undefined) {
  33. return;
  34. }
  35. var type = (0, _jsxAstUtils.elementType)(node);
  36. var requiredProps = ['onkeydown', 'onkeyup', 'onkeypress'];
  37. if (!(0, _arrayIncludes["default"])(domElements, type)) {
  38. // Do not test higher level JSX components, as we do not know what
  39. // low-level DOM element this maps to.
  40. return;
  41. }
  42. if ((0, _isHiddenFromScreenReader["default"])(type, props) || (0, _isPresentationRole["default"])(type, props)) {
  43. return;
  44. }
  45. if ((0, _isInteractiveElement["default"])(type, props)) {
  46. return;
  47. }
  48. if ((0, _jsxAstUtils.hasAnyProp)(props, requiredProps)) {
  49. return;
  50. } // Visible, non-interactive elements with click handlers require one keyboard event listener.
  51. context.report({
  52. node,
  53. message: errorMessage
  54. });
  55. }
  56. };
  57. }
  58. };