You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
5.6KB

  1. // https://w3c.github.io/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html
  2. /**
  3. * Safe Element.localName for all supported environments
  4. * @param element
  5. */
  6. export function getLocalName(element) {
  7. var _element$localName;
  8. return (// eslint-disable-next-line no-restricted-properties -- actual guard for environments without localName
  9. (_element$localName = element.localName) !== null && _element$localName !== void 0 ? _element$localName :
  10. // eslint-disable-next-line no-restricted-properties -- required for the fallback
  11. element.tagName.toLowerCase()
  12. );
  13. }
  14. var localNameToRoleMappings = {
  15. article: "article",
  16. aside: "complementary",
  17. button: "button",
  18. datalist: "listbox",
  19. dd: "definition",
  20. details: "group",
  21. dialog: "dialog",
  22. dt: "term",
  23. fieldset: "group",
  24. figure: "figure",
  25. // WARNING: Only with an accessible name
  26. form: "form",
  27. footer: "contentinfo",
  28. h1: "heading",
  29. h2: "heading",
  30. h3: "heading",
  31. h4: "heading",
  32. h5: "heading",
  33. h6: "heading",
  34. header: "banner",
  35. hr: "separator",
  36. html: "document",
  37. legend: "legend",
  38. li: "listitem",
  39. math: "math",
  40. main: "main",
  41. menu: "list",
  42. nav: "navigation",
  43. ol: "list",
  44. optgroup: "group",
  45. // WARNING: Only in certain context
  46. option: "option",
  47. output: "status",
  48. progress: "progressbar",
  49. // WARNING: Only with an accessible name
  50. section: "region",
  51. summary: "button",
  52. table: "table",
  53. tbody: "rowgroup",
  54. textarea: "textbox",
  55. tfoot: "rowgroup",
  56. // WARNING: Only in certain context
  57. td: "cell",
  58. th: "columnheader",
  59. thead: "rowgroup",
  60. tr: "row",
  61. ul: "list"
  62. };
  63. var prohibitedAttributes = {
  64. caption: new Set(["aria-label", "aria-labelledby"]),
  65. code: new Set(["aria-label", "aria-labelledby"]),
  66. deletion: new Set(["aria-label", "aria-labelledby"]),
  67. emphasis: new Set(["aria-label", "aria-labelledby"]),
  68. generic: new Set(["aria-label", "aria-labelledby", "aria-roledescription"]),
  69. insertion: new Set(["aria-label", "aria-labelledby"]),
  70. paragraph: new Set(["aria-label", "aria-labelledby"]),
  71. presentation: new Set(["aria-label", "aria-labelledby"]),
  72. strong: new Set(["aria-label", "aria-labelledby"]),
  73. subscript: new Set(["aria-label", "aria-labelledby"]),
  74. superscript: new Set(["aria-label", "aria-labelledby"])
  75. };
  76. /**
  77. *
  78. * @param element
  79. * @param role The role used for this element. This is specified to control whether you want to use the implicit or explicit role.
  80. */
  81. function hasGlobalAriaAttributes(element, role) {
  82. // https://rawgit.com/w3c/aria/stable/#global_states
  83. // commented attributes are deprecated
  84. return ["aria-atomic", "aria-busy", "aria-controls", "aria-current", "aria-describedby", "aria-details",
  85. // "disabled",
  86. "aria-dropeffect",
  87. // "errormessage",
  88. "aria-flowto", "aria-grabbed",
  89. // "haspopup",
  90. "aria-hidden",
  91. // "invalid",
  92. "aria-keyshortcuts", "aria-label", "aria-labelledby", "aria-live", "aria-owns", "aria-relevant", "aria-roledescription"].some(function (attributeName) {
  93. var _prohibitedAttributes;
  94. return element.hasAttribute(attributeName) && !((_prohibitedAttributes = prohibitedAttributes[role]) !== null && _prohibitedAttributes !== void 0 && _prohibitedAttributes.has(attributeName));
  95. });
  96. }
  97. function ignorePresentationalRole(element, implicitRole) {
  98. // https://rawgit.com/w3c/aria/stable/#conflict_resolution_presentation_none
  99. return hasGlobalAriaAttributes(element, implicitRole);
  100. }
  101. export default function getRole(element) {
  102. var explicitRole = getExplicitRole(element);
  103. if (explicitRole === null || explicitRole === "presentation") {
  104. var implicitRole = getImplicitRole(element);
  105. if (explicitRole !== "presentation" || ignorePresentationalRole(element, implicitRole || "")) {
  106. return implicitRole;
  107. }
  108. }
  109. return explicitRole;
  110. }
  111. function getImplicitRole(element) {
  112. var mappedByTag = localNameToRoleMappings[getLocalName(element)];
  113. if (mappedByTag !== undefined) {
  114. return mappedByTag;
  115. }
  116. switch (getLocalName(element)) {
  117. case "a":
  118. case "area":
  119. case "link":
  120. if (element.hasAttribute("href")) {
  121. return "link";
  122. }
  123. break;
  124. case "img":
  125. if (element.getAttribute("alt") === "" && !ignorePresentationalRole(element, "img")) {
  126. return "presentation";
  127. }
  128. return "img";
  129. case "input":
  130. {
  131. var _ref = element,
  132. type = _ref.type;
  133. switch (type) {
  134. case "button":
  135. case "image":
  136. case "reset":
  137. case "submit":
  138. return "button";
  139. case "checkbox":
  140. case "radio":
  141. return type;
  142. case "range":
  143. return "slider";
  144. case "email":
  145. case "tel":
  146. case "text":
  147. case "url":
  148. if (element.hasAttribute("list")) {
  149. return "combobox";
  150. }
  151. return "textbox";
  152. case "search":
  153. if (element.hasAttribute("list")) {
  154. return "combobox";
  155. }
  156. return "searchbox";
  157. case "number":
  158. return "spinbutton";
  159. default:
  160. return null;
  161. }
  162. }
  163. case "select":
  164. if (element.hasAttribute("multiple") || element.size > 1) {
  165. return "listbox";
  166. }
  167. return "combobox";
  168. }
  169. return null;
  170. }
  171. function getExplicitRole(element) {
  172. var role = element.getAttribute("role");
  173. if (role !== null) {
  174. var explicitRole = role.trim().split(" ")[0];
  175. // String.prototype.split(sep, limit) will always return an array with at least one member
  176. // as long as limit is either undefined or > 0
  177. if (explicitRole.length > 0) {
  178. return explicitRole;
  179. }
  180. }
  181. return null;
  182. }
  183. //# sourceMappingURL=getRole.mjs.map