UNPKG

react-aim-menu

Version:

A React version of Amazon's jQuery-menu-aim plugin

255 lines (236 loc) 9.82 kB
import {jsx as $jp1wC$jsx} from "react/jsx-runtime"; import $jp1wC$react, {useState as $jp1wC$useState, useContext as $jp1wC$useContext, useEffect as $jp1wC$useEffect, createContext as $jp1wC$createContext, forwardRef as $jp1wC$forwardRef, useRef as $jp1wC$useRef, useMemo as $jp1wC$useMemo} from "react"; function $03683a42a6c08b9c$export$567fc7097e064344() { return '_' + Math.random().toString(36).substr(2, 9); } const $03683a42a6c08b9c$export$642213d516a9b928 = function(mouseEvent) { let pos = { x: 0, y: 0 }; if (mouseEvent.pageX || mouseEvent.pageY) pos = { x: mouseEvent.pageX, y: mouseEvent.pageY }; else if (mouseEvent.clientX || mouseEvent.clientY) pos = { x: mouseEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft, y: mouseEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop }; return pos; }; const $03683a42a6c08b9c$export$c32a249941905394 = function(elem) { const boundingBox = elem.getBoundingClientRect(); const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; const scrollTop = window.pageYOffset || document.documentElement.scrollTop; return { topLeft: { x: boundingBox.left + scrollLeft, y: boundingBox.top + scrollTop }, topRight: { x: boundingBox.left + scrollLeft + boundingBox.width, y: boundingBox.top + scrollTop }, bottomLeft: { x: boundingBox.left + scrollLeft, y: boundingBox.top + scrollTop + boundingBox.height }, bottomRight: { x: boundingBox.left + scrollLeft + boundingBox.width, y: boundingBox.top + scrollTop + boundingBox.height } }; }; const $03683a42a6c08b9c$export$534bdd1067f4ef34 = function(menuBox, point, direction = 'right') { if (direction === 'right') { const height = menuBox.bottomRight.y - menuBox.topRight.y; return { A: { x: point.x, y: point.y }, B: { x: menuBox.topRight.x, y: Math.min(0, menuBox.topRight.y - height) }, C: { x: menuBox.bottomRight.x, y: Math.max(window.innerHeight + height, menuBox.bottomRight.y + height) } }; } else if (direction === 'down') return { A: point, B: menuBox.topRight, C: menuBox.bottomRight }; }; const $03683a42a6c08b9c$export$20fc610e43966a58 = function(triangle, point) { const { A: A , B: B , C: C } = triangle; return $03683a42a6c08b9c$var$checkSameSide($03683a42a6c08b9c$var$toEdge(A, B), C, point) && $03683a42a6c08b9c$var$checkSameSide($03683a42a6c08b9c$var$toEdge(A, C), B, point) && $03683a42a6c08b9c$var$checkSameSide($03683a42a6c08b9c$var$toEdge(B, C), A, point); }; const $03683a42a6c08b9c$var$checkSameSide = function(edge, point1, point2) { return $03683a42a6c08b9c$var$getPolarity(edge, point1) === $03683a42a6c08b9c$var$getPolarity(edge, point2); }; const $03683a42a6c08b9c$var$getPolarity = function(edge, point) { const vectorA = $03683a42a6c08b9c$var$toVector(edge.v1, edge.v2); const vectorB = $03683a42a6c08b9c$var$toVector(edge.v1, point); const scalar = vectorA.x * vectorB.y - vectorA.y * vectorB.x; return scalar >= 0 ? 1 : -1; }; const $03683a42a6c08b9c$var$toEdge = function(pointA, pointB) { return { v1: { ...pointA }, v2: { ...pointB } }; }; const $03683a42a6c08b9c$var$toVector = function(pointA, pointB) { return { x: pointB.x - pointA.x, y: pointB.y - pointA.y }; }; function $8198c3a472ced9dd$var$setRef(ref, value) { if (!ref) return; if (typeof ref === 'function') ref(value); else if (ref) ref.current = value; } /** * useForkRef * Joins refs together and returns a combination of the two as a new ref * * @param refA * @param refB */ function $8198c3a472ced9dd$export$ebc1e1560c2dffa5(refA, refB) { /** * This will create a new function if the ref props change and are defined. * This means react will call the old forkRef with `null` and the new forkRef * with the ref. Cleanup naturally emerges from this behavior */ return $jp1wC$useMemo(()=>{ if (refA == null && refB == null) return null; return (refValue)=>{ $8198c3a472ced9dd$var$setRef(refA, refValue); $8198c3a472ced9dd$var$setRef(refB, refValue); }; }, [ refA, refB ]); } const $2bfe47a3fcaebb7f$var$state = { pendingExpand: { item: null, timeoutId: null }, mouseHistory: [] }; function $2bfe47a3fcaebb7f$var$clearPendingExpand() { if ($2bfe47a3fcaebb7f$var$state.pendingExpand && $2bfe47a3fcaebb7f$var$state.pendingExpand.timeoutId) clearTimeout($2bfe47a3fcaebb7f$var$state.pendingExpand.timeoutId); $2bfe47a3fcaebb7f$var$state.pendingExpand = null; } function $2bfe47a3fcaebb7f$var$checkAim(menuElem) { if ($2bfe47a3fcaebb7f$var$state.mouseHistory.length < 2) return false; const currentPosition = $2bfe47a3fcaebb7f$var$state.mouseHistory[$2bfe47a3fcaebb7f$var$state.mouseHistory.length - 1]; const prevPosition = $2bfe47a3fcaebb7f$var$state.mouseHistory[0]; const menuBox = $03683a42a6c08b9c$export$c32a249941905394(menuElem); const triangle = $03683a42a6c08b9c$export$534bdd1067f4ef34(menuBox, prevPosition); return $03683a42a6c08b9c$export$20fc610e43966a58(triangle, currentPosition); } const $2bfe47a3fcaebb7f$var$defaultState = { }; const $2bfe47a3fcaebb7f$var$DEFAULT_HOVER_DELAY = 450; const $2bfe47a3fcaebb7f$var$MOUSE_HISTORY_SIZE = 3; const $2bfe47a3fcaebb7f$export$c7e742effb1c51e2 = /*#__PURE__*/ $jp1wC$createContext($2bfe47a3fcaebb7f$var$defaultState); const $2bfe47a3fcaebb7f$var$Menu = /*#__PURE__*/ $jp1wC$forwardRef(function Menu({ hoverDelay: hoverDelay = $2bfe47a3fcaebb7f$var$DEFAULT_HOVER_DELAY , ...props }, ref) { const menuRef = $jp1wC$useRef(null); const forkedRef = $8198c3a472ced9dd$export$ebc1e1560c2dffa5(ref, menuRef); const [expandedItem, setExpandedItem] = $jp1wC$useState(null); function updateExpand() { if (!$2bfe47a3fcaebb7f$var$state.pendingExpand || expandedItem === $2bfe47a3fcaebb7f$var$state.pendingExpand.item) return; setExpandedItem($2bfe47a3fcaebb7f$var$state.pendingExpand.item); $2bfe47a3fcaebb7f$var$state.mouseHistory = []; $2bfe47a3fcaebb7f$var$clearPendingExpand(); } function onItemEnter(item) { $2bfe47a3fcaebb7f$var$clearPendingExpand(); $2bfe47a3fcaebb7f$var$state.pendingExpand = { item: item }; if (!expandedItem || !$2bfe47a3fcaebb7f$var$checkAim(menuRef.current)) return updateExpand(); $2bfe47a3fcaebb7f$var$state.pendingExpand.timeoutId = setTimeout(()=>updateExpand() , hoverDelay); } function onItemLeave() { $2bfe47a3fcaebb7f$var$state.pendingExpand = { item: null, timeoutId: setTimeout(()=>updateExpand() , hoverDelay + 100) }; } function onMouseMove(event) { props.onMouseMove && props.onMouseMove(event); $2bfe47a3fcaebb7f$var$state.mouseHistory.push($03683a42a6c08b9c$export$642213d516a9b928(event.nativeEvent)); if ($2bfe47a3fcaebb7f$var$state.mouseHistory.length > $2bfe47a3fcaebb7f$var$MOUSE_HISTORY_SIZE) $2bfe47a3fcaebb7f$var$state.mouseHistory.shift(); } function handleMenuLeave(event) { props.onMouseLeave && props.onMouseLeave(event); $2bfe47a3fcaebb7f$var$clearPendingExpand(); setExpandedItem(null); } return(/*#__PURE__*/ $jp1wC$jsx($2bfe47a3fcaebb7f$export$c7e742effb1c51e2.Provider, { value: { onItemEnter: onItemEnter, onItemLeave: onItemLeave, expandedItem: expandedItem }, children: /*#__PURE__*/ $jp1wC$jsx("div", { ...props, ref: forkedRef, onMouseLeave: handleMenuLeave, onMouseMove: onMouseMove, children: props.children }) })); }); var $2bfe47a3fcaebb7f$export$2e2bcd8739ae039 = $2bfe47a3fcaebb7f$var$Menu; const $d070a06810ab4d73$var$MenuItem = /*#__PURE__*/ $jp1wC$react.forwardRef(function MenuItem({ onHover: onHover , onLeave: onLeave , ...props }, ref) { const [id, setId] = $jp1wC$useState(null); const [expanded, setExpanded] = $jp1wC$useState(false); const menu = $jp1wC$useContext($2bfe47a3fcaebb7f$export$c7e742effb1c51e2); $jp1wC$useEffect(()=>{ setId($03683a42a6c08b9c$export$567fc7097e064344()); }, []); $jp1wC$useEffect(()=>{ if (menu.expandedItem && menu.expandedItem === id && !expanded) { setExpanded(true); onHover && onHover(); } if (menu.expandedItem !== id && expanded) { setExpanded(false); onLeave && onLeave(); } }, [ menu.expandedItem ]); function handleMouseEnter(event) { menu.onItemEnter(id); props.onMouseEnter && props.onMouseEnter(event); } function handleMouseLeave(event) { menu.onItemLeave(); props.onMouseLeave && props.onMouseLeave(event); } return(/*#__PURE__*/ $jp1wC$jsx("div", { ...props, ref: ref, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: props.children })); }); var $d070a06810ab4d73$export$2e2bcd8739ae039 = $d070a06810ab4d73$var$MenuItem; export {$d070a06810ab4d73$export$2e2bcd8739ae039 as MenuItem, $2bfe47a3fcaebb7f$export$2e2bcd8739ae039 as Menu}; //# sourceMappingURL=module.js.map