@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
139 lines (138 loc) • 6.23 kB
JavaScript
import { _ as __rest } from "./tslib.es6.js";
import React__default, { useState, useEffect } from "react";
import { Close } from "@nutui/icons-react";
import classNames from "classnames";
import Popover__default from "./Popover.js";
import { g as getRect } from "./use-client-rect.js";
import { C as ComponentDefaults } from "./typings.js";
import { useConfig } from "./ConfigProvider.js";
const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { visible: false, type: "step", location: "bottom", mask: true, maskWidth: "", maskHeight: "", offset: [8, 10], title: "", next: "", prev: "", complete: "", showPrev: true, closeOnOverlayClick: true });
const classPrefix = "nut-tour";
const Tour = (props) => {
const { locale } = useConfig();
const _a = Object.assign(Object.assign({}, defaultProps), props), { children, className, title, closeOnOverlayClick, showPrev, list, type, location, visible, mask, maskWidth, maskHeight, offset, next, prev, complete, onClose, onChange } = _a, rest = __rest(_a, ["children", "className", "title", "closeOnOverlayClick", "showPrev", "list", "type", "location", "visible", "mask", "maskWidth", "maskHeight", "offset", "next", "prev", "complete", "onClose", "onChange"]);
const [showTour, setShowTour] = useState(false);
const [showPopup, setShowPopup] = useState(false);
const [active, setActive] = useState(0);
const [maskRect, setMaskRect] = useState({
top: 0,
left: 0,
right: 0,
bottom: 0,
width: 0,
height: 0
});
const classes = classNames(classPrefix, className);
useEffect(() => {
if (visible) {
getRootPosition();
}
setActive(0);
setShowTour(visible);
setShowPopup(visible);
}, [visible]);
useEffect(() => {
if (visible) {
setShowPopup(true);
getRootPosition();
}
}, [active]);
const getRootPosition = () => {
const el = document.querySelector(`#${list[active].target}`);
const rect = getRect(el);
setMaskRect(rect);
};
const maskStyle = () => {
const { width, height, left, top } = maskRect;
const center = [left + width / 2, top + height / 2];
const w = Number(maskWidth || width);
const h = Number(maskHeight || height);
const styles = {
width: `${w + +offset[1] * 2}px`,
height: `${h + +offset[0] * 2}px`,
top: `${center[1] - h / 2 - +offset[0]}px`,
left: `${center[0] - w / 2 - +offset[1]}px`
};
return styles;
};
const maskClose = (e) => {
setShowTour(false);
setShowPopup(false);
onClose && onClose(e);
};
const handleClickMask = (e) => {
closeOnOverlayClick && maskClose(e);
};
const changeStep = (type2) => {
if (type2 === "next") {
setActive(active + 1);
onChange && onChange(active + 1);
} else {
setActive(active - 1);
onChange && onChange(active - 1);
}
setShowPopup(false);
};
return React__default.createElement(
"div",
Object.assign({ className: classes }, rest),
React__default.createElement("div", { className: "nut-tour-masked", style: { display: showTour ? "block" : "none" }, onClick: handleClickMask }),
list.map((item, index) => {
return React__default.createElement("div", { key: index, style: { height: 0 } }, index === active && React__default.createElement(
React__default.Fragment,
null,
showTour && React__default.createElement("div", { className: `${mask ? "nut-tour-mask" : "nut-tour-mask nut-tour-mask-none"}`, id: "nut-tour-popid", style: maskStyle() }),
React__default.createElement(
Popover__default,
{ visible: showPopup, location: item.location || location, targetId: "nut-tour-popid", closeOnOutsideClick: false, offset: item.popoverOffset || [0, 12], arrowOffset: item.arrowOffset || 0 },
React__default.createElement(React__default.Fragment, null),
React__default.createElement(React__default.Fragment, null, children || React__default.createElement(
React__default.Fragment,
null,
type === "step" && React__default.createElement(
"div",
{ className: "nut-tour-content" },
title && React__default.createElement(
"div",
{ className: "nut-tour-content-top" },
React__default.createElement(
"div",
{ onClick: (e) => maskClose(e) },
React__default.createElement(Close, { className: "nut-tour-content-top-close" })
)
),
React__default.createElement("div", { className: "nut-tour-content-inner" }, item.content),
React__default.createElement(
"div",
{ className: "nut-tour-content-bottom" },
React__default.createElement(
"div",
{ className: "nut-tour-content-bottom-init" },
active + 1,
"/",
list.length
),
React__default.createElement(
"div",
{ className: "nut-tour-content-bottom-operate" },
active !== 0 && showPrev && React__default.createElement("div", { className: "nut-tour-content-bottom-operate-btn", onClick: () => changeStep("prev") }, prev || locale.tour.prevStepText),
list.length - 1 === active && React__default.createElement("div", { className: "nut-tour-content-bottom-operate-btn active", onClick: (e) => maskClose(e) }, complete || locale.tour.completeText),
list.length - 1 !== active && React__default.createElement("div", { className: "nut-tour-content-bottom-operate-btn active", onClick: () => changeStep("next") }, next || locale.tour.nextStepText)
)
)
),
type === "tile" && React__default.createElement(
"div",
{ className: "nut-tour-content nut-tour-content-tile" },
React__default.createElement("div", { className: "nut-tour-content-inner" }, item.content)
)
))
)
));
})
);
};
Tour.displayName = "NutTour";
export {
Tour as default
};