UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

84 lines (81 loc) 2.99 kB
'use strict'; /** * Gets all focusable child elements within a container. * Uses a comprehensive selector to find elements that can receive focus. * @param element - The container element to search within * @returns Array of focusable HTML elements */ const focusableChildren = (element) => { const focusableSelectors = [ 'a[href]', 'button:not([disabled])', 'input:not([disabled])', 'textarea:not([disabled])', 'select:not([disabled])', 'details', '[tabindex]:not([tabindex="-1"])', '[contenteditable="true"]', ].join(','); const elements = [...element.querySelectorAll(focusableSelectors)]; return elements.filter((el) => !isDisabled(el) && isVisible(el)); }; /** * Checks if an element is disabled. * Considers various ways an element can be disabled including CSS classes and attributes. * @param element - The HTML element to check * @returns True if the element is disabled, false otherwise */ const isDisabled = (element) => { if (!element || element.nodeType !== Node.ELEMENT_NODE) { return true; } if (element.classList.contains('disabled')) { return true; } if ('disabled' in element && typeof element.disabled === 'boolean') { return element.disabled; } return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; }; /** * Type guard to check if an object is an Element. * Handles edge cases including jQuery objects. * @param object - The object to check * @returns True if the object is an Element, false otherwise */ const isElement = (object) => { if (!object || typeof object !== 'object') { return false; } return 'nodeType' in object && typeof object.nodeType === 'number'; }; /** * Checks if an element is visible in the DOM. * Considers client rects and computed visibility styles, handling edge cases like details elements. * @param element - The HTML element to check for visibility * @returns True if the element is visible, false otherwise */ const isVisible = (element) => { if (!isElement(element) || element.getClientRects().length === 0) { return false; } const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; // Handle `details` element as its content may falsely appear visible when it is closed const closedDetails = element.closest('details:not([open])'); if (!closedDetails) { return elementIsVisible; } if (closedDetails !== element) { const summary = element.closest('summary'); // Check if summary is a direct child of the closed details if (summary?.parentNode !== closedDetails) { return false; } } return elementIsVisible; }; exports.focusableChildren = focusableChildren; exports.isDisabled = isDisabled; exports.isElement = isElement; exports.isVisible = isVisible; //# sourceMappingURL=utils.js.map