feat: CP support Tour closeIcon (#47200)

* feat: CP support Tour closeIcon

* fix: fix
This commit is contained in:
lijianan 2024-01-29 11:01:30 +08:00 committed by GitHub
parent 95c3e100b5
commit 095b846cad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 36 additions and 17 deletions

View File

@ -50,6 +50,7 @@ import Tabs from '../../tabs';
import Tag from '../../tag'; import Tag from '../../tag';
import TimePicker from '../../time-picker'; import TimePicker from '../../time-picker';
import Timeline from '../../timeline'; import Timeline from '../../timeline';
import Tour from '../../tour';
import Transfer from '../../transfer'; import Transfer from '../../transfer';
import Tree from '../../tree'; import Tree from '../../tree';
import Typography from '../../typography'; import Typography from '../../typography';
@ -1327,4 +1328,17 @@ describe('ConfigProvider support style and className props', () => {
expect(element).toHaveClass('cp-dropdown'); expect(element).toHaveClass('cp-dropdown');
expect(element).toHaveStyle({ backgroundColor: 'red' }); expect(element).toHaveStyle({ backgroundColor: 'red' });
}); });
it('Should Tour closeIcon works', () => {
const { container } = render(
<ConfigProvider
tour={{ closeIcon: <span className="cp-test-closeIcon">cp-test-closeIcon</span> }}
>
<Tour steps={[{ title: 'test' }]} open />
</ConfigProvider>,
);
const selectors = '.ant-tour .ant-tour-inner .ant-tour-close .cp-test-closeIcon';
const element = container.querySelector<HTMLSpanElement>(selectors);
expect(element).toBeTruthy();
});
}); });

View File

