import { closest } from '../../core/utils'; function focusableElementEvaluate(node, options, virtualNode) { /** * Note: * Check * - if element is focusable * - if element is in focus order via `tabindex` */ if ( virtualNode.hasAttr('contenteditable') && isContenteditable(virtualNode) ) { return true; } const isFocusable = virtualNode.isFocusable; let tabIndex = parseInt(virtualNode.attr('tabindex'), 10); tabIndex = !isNaN(tabIndex) ? tabIndex : null; return tabIndex ? isFocusable && tabIndex >= 0 : isFocusable; // contenteditable is focusable when it is an empty string (whitespace // is not considered empty) or "true". if the value is "false" // you can't edit it, but if it's anything else it inherits the value // from the first valid ancestor // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable function isContenteditable(vNode) { const contenteditable = vNode.attr('contenteditable'); if (contenteditable === 'true' || contenteditable === '') { return true; } if (contenteditable === 'false') { return false; } const ancestor = closest(virtualNode.parent, '[contenteditable]'); if (!ancestor) { return false; } return isContenteditable(ancestor); } } export default focusableElementEvaluate;