mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 17:44:35 +08:00
fix: Tour step.type
should work (#45086)
* fix: Tour step.type should work * chore: code clean * chore: update memo deps * chore: code clean
This commit is contained in:
parent
ef7c500a8e
commit
29be72bc38
@ -84,7 +84,7 @@ exports[`Tour Primary 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tour-mask ant-tour-primary"
|
||||
class="ant-tour-mask"
|
||||
style="position: fixed; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 1001; pointer-events: none;"
|
||||
>
|
||||
<svg
|
||||
@ -157,7 +157,7 @@ exports[`Tour Primary 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tour-primary ant-tour-target-placeholder"
|
||||
class="ant-tour-target-placeholder"
|
||||
style="left: -6px; top: -6px; width: 12px; height: 12px; position: fixed; pointer-events: none;"
|
||||
/>
|
||||
</div>
|
||||
@ -307,7 +307,7 @@ exports[`Tour controlled current 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tour-mask ant-tour-primary"
|
||||
class="ant-tour-mask"
|
||||
style="position: fixed; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 1001; pointer-events: none;"
|
||||
>
|
||||
<svg
|
||||
@ -339,7 +339,7 @@ exports[`Tour controlled current 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tour-primary ant-tour-target-placeholder"
|
||||
class="ant-tour-target-placeholder"
|
||||
style="left: 50%; top: 50%; width: 1px; height: 1px; position: fixed; pointer-events: none;"
|
||||
/>
|
||||
</div>
|
||||
@ -696,7 +696,7 @@ exports[`Tour step support Primary 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tour-mask ant-tour-primary"
|
||||
class="ant-tour-mask"
|
||||
style="position: fixed; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 1001; pointer-events: none;"
|
||||
>
|
||||
<svg
|
||||
@ -769,7 +769,7 @@ exports[`Tour step support Primary 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tour-primary ant-tour-target-placeholder"
|
||||
class="ant-tour-target-placeholder"
|
||||
style="left: -6px; top: -6px; width: 12px; height: 12px; position: fixed; pointer-events: none;"
|
||||
/>
|
||||
</div>
|
||||
|
@ -529,4 +529,38 @@ describe('Tour', () => {
|
||||
|
||||
resetIndex();
|
||||
});
|
||||
|
||||
it('first step should be primary', () => {
|
||||
const App: React.FC = () => {
|
||||
const coverBtnRef = useRef<HTMLButtonElement>(null);
|
||||
return (
|
||||
<>
|
||||
<button ref={coverBtnRef} type="button">
|
||||
target
|
||||
</button>
|
||||
|
||||
<Tour
|
||||
steps={[
|
||||
{
|
||||
title: '',
|
||||
description: '',
|
||||
target: () => coverBtnRef.current!,
|
||||
type: 'primary',
|
||||
className: 'should-be-primary',
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
target: () => coverBtnRef.current!,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
render(<App />);
|
||||
fireEvent.click(screen.getByRole('button', { name: 'target' }));
|
||||
expect(document.querySelector('.should-be-primary')).toBeTruthy();
|
||||
expect(document.querySelector('.should-be-primary')).toHaveClass('ant-tour-primary');
|
||||
});
|
||||
});
|
||||
|
@ -1,60 +0,0 @@
|
||||
import { act, renderHook } from '../../../tests/utils';
|
||||
import useMergedType from '../useMergedType';
|
||||
|
||||
describe('useMergedType', () => {
|
||||
it('returns the merged type', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMergedType({
|
||||
defaultType: 'default',
|
||||
steps: [{ type: 'primary', title: 'Step 1' }],
|
||||
current: 0,
|
||||
}),
|
||||
);
|
||||
expect(result.current?.currentMergedType).toBe('primary');
|
||||
});
|
||||
|
||||
it('returns the default type', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMergedType({
|
||||
defaultType: 'default',
|
||||
steps: [],
|
||||
current: 0,
|
||||
}),
|
||||
);
|
||||
expect(result.current?.currentMergedType).toBe('default');
|
||||
});
|
||||
|
||||
it('returns the default type when index is invalid', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMergedType({
|
||||
defaultType: 'default',
|
||||
steps: [],
|
||||
current: 0,
|
||||
}),
|
||||
);
|
||||
expect(result.current?.currentMergedType).toBe('default');
|
||||
});
|
||||
|
||||
it('returns the default type when list is null', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMergedType({
|
||||
defaultType: 'default',
|
||||
}),
|
||||
);
|
||||
expect(result.current?.currentMergedType).toBe('default');
|
||||
});
|
||||
|
||||
it('returns type of new step after onChange from rc-tour', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMergedType({
|
||||
defaultType: 'default',
|
||||
steps: [{ title: 'Step 1' }, { type: 'primary', title: 'Step 1' }],
|
||||
}),
|
||||
);
|
||||
act(() => {
|
||||
result.current?.updateInnerCurrent?.(1);
|
||||
});
|
||||
|
||||
expect(result.current?.currentMergedType).toBe('primary');
|
||||
});
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import React, { useContext } from 'react';
|
||||
import React, { useContext, useMemo } from 'react';
|
||||
import RCTour from '@rc-component/tour';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@ -10,15 +10,12 @@ import type { TourProps, TourStepProps } from './interface';
|
||||
import TourPanel from './panelRender';
|
||||
import PurePanel from './PurePanel';
|
||||
import useStyle from './style';
|
||||
import useMergedType from './useMergedType';
|
||||
|
||||
const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: typeof PurePanel } = (
|
||||
props,
|
||||
) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
current,
|
||||
defaultCurrent,
|
||||
type,
|
||||
rootClassName,
|
||||
indicatorsRender,
|
||||
@ -30,12 +27,16 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const [, token] = useToken();
|
||||
|
||||
const { currentMergedType, updateInnerCurrent } = useMergedType({
|
||||
defaultType: type,
|
||||
steps,
|
||||
current,
|
||||
defaultCurrent,
|
||||
});
|
||||
const mergedSteps = useMemo(
|
||||
() =>
|
||||
steps?.map((step) => ({
|
||||
...step,
|
||||
className: classNames(step.className, {
|
||||
[`${prefixCls}-primary`]: (step.type ?? type) === 'primary',
|
||||
}),
|
||||
})),
|
||||
[steps, type],
|
||||
);
|
||||
|
||||
const builtinPlacements = getPlacements({
|
||||
arrowPointAtCenter: true,
|
||||
@ -47,7 +48,6 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
|
||||
|
||||
const customClassName = classNames(
|
||||
{
|
||||
[`${prefixCls}-primary`]: currentMergedType === 'primary',
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
hashId,
|
||||
@ -63,23 +63,15 @@ const Tour: React.FC<TourProps> & { _InternalPanelDoNotUseOrYouWillBeFired: type
|
||||
/>
|
||||
);
|
||||
|
||||
const onStepChange = (stepCurrent: number) => {
|
||||
updateInnerCurrent(stepCurrent);
|
||||
props.onChange?.(stepCurrent);
|
||||
};
|
||||
|
||||
return wrapSSR(
|
||||
<RCTour
|
||||
{...restProps}
|
||||
rootClassName={customClassName}
|
||||
prefixCls={prefixCls}
|
||||
current={current}
|
||||
defaultCurrent={defaultCurrent}
|
||||
animated
|
||||
renderPanel={mergedRenderPanel}
|
||||
builtinPlacements={builtinPlacements}
|
||||
onChange={onStepChange}
|
||||
steps={steps}
|
||||
steps={mergedSteps}
|
||||
/>,
|
||||
);
|
||||
};
|
||||
|
@ -43,7 +43,6 @@ const TourPanel: React.FC<TourPanelProps> = ({
|
||||
nextButtonProps,
|
||||
prevButtonProps,
|
||||
type: stepType,
|
||||
className,
|
||||
closeIcon: stepCloseIcon,
|
||||
} = stepProps;
|
||||
|
||||
@ -120,7 +119,7 @@ const TourPanel: React.FC<TourPanelProps> = ({
|
||||
const [contextLocale] = useLocale('Tour', defaultLocale.Tour);
|
||||
|
||||
return (
|
||||
<div className={classNames(className, `${prefixCls}-content`)}>
|
||||
<div className={`${prefixCls}-content`}>
|
||||
<div className={`${prefixCls}-inner`}>
|
||||
{closable && mergedDisplayCloseIcon}
|
||||
{coverNode}
|
||||
|
@ -1,31 +0,0 @@
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import type { TourProps } from './interface';
|
||||
|
||||
interface Props {
|
||||
defaultType?: string;
|
||||
steps?: TourProps['steps'];
|
||||
current?: number;
|
||||
defaultCurrent?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the merged type of a step or the default type.
|
||||
*/
|
||||
const useMergedType = ({ defaultType, steps = [], current, defaultCurrent }: Props) => {
|
||||
const [innerCurrent, updateInnerCurrent] = useMergedState<number | undefined>(defaultCurrent, {
|
||||
value: current,
|
||||
});
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (current === undefined) return;
|
||||
updateInnerCurrent(current);
|
||||
}, [current]);
|
||||
|
||||
const innerType = typeof innerCurrent === 'number' ? steps[innerCurrent]?.type : defaultType;
|
||||
const currentMergedType = innerType ?? defaultType;
|
||||
|
||||
return { currentMergedType, updateInnerCurrent };
|
||||
};
|
||||
|
||||
export default useMergedType;
|
Loading…
Reference in New Issue
Block a user