@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
153 lines (152 loc) • 5.74 kB
JavaScript
import React__default, { forwardRef, useState, useEffect, useImperativeHandle, useMemo, useRef } from "react";
import classNames from "classnames";
import { CSSTransition } from "react-transition-group";
import { Check } from "@nutui/icons-react";
import { O as Overlay } from "./overlay2.js";
import { u as useClickAway } from "./use-click-away.js";
import { C as ComponentDefaults } from "./typings.js";
import { u as usePropsValue } from "./use-props-value.js";
import { g as getScrollParent } from "./get-scroll-parent.js";
const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { titleIcon: null, columns: 1, direction: "down", icon: null, closeOnClickAway: true, activeTitleClass: "", inactiveTitleClass: "", onChange: (value) => void 0 });
const MenuItem = forwardRef((props, ref) => {
const { className, style, options, value, defaultValue, columns, title, icon, direction, onChange, activeTitleClass, inactiveTitleClass, closeOnClickAway, children, activeColor, show, parent, index } = Object.assign(Object.assign({}, defaultProps), props);
const [showPopup, setShowPopup] = useState(show);
const [innerValue, setValue] = usePropsValue({
defaultValue,
value,
finalValue: void 0,
onChange: (v) => {
const [option] = options.filter((o) => o.value === v);
onChange === null || onChange === void 0 ? void 0 : onChange(option);
}
});
useEffect(() => {
setShowPopup(show);
}, [show]);
useEffect(() => {
getParentOffset();
}, [showPopup]);
useImperativeHandle(ref, () => ({
toggle: (s) => {
const from = "REF";
s ? parent.toggleMenuItem(index, from) : parent.hideMenuItem(index, from);
}
}));
const getIconCName = (optionVal, value2) => {
return classNames({
[activeTitleClass]: optionVal === value2,
[inactiveTitleClass]: optionVal !== value2
});
};
const setTitle = (text) => {
if (!title) {
parent.updateTitle(text, index);
}
};
const handleClick = (item) => {
parent.toggleMenuItem(index);
setTitle(item.text);
setValue(item.value);
};
const isShow = () => {
if (showPopup)
return {};
return { display: "none" };
};
const [position, setPosition] = useState({
top: 0,
height: 0
});
const scrollParent = useMemo(() => {
return getScrollParent(parent.menuRef, window);
}, [parent.menuRef]);
const getParentOffset = () => {
setTimeout(() => {
const p = parent.menuRef.current;
if (p) {
const rect = p.getBoundingClientRect();
setPosition({
height: rect.height,
top: rect.top
});
}
});
};
useEffect(() => {
if (!parent.lockScroll) {
scrollParent === null || scrollParent === void 0 ? void 0 : scrollParent.addEventListener("scroll", getParentOffset, false);
return () => {
scrollParent === null || scrollParent === void 0 ? void 0 : scrollParent.removeEventListener("scroll", getParentOffset, false);
};
}
}, []);
const getPosition = () => {
return direction === "down" ? {
top: `${position.top + position.height}px`,
bottom: "0",
height: "initial"
} : {
bottom: `${window.innerHeight - position.top}px`,
top: "auto",
height: "initial"
};
};
const micRef = useRef(null);
const cssRef = useRef(null);
const targetSet = [micRef.current];
useClickAway(
() => {
parent.hideMenuItem(index);
},
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
targetSet,
"click",
false,
showPopup,
closeOnClickAway
);
return React__default.createElement(
"div",
{ className: "nut-menu-container", ref: micRef },
parent.overlay ? React__default.createElement(Overlay, { className: "nut-menu-container-overlay", style: getPosition(), lockScroll: parent.lockScroll, visible: showPopup, closeOnOverlayClick: parent.closeOnOverlayClick, onClick: () => {
parent.closeOnOverlayClick && parent.hideMenuItem(index);
} }) : null,
React__default.createElement(
"div",
{ className: classNames({
"nut-menu-container-wrap": direction === "down",
"nut-menu-container-wrap-up": direction !== "down"
}, className), style: Object.assign(Object.assign({}, style), isShow()) },
React__default.createElement(
CSSTransition,
{ nodeRef: cssRef, in: showPopup, timeout: 100, classNames: direction === "down" ? "nut-menu-container-down" : "nut-menu-container-up" },
React__default.createElement(
"div",
{ className: "nut-menu-container-content" },
options === null || options === void 0 ? void 0 : options.map((item) => {
return React__default.createElement(
"div",
{ className: `nut-menu-container-item ${classNames({
active: item.value === innerValue
})}`, key: item.text, style: {
flexBasis: `${100 / columns}%`
}, onClick: () => {
handleClick(item);
} },
item.value === innerValue ? React__default.createElement("i", { className: "nut-menu-container-item-icon" }, icon || React__default.createElement(Check, { color: activeColor, className: getIconCName(item.value, value) })) : null,
React__default.createElement("div", { className: `nut-menu-container-item-title ${getIconCName(item.value, value)}`, style: {
color: `${item.value === innerValue ? activeColor : ""}`
} }, item.text)
);
}),
children
)
)
)
);
});
MenuItem.displayName = "NutMenuItem";
export {
MenuItem as M
};