78 lines
2.7 KiB
JavaScript
78 lines
2.7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "applyFocusVisiblePolyfill", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return applyFocusVisiblePolyfill;
|
|
}
|
|
});
|
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
const _keyborg = require("keyborg");
|
|
const _constants = require("./constants");
|
|
function applyFocusVisiblePolyfill(scope, targetWindow) {
|
|
if (alreadyInScope(scope)) {
|
|
// Focus visible polyfill already applied at this scope
|
|
return ()=>undefined;
|
|
}
|
|
const state = {
|
|
current: undefined
|
|
};
|
|
const keyborg = (0, _keyborg.createKeyborg)(targetWindow);
|
|
function registerElementIfNavigating(el) {
|
|
if (keyborg.isNavigatingWithKeyboard() && (0, _reactutilities.isHTMLElement)(el)) {
|
|
state.current = el;
|
|
el.setAttribute(_constants.FOCUS_VISIBLE_ATTR, '');
|
|
}
|
|
}
|
|
function disposeCurrentElement() {
|
|
if (state.current) {
|
|
state.current.removeAttribute(_constants.FOCUS_VISIBLE_ATTR);
|
|
state.current = undefined;
|
|
}
|
|
}
|
|
// When navigation mode changes remove the focus-visible selector
|
|
keyborg.subscribe((isNavigatingWithKeyboard)=>{
|
|
if (!isNavigatingWithKeyboard) {
|
|
disposeCurrentElement();
|
|
}
|
|
});
|
|
// Keyborg's focusin event is delegated so it's only registered once on the window
|
|
// and contains metadata about the focus event
|
|
const keyborgListener = (e)=>{
|
|
disposeCurrentElement();
|
|
const target = e.composedPath()[0];
|
|
registerElementIfNavigating(target);
|
|
};
|
|
// Make sure that when focus leaves the scope, the focus visible class is removed
|
|
const blurListener = (e)=>{
|
|
if (!e.relatedTarget || (0, _reactutilities.isHTMLElement)(e.relatedTarget) && !scope.contains(e.relatedTarget)) {
|
|
disposeCurrentElement();
|
|
}
|
|
};
|
|
scope.addEventListener(_keyborg.KEYBORG_FOCUSIN, keyborgListener);
|
|
scope.addEventListener('focusout', blurListener);
|
|
scope.focusVisible = true;
|
|
if (scope.contains(targetWindow.document.activeElement)) {
|
|
registerElementIfNavigating(targetWindow.document.activeElement);
|
|
}
|
|
// Return disposer
|
|
return ()=>{
|
|
disposeCurrentElement();
|
|
scope.removeEventListener(_keyborg.KEYBORG_FOCUSIN, keyborgListener);
|
|
scope.removeEventListener('focusout', blurListener);
|
|
delete scope.focusVisible;
|
|
(0, _keyborg.disposeKeyborg)(keyborg);
|
|
};
|
|
}
|
|
function alreadyInScope(el) {
|
|
if (!el) {
|
|
return false;
|
|
}
|
|
if (el.focusVisible) {
|
|
return true;
|
|
}
|
|
return alreadyInScope(el === null || el === void 0 ? void 0 : el.parentElement);
|
|
}
|