(ev: Event, doc: Document)
| 425 | } |
| 426 | |
| 427 | private trapKeyboardFocus(ev: Event, doc: Document) { |
| 428 | const target = ev.target as HTMLElement | null; |
| 429 | |
| 430 | if (!target) { |
| 431 | return; |
| 432 | } |
| 433 | |
| 434 | /** |
| 435 | * If the target is inside the menu contents, let the browser |
| 436 | * focus as normal and keep a log of the last focused element. |
| 437 | */ |
| 438 | if (this.el.contains(target)) { |
| 439 | this.lastFocus = target; |
| 440 | } else { |
| 441 | /** |
| 442 | * Otherwise, we are about to have focus go out of the menu. |
| 443 | * Wrap the focus to either the first or last element. |
| 444 | */ |
| 445 | |
| 446 | const { el } = this; |
| 447 | |
| 448 | /** |
| 449 | * Once we call `focusFirstDescendant`, another focus event |
| 450 | * will fire, which will cause `lastFocus` to be updated |
| 451 | * before we can run the code after that. We cache the value |
| 452 | * here to avoid that. |
| 453 | */ |
| 454 | focusFirstDescendant(el); |
| 455 | |
| 456 | /** |
| 457 | * If the cached last focused element is the same as the now- |
| 458 | * active element, that means the user was on the first element |
| 459 | * already and pressed Shift + Tab, so we need to wrap to the |
| 460 | * last descendant. |
| 461 | */ |
| 462 | if (this.lastFocus === doc.activeElement) { |
| 463 | focusLastDescendant(el); |
| 464 | } |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | async _setOpen(shouldOpen: boolean, animated = true, role?: string): Promise<boolean> { |
| 469 | // If the menu is disabled or it is currently being animated, let's do nothing |
no test coverage detected