(container: HTMLElement, forward: boolean, startFromContainer?: boolean)
| 48 | }; |
| 49 | |
| 50 | const findFocusableElement = async (container: HTMLElement, forward: boolean, startFromContainer?: boolean): FocusableElementPromise => { |
| 51 | let child: HTMLElement | undefined; |
| 52 | let assignedElements; |
| 53 | let currentIndex = -1; |
| 54 | |
| 55 | if (container.shadowRoot) { |
| 56 | child = forward ? container.shadowRoot.firstElementChild as HTMLElement : container.shadowRoot.lastElementChild as HTMLElement; |
| 57 | } else if (container instanceof HTMLSlotElement && container.assignedNodes()) { |
| 58 | assignedElements = container.assignedElements(); |
| 59 | currentIndex = forward ? 0 : assignedElements.length - 1; |
| 60 | child = assignedElements[currentIndex] as HTMLElement; |
| 61 | } else if (startFromContainer) { |
| 62 | child = container; |
| 63 | } else { |
| 64 | child = forward ? container.firstElementChild as HTMLElement : container.lastElementChild as HTMLElement; |
| 65 | } |
| 66 | |
| 67 | let focusableDescendant; |
| 68 | |
| 69 | /* eslint-disable no-await-in-loop */ |
| 70 | |
| 71 | while (child) { |
| 72 | const originalChild: HTMLElement | undefined = child; |
| 73 | |
| 74 | if (!isElementHidden(originalChild) && !isUI5ElementWithNegativeTabIndex(originalChild)) { |
| 75 | if (instanceOfUI5Element(child)) { |
| 76 | // getDomRef is used because some components mark their focusable ref in an inner |
| 77 | // html but there might also be focusable targets outside of it |
| 78 | // as an example - TreeItemBase |
| 79 | // div - root of the component returned by getDomRef() |
| 80 | // li.ui5-li-tree - returned by getFocusDomRef() and may not be focusable (ItemNavigation manages tabindex) |
| 81 | // ul.subtree - may still contain focusable targets (sub nodes of the tree item) |
| 82 | await child._waitForDomRef(); |
| 83 | child = child.getDomRef(); |
| 84 | } |
| 85 | |
| 86 | if (!child || isElementHidden(child)) { |
| 87 | return null; |
| 88 | } |
| 89 | |
| 90 | if (child.nodeType === 1 && isElemFocusable(child) && !isFocusTrap(child)) { |
| 91 | if (isElementClickable(child)) { |
| 92 | return (child && typeof child.focus === "function") ? child : null; |
| 93 | } |
| 94 | |
| 95 | focusableDescendant = await findFocusableElement(child, forward); |
| 96 | |
| 97 | // check if it is a keyboard focusable scroll container |
| 98 | if (!isSafari() && !focusableDescendant && isScrollable(child)) { |
| 99 | return (child && typeof child.focus === "function") ? child : null; |
| 100 | } |
| 101 | |
| 102 | if (focusableDescendant) { |
| 103 | return (focusableDescendant && typeof focusableDescendant.focus === "function") ? focusableDescendant : null; |
| 104 | } |
| 105 | } |
| 106 | } |
| 107 |
no test coverage detected
searching dependent graphs…