focus-pro
Version:
focus-pro 中台前端组件库
165 lines (159 loc) • 7.05 kB
JavaScript
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import "./index.module.less";
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
import { Fragment as _Fragment } from "react/jsx-runtime";
var RightMenu = function RightMenu(props) {
var position = props.position,
menuItems = props.menuItems,
_props$className = props.className,
className = _props$className === void 0 ? '' : _props$className,
seeState = props.seeState,
children = props.children,
onCancel = props.onCancel;
// 右键菜单的显示和位置
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
visible = _useState2[0],
changeVisible = _useState2[1];
var _useState3 = useState(position !== null && position !== void 0 ? position : [0, 0]),
_useState4 = _slicedToArray(_useState3, 2),
pos = _useState4[0],
setPos = _useState4[1];
var _useState5 = useState(),
_useState6 = _slicedToArray(_useState5, 2),
rightEvent = _useState6[0],
setRightEvent = _useState6[1];
var tempRef = useRef(null);
var originInfo = useRef({
xMin: 0,
xMax: 0,
yMin: 0,
yMax: 0
});
// 绑定右键事件到父元素
useEffect(function () {
if (!seeState) return;
// 通过ref拿到父元素的dom
var parentNode = tempRef.current;
// 父元素的位置信息
var parentPos = parentNode.getBoundingClientRect();
originInfo.current = {
xMin: parentPos.x,
// 盒子的左顶点到浏览器当前左窗口的距离
xMax: parentPos.x + parentPos.width,
yMin: parentPos.y,
// 盒子的左顶点到浏览器当前下窗口的距离
yMax: parentPos.y + parentPos.height
};
// 右键回调事件
var handleRightClick = function handleRightClick(e) {
e.preventDefault();
// 能显示菜单
changeVisible(true);
// 鼠标点击的位置为菜单左顶点位置
setPos([e.clientX, e.clientY]);
// 将右键时候的e存储起来
setRightEvent(e);
};
if (parentNode !== null) {
// 绑定右键点击事件
parentNode.addEventListener('contextmenu', handleRightClick);
}
// useEffect中的函数可以返回一个清除函数,这个清除函数会在组件被卸载或者在下一次执行该useEffect之前调用
return function () {
parentNode.removeEventListener('contextmenu', handleRightClick);
};
}, [seeState]); // 添加 seeState 作为依赖,在页面状态切换时能更新响应逻辑
function updatePos(newPos) {
setPos(newPos);
}
function showContextMenu(e) {
console.log('e', e);
e.preventDefault();
var _originInfo$current = originInfo.current,
xMin = _originInfo$current.xMin,
xMax = _originInfo$current.xMax,
yMin = _originInfo$current.yMin,
yMax = _originInfo$current.yMax;
// 鼠标点击位置在父元素区域范围内,更新pos
if (e.clientX >= xMin && e.clientX <= xMax && e.clientY >= yMin && e.clientY <= yMax) {
updatePos([e.clientX, e.clientY]);
}
}
// 无论是菜单项是禁用的还是可用的,都会触发的关闭右键菜单的操作
function handleMenuItemClick() {
changeVisible(false);
if (typeof onCancel === 'function') {
onCancel(false);
}
}
// 单击菜单里的某个item
function clickMenuItem(e, menuItem) {
e.stopPropagation();
// Item禁用时
if (menuItem.disable) return;
console.log('r', rightEvent);
// 传入的e是右键单击时的e
menuItem.onClick(rightEvent);
// 关闭菜单,执行onCancel
handleMenuItemClick();
}
// 渲染菜单里的Item,useMemo的作用是只有menuItems和onCancel变化时才重新计算
var menuItemRender = useMemo(function () {
return menuItems.map(function (menuItem) {
var _menuItem$icon;
return /*#__PURE__*/_jsxs("li", {
className: menuItem.disable ? 'disable-menu' : '',
onClick: function onClick(e) {
return clickMenuItem(e, menuItem);
}
// onMouseDown={(e) => {
// e.stopPropagation();
// }}
,
children: [/*#__PURE__*/_jsx("span", {
className: "icons",
children: (_menuItem$icon = menuItem.icon) !== null && _menuItem$icon !== void 0 ? _menuItem$icon : ''
}), /*#__PURE__*/_jsxs("span", {
children: ["\xA0\xA0", menuItem.label]
})]
}, menuItem.key);
});
}, [menuItems, onCancel, rightEvent]);
return /*#__PURE__*/_jsx("div", {
ref: tempRef
// onMouseDown={(e) => {
// e.stopPropagation();
// }}
,
children: /*#__PURE__*/_jsxs(_Fragment, {
children: [children, /*#__PURE__*/createPortal( /*#__PURE__*/_jsx("div", {
className: "right-menu-wrapper ".concat(visible ? 'right-menu-wrapper-show' : ''),
onClick: handleMenuItemClick,
onContextMenu: showContextMenu,
children: /*#__PURE__*/_jsx("div", {
className: "right-menu-container ".concat(className),
style: position ? {
top: position[1],
left: position[0] + 10
} : {
top: pos[1],
left: pos[0] + 10
},
children: /*#__PURE__*/_jsx("ul", {
children: menuItemRender
})
})
}), document.body)]
})
});
};
export default RightMenu;