UNPKG

@uifabric/utilities

Version:

Fluent UI React utilities for building components.

86 lines 3.24 kB
import * as React from 'react'; import { getWindow } from './dom/getWindow'; import { isDirectionalKeyCode } from './keyboard'; import { setFocusVisibility } from './setFocusVisibility'; /** * Counter for mounted component that uses focus rectangle. * We want to cleanup the listners before last component that uses focus rectangle unmounts. */ var mountCounters = new WeakMap(); function setMountCounters(key, delta) { var newValue; var currValue = mountCounters.get(key); if (currValue) { newValue = currValue + delta; } else { newValue = 1; } mountCounters.set(key, newValue); return newValue; } /** * Initializes the logic which: * * 1. Subscribes keydown and mousedown events. (It will only do it once per window, * so it's safe to call this method multiple times.) * 2. When the user presses directional keyboard keys, adds the 'ms-Fabric--isFocusVisible' classname * to the document body, removes the 'ms-Fabric-isFocusHidden' classname. * 3. When the user clicks a mouse button, adds the 'ms-Fabric-isFocusHidden' classname to the * document body, removes the 'ms-Fabric--isFocusVisible' classname. * * This logic allows components on the page to conditionally render focus treatments based on * the existence of global classnames, which simplifies logic overall. * * @param rootRef - A Ref object. Focus rectangle can be applied on itself and all its children. */ export function useFocusRects(rootRef) { React.useEffect(function () { var _a, _b; var win = getWindow((_a = rootRef) === null || _a === void 0 ? void 0 : _a.current); if (!win || ((_b = win.FabricConfig) === null || _b === void 0 ? void 0 : _b.disableFocusRects) === true) { return undefined; } var count = setMountCounters(win, 1); if (count <= 1) { win.addEventListener('mousedown', _onMouseDown, true); win.addEventListener('pointerdown', _onPointerDown, true); win.addEventListener('keydown', _onKeyDown, true); } return function () { var _a; if (!win || ((_a = win.FabricConfig) === null || _a === void 0 ? void 0 : _a.disableFocusRects) === true) { return; } count = setMountCounters(win, -1); if (count === 0) { win.removeEventListener('mousedown', _onMouseDown, true); win.removeEventListener('pointerdown', _onPointerDown, true); win.removeEventListener('keydown', _onKeyDown, true); } }; }, [rootRef]); } /** * Function Component wrapper which enables calling `useFocusRects` hook. * Renders nothing. */ export var FocusRects = function (props) { useFocusRects(props.rootRef); return null; }; function _onMouseDown(ev) { setFocusVisibility(false, ev.target); } function _onPointerDown(ev) { if (ev.pointerType !== 'mouse') { setFocusVisibility(false, ev.target); } } function _onKeyDown(ev) { // eslint-disable-next-line deprecation/deprecation if (isDirectionalKeyCode(ev.which)) { setFocusVisibility(true, ev.target); } } //# sourceMappingURL=useFocusRects.js.map