import CloseOutlined from '@ant-design/icons/CloseOutlined'; import classNames from 'classnames'; import type { ReactNode } from 'react'; import React from 'react'; import type { ButtonProps } from '../button'; import Button from '../button'; import { useLocale } from '../locale'; import defaultLocale from '../locale/en_US'; import type { TourStepProps } from './interface'; import useClosable from '../_util/hooks/useClosable'; function isValidNode(node: ReactNode): boolean { return node !== undefined && node !== null; } interface TourPanelProps { stepProps: TourStepProps; current: number; type: TourStepProps['type']; indicatorsRender?: TourStepProps['indicatorsRender']; closeIcon?: ReactNode; } // Due to the independent design of Panel, it will be too coupled to put in rc-tour, // so a set of Panel logic is implemented separately in antd. const TourPanel: React.FC = ({ stepProps, current, type, indicatorsRender, closeIcon, }) => { const { prefixCls, total = 1, title, onClose, onPrev, onNext, onFinish, cover, description, nextButtonProps, prevButtonProps, type: stepType, closeIcon: stepCloseIcon, } = stepProps; const mergedType = stepType ?? type; const mergedCloseIcon = stepCloseIcon ?? closeIcon; const mergedClosable = mergedCloseIcon !== false && mergedCloseIcon !== null; const [closable, mergedDisplayCloseIcon] = useClosable( mergedClosable, mergedCloseIcon, (icon) => ( {icon} ), , true, ); const isLastStep = current === total - 1; const prevBtnClick = () => { onPrev?.(); prevButtonProps?.onClick?.(); }; const nextBtnClick = () => { if (isLastStep) { onFinish?.(); } else { onNext?.(); } nextButtonProps?.onClick?.(); }; const headerNode = isValidNode(title) ? (
{title}
) : null; const descriptionNode = isValidNode(description) ? (
{description}
) : null; const coverNode = isValidNode(cover) ?
{cover}
: null; let mergeIndicatorNode: ReactNode; if (indicatorsRender) { mergeIndicatorNode = indicatorsRender(current, total); } else { mergeIndicatorNode = [...Array.from({ length: total }).keys()].map( (stepItem, index) => ( ), ); } const mainBtnType = mergedType === 'primary' ? 'default' : 'primary'; const secondaryBtnProps: ButtonProps = { type: 'default', ghost: mergedType === 'primary', }; const [contextLocale] = useLocale('Tour', defaultLocale.Tour); return (
{closable && mergedDisplayCloseIcon} {coverNode} {headerNode} {descriptionNode}
{total > 1 &&
{mergeIndicatorNode}
}
{current !== 0 ? ( ) : null}
); }; export default TourPanel;