UNPKG

@nutui/nutui-react

Version:

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

139 lines (138 loc) 6.23 kB
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 };