@ -15,6 +15,7 @@ import type { SelectProps } from '../select';
import type { SpaceProps } from '../space'; import type { SpaceProps } from '../space';
import type { TabsProps } from '../tabs'; import type { TabsProps } from '../tabs';
import type { AliasToken, MappingAlgorithm, OverrideToken } from '../theme/interface'; import type { AliasToken, MappingAlgorithm, OverrideToken } from '../theme/interface';
import type { TourProps } from '../tour/interface';
import type { RenderEmptyHandler } from './defaultRenderEmpty'; import type { RenderEmptyHandler } from './defaultRenderEmpty';
export const defaultIconPrefixCls = 'anticon'; export const defaultIconPrefixCls = 'anticon';
@ -65,6 +66,8 @@ export interface ComponentStyleConfig {
style?: React.CSSProperties; style?: React.CSSProperties;
} }
export type TourConfig = Pick<TourProps, 'closeIcon'>;
export type ModalConfig = ComponentStyleConfig & Pick<ModalProps, 'classNames' | 'styles'>; export type ModalConfig = ComponentStyleConfig & Pick<ModalProps, 'classNames' | 'styles'>;
export type BadgeConfig = ComponentStyleConfig & Pick<BadgeProps, 'classNames' | 'styles'>; export type BadgeConfig = ComponentStyleConfig & Pick<BadgeProps, 'classNames' | 'styles'>;
@ -145,6 +148,7 @@ export interface ConfigConsumerProps {
tabs?: ComponentStyleConfig & Pick<TabsProps, 'indicator' | 'indicatorSize'>; tabs?: ComponentStyleConfig & Pick<TabsProps, 'indicator' | 'indicatorSize'>;
timeline?: ComponentStyleConfig; timeline?: ComponentStyleConfig;
timePicker?: ComponentStyleConfig; timePicker?: ComponentStyleConfig;
tour?: TourConfig;
upload?: ComponentStyleConfig; upload?: ComponentStyleConfig;
notification?: ComponentStyleConfig; notification?: ComponentStyleConfig;
tree?: ComponentStyleConfig; tree?: ComponentStyleConfig;

View File

@ -151,6 +151,7 @@ const {
| tag | Set Tag common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | tag | Set Tag common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| timeline | Set Timeline common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | timeline | Set Timeline common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| timePicker | Set TimePicker common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | timePicker | Set TimePicker common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| tour | Set Tour common props | { closeIcon?: React.ReactNode } | - | 5.14.0 |
| transfer | Set Transfer common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | transfer | Set Transfer common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| tree | Set Tree common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | tree | Set Tree common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| typography | Set Typography common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | typography | Set Typography common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |

View File

@ -33,6 +33,7 @@ import type {
PopupOverflow, PopupOverflow,
Theme, Theme,
ThemeConfig, ThemeConfig,
TourConfig,
WaveConfig, WaveConfig,
} from './context'; } from './context';
import { ConfigConsumer, ConfigContext, defaultIconPrefixCls } from './context'; import { ConfigConsumer, ConfigContext, defaultIconPrefixCls } from './context';
@ -181,6 +182,7 @@ export interface ConfigProviderProps {
* Wave is special component which only patch on the effect of component interaction. * Wave is special component which only patch on the effect of component interaction.
*/ */
wave?: WaveConfig; wave?: WaveConfig;
tour?: TourConfig;
} }
interface ProviderChildrenProps extends ConfigProviderProps { interface ProviderChildrenProps extends ConfigProviderProps {
@ -191,6 +193,7 @@ interface ProviderChildrenProps extends ConfigProviderProps {
type holderRenderType = (children: React.ReactNode) => React.ReactNode; type holderRenderType = (children: React.ReactNode) => React.ReactNode;
export const defaultPrefixCls = 'ant'; export const defaultPrefixCls = 'ant';
let globalPrefixCls: string; let globalPrefixCls: string;
let globalIconPrefixCls: string; let globalIconPrefixCls: string;
let globalTheme: ThemeConfig; let globalTheme: ThemeConfig;
@ -333,6 +336,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
wave, wave,
dropdown, dropdown,
warning: warningConfig, warning: warningConfig,
tour,
} = props; } = props;
// =================================== Context =================================== // =================================== Context ===================================
@ -426,6 +430,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
wave, wave,
dropdown, dropdown,
warning: warningConfig, warning: warningConfig,
tour,
}; };
const config: ConfigConsumerProps = { const config: ConfigConsumerProps = {

View File

@ -153,6 +153,7 @@ const {
| tag | 设置 Tag 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | tag | 设置 Tag 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| timeline | 设置 Timeline 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | timeline | 设置 Timeline 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| timePicker | 设置 TimePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | timePicker | 设置 TimePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| tour | 设置 Tour 组件的通用属性 | { closeIcon?: React.ReactNode } | - | 5.14.0 |
| transfer | 设置 Transfer 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | transfer | 设置 Transfer 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| tree | 设置 Tree 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | tree | 设置 Tree 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| typography | 设置 Typography 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 | | typography | 设置 Typography 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |

View File

@ -33,15 +33,12 @@ const App: React.FC = () => {
target: () => ref3.current, target: () => ref3.current,
}, },
]; ];
return ( return (
<> <>
<Button type="primary" onClick={() => setOpen(true)}> <Button type="primary" onClick={() => setOpen(true)}>
Begin Tour Begin Tour
</Button> </Button>
<Divider /> <Divider />
<Space> <Space>
<Button ref={ref1}> Upload</Button> <Button ref={ref1}> Upload</Button>
<Button ref={ref2} type="primary"> <Button ref={ref2} type="primary">
@ -49,7 +46,6 @@ const App: React.FC = () => {
</Button> </Button>
<Button ref={ref3} icon={<EllipsisOutlined />} /> <Button ref={ref3} icon={<EllipsisOutlined />} />
</Space> </Space>
<Tour open={open} onClose={() => setOpen(false)} steps={steps} /> <Tour open={open} onClose={() => setOpen(false)} steps={steps} />
</> </>
); );

View File

@ -1,4 +1,4 @@
import React, { useContext, useMemo } from 'react'; import React, { useContext } from 'react';
import RCTour from '@rc-component/tour'; import RCTour from '@rc-component/tour';
import classNames from 'classnames'; import classNames from 'classnames';
@ -24,12 +24,12 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
steps, steps,
...restProps ...restProps
} = props; } = props;
const { getPrefixCls, direction } = useContext<ConfigConsumerProps>(ConfigContext); const { getPrefixCls, direction, tour } = useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('tour', customizePrefixCls); const prefixCls = getPrefixCls('tour', customizePrefixCls);
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls); const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
const [, token] = useToken(); const [, token] = useToken();
const mergedSteps = useMemo( const mergedSteps = React.useMemo<TourProps['steps']>(
() => () =>
steps?.map((step) => ({ steps?.map((step) => ({
...step, ...step,
@ -63,6 +63,7 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
type={type} type={type}
stepProps={stepProps} stepProps={stepProps}
current={stepCurrent} current={stepCurrent}
closeIcon={tour?.closeIcon}
indicatorsRender={indicatorsRender} indicatorsRender={indicatorsRender}
/> />
); );

View File

@ -1,13 +1,14 @@
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import classNames from 'classnames';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import React from 'react'; import React from 'react';
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import classNames from 'classnames';
import useClosable from '../_util/hooks/useClosable';
import type { ButtonProps } from '../button'; import type { ButtonProps } from '../button';
import Button from '../button'; import Button from '../button';
import { useLocale } from '../locale'; import { useLocale } from '../locale';
import defaultLocale from '../locale/en_US'; import defaultLocale from '../locale/en_US';
import type { TourStepProps } from './interface'; import type { TourStepProps } from './interface';
import useClosable from '../_util/hooks/useClosable';
function isValidNode(node: ReactNode): boolean { function isValidNode(node: ReactNode): boolean {
return node !== undefined && node !== null; return node !== undefined && node !== null;
@ -23,13 +24,8 @@ interface TourPanelProps {
// Due to the independent design of Panel, it will be too coupled to put in rc-tour, // 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. // so a set of Panel logic is implemented separately in antd.
const TourPanel: React.FC<TourPanelProps> = ({ const TourPanel: React.FC<TourPanelProps> = (props) => {
stepProps, const { stepProps, current, type, closeIcon, indicatorsRender } = props;
current,
type,
indicatorsRender,
closeIcon,
}) => {
const { const {
prefixCls, prefixCls,
total = 1, total = 1,
@ -49,6 +45,7 @@ const TourPanel: React.FC<TourPanelProps> = ({
const mergedType = stepType ?? type; const mergedType = stepType ?? type;
const mergedCloseIcon = stepCloseIcon ?? closeIcon; const mergedCloseIcon = stepCloseIcon ?? closeIcon;
const mergedClosable = mergedCloseIcon !== false && mergedCloseIcon !== null; const mergedClosable = mergedCloseIcon !== false && mergedCloseIcon !== null;
const [closable, mergedDisplayCloseIcon] = useClosable( const [closable, mergedDisplayCloseIcon] = useClosable(