UNPKG

@elastic/eui

Version:

Elastic UI Component Library

195 lines (190 loc) 8.24 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ import { useCallback, useEffect, useRef } from 'react'; import { keys } from '../../services/keys'; var DISABLED_ELEMENT_EVENTS = { click: 'onClick', mousedown: 'onMouseDown', mouseup: 'onMouseUp', mouseenter: 'onMouseEnter', mouseleave: 'onMouseLeave', mouseout: 'onMouseOut', mousemove: 'onMouseMove', mouseover: 'onMouseOver', pointerdown: 'onPointerDown', pointerup: 'onPointerUp', pointerenter: 'onPointerEnter', pointerleave: 'onPointerLeave', pointermove: 'onPointerMove', pointerover: 'onPointerOver', touchstart: 'onTouchStart', touchend: 'onTouchEnd', touchmove: 'onTouchMove', keydown: 'onKeyDown', keyup: 'onKeyUp', keypress: 'onKeyPress', submit: 'onSubmit' }; var ALLOWED_KEY_EVENTS = [keys.TAB, keys.ESCAPE]; var getReactEventHandlers = function getReactEventHandlers() { return Object.values(DISABLED_ELEMENT_EVENTS).reduce(function (acc, curr) { acc[curr] = undefined; return acc; }, {}); }; var UNSET_REACT_EVENT_HANDLERS = getReactEventHandlers(); var useCustomDisabledEvents = function useCustomDisabledEvents() { var elementMethodsRef = useRef(null); var isAllowedKeyEvent = function isAllowedKeyEvent(event) { return event instanceof KeyboardEvent && ALLOWED_KEY_EVENTS.includes(event.key); }; var preventEvent = useCallback(function (event) { if (isAllowedKeyEvent(event)) { return; } event.stopImmediatePropagation(); event.preventDefault(); event.stopPropagation(); }, []); var preventElementEvents = useCallback(function (element) { if (elementMethodsRef.current) return; var originalEvents = { click: 'click' in element ? element.click : undefined, dispatchEvent: element.dispatchEvent }; try { elementMethodsRef.current = originalEvents; // Add prevention listeners Object.keys(DISABLED_ELEMENT_EVENTS).forEach(function (eventType) { element.addEventListener(eventType, preventEvent, { capture: true }); }); if ('click' in element && typeof element.click === 'function') { element.click = function () {}; } element.dispatchEvent = function (event) { if (Object.keys(DISABLED_ELEMENT_EVENTS).includes(event.type)) { if (isAllowedKeyEvent(event)) { return originalEvents.dispatchEvent.call(element, event); } return false; } return originalEvents.dispatchEvent.call(element, event); }; } catch (error) { elementMethodsRef.current = null; } }, [preventEvent]); var resetElementEvents = useCallback(function (element) { if (!elementMethodsRef.current) return; var _elementMethodsRef$cu = elementMethodsRef.current, click = _elementMethodsRef$cu.click, dispatchEvent = _elementMethodsRef$cu.dispatchEvent; try { // remove prevention listeners Object.keys(DISABLED_ELEMENT_EVENTS).forEach(function (eventType) { element.removeEventListener(eventType, preventEvent, { capture: true }); }); // restore click method if (click && 'click' in element) { element.click = click; } // restore dispatchEvent element.dispatchEvent = dispatchEvent; } catch (error) {} elementMethodsRef.current = null; }, [preventEvent]); return { preventElementEvents: preventElementEvents, resetElementEvents: resetElementEvents }; }; /** * NOTE: Beta feature, may be changed or removed in the future * * Utility to apply either the native or a custom semantic disabled state. * * It applies `aria-disabled` instead of `disabled` when `hasAriaDisabled=true` * to ensure the element is semantically disabled while still focusable. * * It mimics the native `disabled` behavior by removing any programmatic mouse, pointer, touch * or keyboard event handler but it differs to the native `disabled` behavior in that it preserves * the focus, blur and tabIndex behavior. */ export var useEuiDisabledElement = function useEuiDisabledElement(_ref) { var _ref$isDisabled = _ref.isDisabled, isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled, _ref$hasAriaDisabled = _ref.hasAriaDisabled, hasAriaDisabled = _ref$hasAriaDisabled === void 0 ? false : _ref$hasAriaDisabled, onKeyDown = _ref.onKeyDown, onKeyUp = _ref.onKeyUp, onKeyPress = _ref.onKeyPress; var elementRef = useRef(null); var _useCustomDisabledEve = useCustomDisabledEvents(), preventElementEvents = _useCustomDisabledEve.preventElementEvents, resetElementEvents = _useCustomDisabledEve.resetElementEvents; var shouldBeDisabled = hasAriaDisabled && isDisabled; var setRef = useCallback(function (node) { if (elementRef.current) { resetElementEvents(elementRef.current); } elementRef.current = node; if (node && shouldBeDisabled) { preventElementEvents(node); } }, [shouldBeDisabled, preventElementEvents, resetElementEvents]); useEffect(function () { if (!elementRef.current) return; if (shouldBeDisabled) { preventElementEvents(elementRef.current); } else { resetElementEvents(elementRef.current); } return function () { if (elementRef.current) { resetElementEvents(elementRef.current); } }; }, [shouldBeDisabled, preventElementEvents, resetElementEvents]); if (!hasAriaDisabled) { return { ref: setRef, disabled: isDisabled }; } var onKeyboardEvent = function onKeyboardEvent(e, callback) { if (ALLOWED_KEY_EVENTS.includes(e.key)) { callback === null || callback === void 0 || callback(e); } }; var eventHandlers = shouldBeDisabled && _objectSpread(_objectSpread({}, UNSET_REACT_EVENT_HANDLERS), {}, { onKeyDown: onKeyDown ? function (e) { return onKeyboardEvent(e, onKeyDown); } : undefined, onKeyUp: onKeyUp ? function (e) { return onKeyboardEvent(e, onKeyUp); } : undefined, onKeyPress: onKeyPress ? function (e) { return onKeyboardEvent(e, onKeyPress); } : undefined }); return _objectSpread({ ref: setRef, 'aria-disabled': isDisabled ? true : undefined, disabled: isDisabled ? undefined : false }, eventHandlers); };