()
| 310 | } |
| 311 | }; |
| 312 | const trapShadowFocus = () => { |
| 313 | /** |
| 314 | * If the target is inside the wrapper, let the browser |
| 315 | * focus as normal and keep a log of the last focused element. |
| 316 | */ |
| 317 | if (lastOverlay.contains(target)) { |
| 318 | lastOverlay.lastFocus = target; |
| 319 | /** |
| 320 | * Toasts can be presented from an overlay. |
| 321 | * However, focus should still be returned to |
| 322 | * the overlay when clicking a toast. Normally, |
| 323 | * focus would be returned to the last focusable |
| 324 | * descendant in the overlay which may not always be |
| 325 | * the button that the toast was presented from. In this case, |
| 326 | * the focus may be returned to an unexpected element. |
| 327 | * To account for this, we make sure to return focus to the |
| 328 | * last focused element in the overlay if focus is |
| 329 | * moved to the toast. |
| 330 | */ |
| 331 | } else if (target.tagName === 'ION-TOAST') { |
| 332 | focusElementInOverlay(lastOverlay.lastFocus, lastOverlay); |
| 333 | } else { |
| 334 | /** |
| 335 | * Otherwise, we are about to have focus |
| 336 | * go out of the overlay. We need to wrap |
| 337 | * the focus to either the first element |
| 338 | * or the last element. |
| 339 | */ |
| 340 | |
| 341 | /** |
| 342 | * Once we call `focusFirstDescendant` and focus the first |
| 343 | * descendant, another focus event will fire which will |
| 344 | * cause `lastOverlay.lastFocus` to be updated before |
| 345 | * we can run the code after that. We will cache the value |
| 346 | * here to avoid that. |
| 347 | */ |
| 348 | const lastFocus = lastOverlay.lastFocus; |
| 349 | |
| 350 | // Focus the first element in the overlay wrapper |
| 351 | focusFirstDescendant(lastOverlay); |
| 352 | |
| 353 | /** |
| 354 | * If the cached last focused element is the |
| 355 | * same as the active element, then we need |
| 356 | * to wrap focus to the last descendant. This happens |
| 357 | * when the first descendant is focused, and the user |
| 358 | * presses Shift + Tab. The previous line will focus |
| 359 | * the same descendant again (the first one), causing |
| 360 | * last focus to equal the active element. |
| 361 | */ |
| 362 | if (lastFocus === doc.activeElement) { |
| 363 | focusLastDescendant(lastOverlay); |
| 364 | } |
| 365 | lastOverlay.lastFocus = doc.activeElement as HTMLElement; |
| 366 | } |
| 367 | }; |
| 368 | |
| 369 | if (lastOverlay.shadowRoot) { |
no test coverage detected