@@ -14,6 +14,7 @@ import {
1414import includes from 'array-includes' ;
1515import flatMap from 'array.prototype.flatmap' ;
1616
17+ import { getProp , getPropValue } from 'jsx-ast-utils' ;
1718import attributesComparator from './attributesComparator' ;
1819
1920const roleKeys = roles . keys ( ) ;
@@ -68,14 +69,50 @@ const interactiveElementAXObjectSchemas = flatMap(
6869 ( [ elementSchema , AXObjectsArr ] ) => ( AXObjectsArr . every ( ( role ) : boolean => interactiveAXObjects . has ( role ) ) ? [ elementSchema ] : [ ] ) ,
6970) ;
7071
71- function checkIsInteractiveElement ( tagName , attributes ) : boolean {
72+ function checkIsInteractiveElement ( tagName , attributes , options = { } ) : boolean {
7273 function elementSchemaMatcher ( elementSchema ) {
7374 return (
7475 tagName === elementSchema . name
7576 && attributesComparator ( elementSchema . attributes , attributes )
7677 ) ;
7778 }
7879
80+ function isInteractiveElementWithCustomOptions ( ) {
81+ const elementConfig = options [ tagName ] ;
82+
83+ if ( ! elementConfig ) return false ;
84+
85+ return Object . keys ( elementConfig . attributes ) . some ( ( standardAttr ) => {
86+ const customAttrs = elementConfig . attributes [ standardAttr ] ;
87+
88+ const validCustomAttr = customAttrs . find ( ( customAttr ) => {
89+ if ( customAttr === standardAttr ) return false ;
90+ const customProp = getProp ( attributes , customAttr ) ;
91+ return customProp && getPropValue ( customProp ) != null ;
92+ } ) ;
93+
94+ if ( validCustomAttr ) {
95+ const originalProp = getProp ( attributes , validCustomAttr ) ;
96+ const standardProp = {
97+ ...originalProp ,
98+ name : {
99+ ...originalProp . name ,
100+ name : standardAttr ,
101+ } ,
102+ } ;
103+
104+ return checkIsInteractiveElement ( tagName , [ ...attributes , standardProp ] , { } ) ;
105+ }
106+
107+ return false ;
108+ } ) ;
109+ }
110+
111+ // Checks if there are custom options for this element
112+ if ( options && Object . keys ( options ) . length > 0 ) {
113+ return isInteractiveElementWithCustomOptions ( ) ;
114+ }
115+
79116 // Check in elementRoles for inherent interactive role associations for
80117 // this element.
81118 const isInherentInteractiveElement = interactiveElementRoleSchemas . some ( elementSchemaMatcher ) ;
@@ -106,14 +143,15 @@ function checkIsInteractiveElement(tagName, attributes): boolean {
106143const isInteractiveElement = (
107144 tagName : string ,
108145 attributes : Array < Node > ,
146+ options : Object = { } ,
109147) : boolean => {
110148 // Do not test higher level JSX components, as we do not know what
111149 // low-level DOM element this maps to.
112150 if ( ! dom . has ( tagName ) ) {
113151 return false ;
114152 }
115153
116- return checkIsInteractiveElement ( tagName , attributes ) ;
154+ return checkIsInteractiveElement ( tagName , attributes , options ) ;
117155} ;
118156
119157export default isInteractiveElement ;
0 commit comments