UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

153 lines (152 loc) 5.74 kB
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 };