UNPKG

@wix/design-system

Version:

@wix/design-system

123 lines (121 loc) 4.52 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.useHover = exports.createHoverHandlers = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = require("react"); // Pointer-aware hover that ignores touch — without this, Stylable's JS-toggled // `:hovered` sticks on tap (mobile fires `mouseenter` but no `mouseleave`). // Mouse listeners are kept for unidriver test fakes; duplicate pointer/mouse // pairs from real browsers are deduped via WeakMap. var POINTER_TO_MOUSE_DEDUPE_MS = 50; var recentPointerEvents = new WeakMap(); var isHoverCapablePointer = pointerType => pointerType === 'mouse' || pointerType === 'pen'; var markPointerHandled = target => { if (target) { recentPointerEvents.set(target, Date.now()); } }; var recentlyHandledByPointer = target => { if (!target) return false; var at = recentPointerEvents.get(target); return at !== undefined && Date.now() - at < POINTER_TO_MOUSE_DEDUPE_MS; }; var useHover = exports.useHover = function useHover() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, isDisabled = _ref.isDisabled, onHoverStart = _ref.onHoverStart, onHoverEnd = _ref.onHoverEnd; var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), hovered = _useState2[0], setHovered = _useState2[1]; var isHoveredRef = (0, _react.useRef)(false); var onHoverStartRef = (0, _react.useRef)(onHoverStart); var onHoverEndRef = (0, _react.useRef)(onHoverEnd); (0, _react.useEffect)(() => { onHoverStartRef.current = onHoverStart; onHoverEndRef.current = onHoverEnd; }); var triggerHoverStart = (0, _react.useCallback)(event => { if (isHoveredRef.current) return; isHoveredRef.current = true; setHovered(true); onHoverStartRef.current == null || onHoverStartRef.current(event); }, []); var triggerHoverEnd = (0, _react.useCallback)(event => { if (!isHoveredRef.current) return; isHoveredRef.current = false; setHovered(false); onHoverEndRef.current == null || onHoverEndRef.current(event); }, []); (0, _react.useEffect)(() => { if (isDisabled && isHoveredRef.current) { isHoveredRef.current = false; setHovered(false); } }, [isDisabled]); var hoverProps = (0, _react.useMemo)(() => ({ onPointerEnter: event => { markPointerHandled(event.currentTarget); if (isDisabled || !isHoverCapablePointer(event.pointerType)) { return; } triggerHoverStart(event); }, onPointerLeave: event => { markPointerHandled(event.currentTarget); if (!isHoverCapablePointer(event.pointerType)) { return; } triggerHoverEnd(event); }, onMouseEnter: event => { if (recentlyHandledByPointer(event.currentTarget)) return; if (isDisabled) return; triggerHoverStart(event); }, onMouseLeave: event => { if (recentlyHandledByPointer(event.currentTarget)) return; triggerHoverEnd(event); } }), [isDisabled, triggerHoverStart, triggerHoverEnd]); return { hovered, hoverProps }; }; // Stateless variant for components that already manage hover state externally // (e.g. per-item indices in DropdownLayout, RadarChart, FacesRatingBar). var createHoverHandlers = exports.createHoverHandlers = function createHoverHandlers() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, isDisabled = _ref2.isDisabled, onHoverStart = _ref2.onHoverStart, onHoverEnd = _ref2.onHoverEnd; return { onPointerEnter: event => { markPointerHandled(event.currentTarget); if (isDisabled || !isHoverCapablePointer(event.pointerType)) { return; } onHoverStart == null || onHoverStart(event); }, onPointerLeave: event => { markPointerHandled(event.currentTarget); if (!isHoverCapablePointer(event.pointerType)) { return; } onHoverEnd == null || onHoverEnd(event); }, onMouseEnter: event => { if (recentlyHandledByPointer(event.currentTarget)) return; if (isDisabled) return; onHoverStart == null || onHoverStart(event); }, onMouseLeave: event => { if (recentlyHandledByPointer(event.currentTarget)) return; onHoverEnd == null || onHoverEnd(event); } }; }; //# sourceMappingURL=useHover.js.map