UNPKG

@nutui/nutui-react-taro

Version:

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

230 lines (229 loc) 9.27 kB
import { _ as __rest, a as __awaiter } from "./tslib.es6-iWu3F_1J.js"; import React__default, { useRef, useState, useEffect } from "react"; import classNames from "classnames"; import Taro, { createSelectorQuery } from "@tarojs/taro"; import { P as Popup } from "./popup.taro-JynjcLCn.js"; import { a as getRect, g as getRectByTaro } from "./get-rect-by-taro-D0h6aiDr.js"; import { C as ComponentDefaults } from "./typings-DV9RBfhj.js"; import { a as useRtl } from "./configprovider.taro-DpK4IiCE.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { list: [], theme: "light", location: "bottom", visible: false, offset: [0, 12], arrowOffset: 0, targetId: "", className: "", showArrow: true, closeOnOutsideClick: true, closeOnActionClick: true, overlay: false, onClick: () => { }, onOpen: () => { }, onClose: () => { } }); const classPrefix = `nut-popover`; const Popover = (props) => { const rtl = useRtl(); const _a = Object.assign(Object.assign({}, defaultProps), props), { children, list, theme, location, visible, offset, arrowOffset, targetId, overlay, closeOnOutsideClick, closeOnActionClick, className, showArrow, style, onClick, onOpen, onClose, onSelect } = _a, rest = __rest(_a, ["children", "list", "theme", "location", "visible", "offset", "arrowOffset", "targetId", "overlay", "closeOnOutsideClick", "closeOnActionClick", "className", "showArrow", "style", "onClick", "onOpen", "onClose", "onSelect"]); const popoverRef = useRef(null); const popoverContentRef = useRef(null); const [showPopup, setShowPopup] = useState(false); const [elWidth, setElWidth] = useState(0); const [elHeight, setElHeight] = useState(0); const [rootPosition, setRootPosition] = useState(); useEffect(() => { setShowPopup(visible); if (visible) { setTimeout(() => { getContentWidth(); }, 0); } }, [visible]); const getContentWidth = () => __awaiter(void 0, void 0, void 0, function* () { let rect; createSelectorQuery().selectViewport().scrollOffset((res) => __awaiter(void 0, void 0, void 0, function* () { const distance = res.scrollTop; if (targetId) { if (Taro.getEnv() === Taro.ENV_TYPE.WEB) { rect = getRect(document.querySelector(`#${targetId}`)); } else { rect = yield getRectTaro(targetId); } } else { rect = yield getRectByTaro(popoverRef.current); } setRootPosition({ width: rect.width, height: rect.height, left: rtl ? rect.right : rect.left, top: rect.top + distance, right: rtl ? rect.left : rect.right }); })).exec(); setTimeout(() => { getPopoverContentW(); }, 300); }); const getRectTaro = (targetId2) => __awaiter(void 0, void 0, void 0, function* () { return new Promise((resolve) => { const query = createSelectorQuery(); query.select(`#${targetId2}`) && query.select(`#${targetId2}`).boundingClientRect(); query.exec((res) => { resolve(res[0]); }); }); }); const getPopoverContentW = () => __awaiter(void 0, void 0, void 0, function* () { const rectContent = yield getRectByTaro(popoverContentRef.current); setElWidth(rectContent.width); setElHeight(rectContent.height); }); const clickAway = () => { if (closeOnOutsideClick) { onClick && onClick(); onClose && onClose(); } }; const classes = classNames({ [`${classPrefix}`]: true, [`${classPrefix}-${theme}`]: theme === "dark" }, className); const popoverArrow = () => { const prefixCls = "nut-popover-arrow"; const loca = location; const direction = loca.split("-")[0]; return `${prefixCls} ${prefixCls}-${direction} ${prefixCls}-${loca}`; }; const getRootPosition = () => { const styles = {}; if (!rootPosition) { styles.visibility = "hidden"; return styles; } const contentWidth = elWidth; const contentHeight = elHeight; const { width, height, left, top, right } = rootPosition; const direction = location.split("-")[0]; const skew = location.split("-")[1]; let cross = 0; let parallel = 0; if (Array.isArray(offset) && offset.length === 2) { const rtloffset = rtl ? -offset[0] : offset[0]; cross += +offset[1]; parallel += +rtloffset; } if (width) { const dir = rtl ? "right" : "left"; if (["bottom", "top"].includes(direction)) { const h = direction === "bottom" ? height + cross : -(contentHeight + cross); styles.top = `${top + h}px`; if (!skew) { styles[dir] = `${-(contentWidth - width) / 2 + rootPosition[dir] + parallel}px`; } if (skew === "start") { styles.left = `${left + parallel}px`; } if (skew === "end") { styles.left = `${right + parallel}px`; } } if (["left", "right"].includes(direction)) { const contentW = direction === "left" ? -(contentWidth + cross) : width + cross; styles.left = `${left + contentW}px`; if (!skew) { styles.top = `${top - contentHeight / 2 + height / 2 - 4 + parallel}px`; } if (skew === "start") { styles.top = `${top + parallel}px`; } if (skew === "end") { styles.top = `${top + height + parallel}px`; } } } if (elWidth === 0) { styles.visibility = "hidden"; } else { styles.visibility = "initial"; } return styles; }; const popoverArrowStyle = () => { const styles = {}; const direction = location.split("-")[0]; const skew = location.split("-")[1]; const base = 16; if (arrowOffset !== 0) { const dir = rtl ? "right" : "left"; const dir2 = rtl ? "left" : "right"; if (["bottom", "top"].includes(direction)) { if (!skew) { styles[dir] = `calc(50% + ${arrowOffset}px)`; } if (skew === "start") { styles[dir] = `${base + arrowOffset}px`; } if (skew === "end") { styles[dir2] = `${base - arrowOffset}px`; } } if (["left", "right"].includes(direction)) { if (!skew) { styles.top = `calc(50% - ${arrowOffset}px)`; } if (skew === "start") { styles.top = `${base - arrowOffset}px`; } if (skew === "end") { styles.bottom = `${base + arrowOffset}px`; } } } return styles; }; const handleSelect = (item, index) => { if (!item.disabled) { onSelect === null || onSelect === void 0 ? void 0 : onSelect(item, index); } if (closeOnActionClick) { onClick === null || onClick === void 0 ? void 0 : onClick(); onClose === null || onClose === void 0 ? void 0 : onClose(); } }; return React__default.createElement( React__default.Fragment, null, !targetId && React__default.createElement("div", { className: "nut-popover-wrapper", ref: popoverRef, onClick: () => { var _a2; (_a2 = props === null || props === void 0 ? void 0 : props.onClick) === null || _a2 === void 0 ? void 0 : _a2.call(props); if (!visible) { onOpen === null || onOpen === void 0 ? void 0 : onOpen(); } else { onClose === null || onClose === void 0 ? void 0 : onClose(); } }, style }, Array.isArray(children) ? children[0] : children), React__default.createElement( "div", { className: classes, style: getRootPosition() }, React__default.createElement( Popup, Object.assign({ className: `nut-popover-content nut-popover-content-${location}`, position: "default", overlay, visible: showPopup }, rest), React__default.createElement( "div", { className: "nut-popover-content-group", ref: popoverContentRef }, showArrow && React__default.createElement("div", { className: popoverArrow(), style: popoverArrowStyle() }), Array.isArray(children) ? children[1] : "", list.map((item, index) => { return React__default.createElement( "div", { className: classNames({ "nut-popover-menu-item": true, "nut-popover-menu-disabled": item.disabled }, item.className), key: item.key || index, onClick: () => handleSelect(item, index) }, item.icon ? React__default.createElement("div", { className: "nut-popover-menu-item-icon" }, item.icon) : null, React__default.createElement("div", { className: "nut-popover-menu-item-name" }, item.name), item.action && item.action.icon ? React__default.createElement("div", { className: "nut-popover-menu-item-action-icon", onClick: (e) => { var _a2, _b; return (_b = (_a2 = item.action) === null || _a2 === void 0 ? void 0 : _a2.onClick) === null || _b === void 0 ? void 0 : _b.call(_a2, e); } }, item.action.icon) : null ); }) ) ), showPopup && closeOnOutsideClick && React__default.createElement("div", { className: "nut-popover-content-bg", onClick: clickAway, onTouchMove: clickAway }) ) ); }; Popover.displayName = "NutPopover"; export { Popover as P };