UNPKG

@fluentui/react-northstar

Version:
279 lines (242 loc) 7.91 kB
import { isBrowser } from './isBrowser'; // Taken from https://github.com/ten1seven/what-input/blob/master/src/scripts/what-input.js /* eslint-disable */ /* * variables */ // last used input type var currentInput = 'mouse'; // assume happy path // event buffer timer var eventTimer = null; // list of modifier keys commonly used with the mouse and // can be safely ignored to prevent false keyboard detection var ignoreMap = [16, // shift 17, // control 18, // alt 91, // Windows key / left Apple cmd 93 // Windows menu / right Apple cmd ]; // used to count how many Providers needed to initialize whatinput. var whatInputInitialized = 'whatInputInitialized'; // mapping of events to input types var inputMap = { keydown: 'keyboard', keyup: 'keyboard', mousedown: 'mouse', mousemove: 'mouse', MSPointerDown: 'pointer', MSPointerMove: 'pointer', pointerdown: 'pointer', pointermove: 'pointer', touchstart: 'touch' }; // boolean: true if touch buffer is active var isBuffering = false; // map of IE 10 pointer events var pointerMap = { 2: 'touch', 3: 'touch', // treat pen like touch 4: 'mouse' }; // check support for passive event listeners var supportsPassive = false; try { var opts = Object.defineProperty({}, 'passive', { get: function get() { supportsPassive = true; } }); window.addEventListener('test', null, opts); } catch (e) {} /* * set up */ var setUp = function setUp() { // add correct mouse wheel event mapping to `inputMap` inputMap[detectWheel()] = 'mouse'; addListeners(window); doUpdate(window.document); }; /* * events */ var addListeners = function addListeners(eventTarget) { // `pointermove`, `MSPointerMove`, `mousemove` and mouse wheel event binding // can only demonstrate potential, but not actual, interaction // and are treated separately var options = supportsPassive ? { passive: true, capture: true } : true; // pointer events (mouse, pen, touch) // @ts-ignore if (eventTarget.PointerEvent) { eventTarget.addEventListener('pointerdown', setInput); // @ts-ignore } else if (window.MSPointerEvent) { eventTarget.addEventListener('MSPointerDown', setInput); } else { // mouse events eventTarget.addEventListener('mousedown', setInput, true); // touch events if ('ontouchstart' in eventTarget) { eventTarget.addEventListener('touchstart', eventBuffer, options); eventTarget.addEventListener('touchend', setInput, true); } } // keyboard events eventTarget.addEventListener('keydown', eventBuffer, true); eventTarget.addEventListener('keyup', eventBuffer, true); }; /** * * @param document document to apply the update to * @param eventKey keyboard key passed from the event * @returns true if mode should be switched, false if not (when an input-like element is focused, and the key was not a navigational key) */ var keyboardInputFocused = function keyboardInputFocused(document, eventKey) { if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA' || document.activeElement.getAttribute('contenteditable')) { return eventKey === 9 || // tab eventKey === 117; // F6 } return true; }; // checks conditions before updating new input var setInput = function setInput(event) { // only execute if the event buffer timer isn't running if (!isBuffering) { var eventKey = event.which; var value = inputMap[event.type]; if (value === 'pointer') { value = pointerType(event); } var ignoreMatch = ignoreMap.indexOf(eventKey) === -1; var shouldUpdate = value === 'keyboard' && eventKey && ignoreMatch && keyboardInputFocused(event.view.document, eventKey) || value === 'mouse' || value === 'touch'; if (currentInput !== value && shouldUpdate) { currentInput = value; // https://github.com/testing-library/user-event/issues/709 // JSDOM does not implement `event.view` so prune this code path in test if (process.env.NODE_ENV !== 'test') { doUpdate(event.view.document); } } } }; // updates the doc and `inputTypes` array with new input var doUpdate = function doUpdate(target) { target.documentElement.setAttribute("data-whatinput", currentInput); }; // buffers events that frequently also fire mouse events var eventBuffer = function eventBuffer(event) { // set the current input setInput(event); // clear the timer if it happens to be running window.clearTimeout(eventTimer); // set the isBuffering to `true` isBuffering = true; // run the timer eventTimer = window.setTimeout(function () { // if the timer runs out, set isBuffering back to `false` isBuffering = false; }, 100); }; /* * utilities */ var pointerType = function pointerType(event) { if (typeof event.pointerType === 'number') { return pointerMap[event.pointerType]; } // treat pen like touch return event.pointerType === 'pen' ? 'touch' : event.pointerType; }; // detect version of mouse wheel event to use // via https://developer.mozilla.org/en-US/docs/Web/Events/wheel var detectWheel = function detectWheel() { var wheelType; // Modern browsers support "wheel" if ('onwheel' in document.createElement('div')) { wheelType = 'wheel'; } else { // Webkit and IE support at least "mousewheel" // or assume that remaining browsers are older Firefox wheelType = // @ts-ignore document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll'; } return wheelType; }; // don't start script unless browser cuts the mustard // (also passes if polyfills are used) if (isBrowser() && 'addEventListener' in window && Array.prototype.indexOf) { setUp(); } /* * set up for document */ export var setUpWhatInput = function setUpWhatInput(target) { var targetWindow = target.defaultView; if (isBrowser() && targetWindow && 'addEventListener' in targetWindow && Array.prototype.indexOf) { var initializedTimes = target[whatInputInitialized]; if (typeof initializedTimes === 'number' && initializedTimes > 0) { target[whatInputInitialized] = initializedTimes + 1; return; } target[whatInputInitialized] = 1; addListeners(targetWindow); doUpdate(target); } }; function cleanupWhatInput(eventTarget) { var options = supportsPassive ? { capture: true } : true; // @ts-ignore if (eventTarget.PointerEvent) { eventTarget.removeEventListener('pointerdown', setInput); // @ts-ignore } else if (window.MSPointerEvent) { eventTarget.removeEventListener('MSPointerDown', setInput); } else { // mouse events eventTarget.removeEventListener('mousedown', setInput, true); // touch events if ('ontouchstart' in eventTarget) { eventTarget.removeEventListener('touchstart', eventBuffer, options); eventTarget.removeEventListener('touchend', setInput, true); } } // keyboard events eventTarget.removeEventListener('keydown', eventBuffer, true); eventTarget.removeEventListener('keyup', eventBuffer, true); } export var tryCleanupWhatInput = function tryCleanupWhatInput(target) { var targetWindow = target.defaultView; if (isBrowser() && targetWindow && 'removeEventListener' in targetWindow) { if (target[whatInputInitialized] === 1) { delete target[whatInputInitialized]; cleanupWhatInput(targetWindow); } else { target[whatInputInitialized] = target[whatInputInitialized] - 1; } } }; export var setWhatInputSource = function setWhatInputSource(target, newInput) { currentInput = newInput; doUpdate(target); }; // returns string: the current input type // returns the same value as the `data-whatinput` attribute export var ask = function ask() { return currentInput; }; export var isFromKeyboard = function isFromKeyboard() { return ask() === 'keyboard'; }; //# sourceMappingURL=whatInput.js.map