(target: FocusableElement | null)
| 119 | * using a capturing listener on the window and stopping propagation. |
| 120 | */ |
| 121 | export function preventFocus(target: FocusableElement | null): (() => void) | undefined { |
| 122 | // The browser will focus the nearest focusable ancestor of our target. |
| 123 | while (target && !isFocusable(target, {skipVisibilityCheck: true})) { |
| 124 | target = target.parentElement; |
| 125 | } |
| 126 | |
| 127 | let window = getOwnerWindow(target); |
| 128 | let activeElement = window.document.activeElement as FocusableElement | null; |
| 129 | if (!activeElement || activeElement === target) { |
| 130 | return; |
| 131 | } |
| 132 | |
| 133 | ignoreFocusEvent = true; |
| 134 | let isRefocusing = false; |
| 135 | let onBlur = (e: FocusEvent) => { |
| 136 | if (getEventTarget(e) === activeElement || isRefocusing) { |
| 137 | e.stopImmediatePropagation(); |
| 138 | } |
| 139 | }; |
| 140 | |
| 141 | let onFocusOut = (e: FocusEvent) => { |
| 142 | if (getEventTarget(e) === activeElement || isRefocusing) { |
| 143 | e.stopImmediatePropagation(); |
| 144 | |
| 145 | // If there was no focusable ancestor, we don't expect a focus event. |
| 146 | // Re-focus the original active element here. |
| 147 | if (!target && !isRefocusing) { |
| 148 | isRefocusing = true; |
| 149 | focusWithoutScrolling(activeElement); |
| 150 | cleanup(); |
| 151 | } |
| 152 | } |
| 153 | }; |
| 154 | |
| 155 | let onFocus = (e: FocusEvent) => { |
| 156 | if (getEventTarget(e) === target || isRefocusing) { |
| 157 | e.stopImmediatePropagation(); |
| 158 | } |
| 159 | }; |
| 160 | |
| 161 | let onFocusIn = (e: FocusEvent) => { |
| 162 | if (getEventTarget(e) === target || isRefocusing) { |
| 163 | e.stopImmediatePropagation(); |
| 164 | |
| 165 | if (!isRefocusing) { |
| 166 | isRefocusing = true; |
| 167 | focusWithoutScrolling(activeElement); |
| 168 | cleanup(); |
| 169 | } |
| 170 | } |
| 171 | }; |
| 172 | |
| 173 | window.addEventListener('blur', onBlur, true); |
| 174 | window.addEventListener('focusout', onFocusOut, true); |
| 175 | window.addEventListener('focusin', onFocusIn, true); |
| 176 | window.addEventListener('focus', onFocus, true); |
| 177 | |
| 178 | let cleanup = () => { |
no test coverage detected