getFocusableElements.ts 974 B

1234567891011121314151617181920212223242526
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. const FOCUSABLE_QUERY =
  3. 'button, a[href]:not([href=""]), input, select, textarea, [tabindex]:not([tabindex="-1"])'
  4. export const isElementVisible = (el: HTMLElement) => {
  5. // In Vitest, a visibility check is unreliable due to the used JSDOM test environment.
  6. // Therefore, we always assume the element is visible.
  7. if (import.meta.env.VITEST) return true
  8. return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length) // from jQuery
  9. }
  10. export const getFocusableElements = (container?: Maybe<HTMLElement>) => {
  11. return Array.from<HTMLElement>(
  12. container?.querySelectorAll(FOCUSABLE_QUERY) || [],
  13. ).filter(
  14. (el) =>
  15. isElementVisible(el) &&
  16. !el.hasAttribute('disabled') &&
  17. el.getAttribute('aria-disabled') !== 'true',
  18. )
  19. }
  20. export const getFirstFocusableElement = (container?: Maybe<HTMLElement>) => {
  21. return getFocusableElements(container)[0]
  22. }