@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
230 lines (229 loc) • 9.27 kB
JavaScript
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
};