Browse Source
* refactor: refactor closeIcon * docs: update docs * refactor(Drawer): refactor drawer closeIcon (#42993) * feat: optimize closeIcon * refactor: refactor closeIcon * docs: update docs * feat: optimize code * feat: update test case * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * docs: update docs * ✨ feat: migrate less to token for Slider (#42428) * ✨ feat: migrate less to token for Slider * ✨ feat: update snap * ✨ feat: update style * ✨ feat: update style * ✨ feat: test ci * ✨ feat: test ci * ✨ feat: test ci * ✨ feat: test ci * ✨ feat: update * ✨ feat: update snap * ✨ feat: update * ✨ feat: update * ✨ feat: 删除未使用token * ✨ feat: update doc * ✨ feat: update dome * ✨ feat: update * ✨ feat: test ci * 📝 doc: update doc * ✨ feat: update * ✨ feat: update * ✨ feat: update * ✨ feat: update * ✨ feat: add demo * ✨ feat: add demo * ✨ feat: update for reviewer * ✨ feat: update for reviewer * ✨ feat: update for reviewer * ✨ feat: update for reviewer * ✨ feat: update for reviewer * ✨ feat: update for reviewer * ✨ feat: update for reviewer * ✨ feat: update for reviewer * Apply suggestions from code review --------- Co-authored-by: MadCcc <1075746765@qq.com> * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * feat: optimize code * docs: update docs --------- Co-authored-by: 黑雨 <wangning4567@163.com> Co-authored-by: MadCcc <1075746765@qq.com>pull/43098/head
kiner-tang(文辉)
1 year ago
committed by
GitHub
8 changed files with 267 additions and 36 deletions
@ -0,0 +1,181 @@ |
|||
import { CloseOutlined } from '@ant-design/icons'; |
|||
import { render } from '@testing-library/react'; |
|||
import React, { useEffect } from 'react'; |
|||
import type { UseClosableParams } from '../hooks/useClosable'; |
|||
import useClosable from '../hooks/useClosable'; |
|||
|
|||
type ParamsOfUseClosable = [ |
|||
UseClosableParams['closable'], |
|||
UseClosableParams['closeIcon'], |
|||
UseClosableParams['defaultClosable'], |
|||
]; |
|||
|
|||
describe('hooks test', () => { |
|||
const useClosableParams: { params: ParamsOfUseClosable; res: [boolean, string] }[] = [ |
|||
// test case like: <Component />
|
|||
{ |
|||
params: [undefined, undefined, undefined], |
|||
res: [false, ''], |
|||
}, |
|||
{ |
|||
params: [undefined, undefined, true], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
{ |
|||
params: [undefined, undefined, false], |
|||
res: [false, ''], |
|||
}, |
|||
|
|||
// test case like: <Component closable={false | true} />
|
|||
{ |
|||
params: [false, undefined, undefined], |
|||
res: [false, ''], |
|||
}, |
|||
{ |
|||
params: [true, undefined, true], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
{ |
|||
params: [true, undefined, false], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
|
|||
// test case like: <Component closable={false | true} closeIcon={null | false | element} />
|
|||
{ |
|||
params: [false, null, undefined], |
|||
res: [false, ''], |
|||
}, |
|||
{ |
|||
params: [false, false, undefined], |
|||
res: [false, ''], |
|||
}, |
|||
{ |
|||
params: [true, null, true], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
{ |
|||
params: [true, false, true], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
{ |
|||
params: [true, null, false], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
{ |
|||
params: [true, false, false], |
|||
res: [true, 'anticon-close'], |
|||
}, |
|||
{ |
|||
params: [ |
|||
true, |
|||
<div className="custom-close" key="close"> |
|||
close |
|||
</div>, |
|||
false, |
|||
], |
|||
res: [true, 'custom-close'], |
|||
}, |
|||
{ |
|||
params: [false, <div key="close">close</div>, false], |
|||
res: [false, ''], |
|||
}, |
|||
|
|||
// test case like: <Component closeIcon={null | false | element} />
|
|||
{ |
|||
params: [undefined, null, undefined], |
|||
res: [false, ''], |
|||
}, |
|||
{ |
|||
params: [undefined, false, undefined], |
|||
res: [false, ''], |
|||
}, |
|||
{ |
|||
params: [ |
|||
undefined, |
|||
<div className="custom-close" key="close"> |
|||
close |
|||
</div>, |
|||
undefined, |
|||
], |
|||
res: [true, 'custom-close'], |
|||
}, |
|||
{ |
|||
params: [ |
|||
undefined, |
|||
<div className="custom-close" key="close"> |
|||
close |
|||
</div>, |
|||
true, |
|||
], |
|||
res: [true, 'custom-close'], |
|||
}, |
|||
{ |
|||
params: [ |
|||
undefined, |
|||
<div className="custom-close" key="close"> |
|||
close |
|||
</div>, |
|||
false, |
|||
], |
|||
res: [true, 'custom-close'], |
|||
}, |
|||
]; |
|||
|
|||
useClosableParams.forEach(({ params, res }) => { |
|||
it(`useClosable with closable=${params[0]},closeIcon=${ |
|||
React.isValidElement(params[1]) ? 'element' : params[1] |
|||
},defaultClosable=${params[2]}. the result should be ${res}`, () => {
|
|||
const App = () => { |
|||
const [closable, closeIcon] = useClosable( |
|||
params[0], |
|||
params[1], |
|||
undefined, |
|||
undefined, |
|||
params[2], |
|||
); |
|||
useEffect(() => { |
|||
expect(closable).toBe(res[0]); |
|||
}, [closable]); |
|||
return <div>hooks test {closeIcon}</div>; |
|||
}; |
|||
const { container } = render(<App />); |
|||
if (res[1] === '') { |
|||
expect(container.querySelector('.anticon-close')).toBeFalsy(); |
|||
} else { |
|||
expect(container.querySelector(`.${res[1]}`)).toBeTruthy(); |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
it('useClosable with defaultCloseIcon', () => { |
|||
const App = () => { |
|||
const [closable, closeIcon] = useClosable( |
|||
true, |
|||
undefined, |
|||
undefined, |
|||
<CloseOutlined className="custom-close-icon" />, |
|||
); |
|||
useEffect(() => { |
|||
expect(closable).toBe(true); |
|||
}, [closable]); |
|||
return <div>hooks test {closeIcon}</div>; |
|||
}; |
|||
const { container } = render(<App />); |
|||
expect(container.querySelector('.custom-close-icon')).toBeTruthy(); |
|||
}); |
|||
|
|||
it('useClosable with customCloseIconRender', () => { |
|||
const App = () => { |
|||
const customCloseIconRender = (icon: React.ReactNode) => ( |
|||
<span className="custom-close-wrapper">{icon}</span> |
|||
); |
|||
const [closable, closeIcon] = useClosable(true, undefined, customCloseIconRender); |
|||
useEffect(() => { |
|||
expect(closable).toBe(true); |
|||
}, [closable]); |
|||
return <div>hooks test {closeIcon}</div>; |
|||
}; |
|||
const { container } = render(<App />); |
|||
expect(container.querySelector('.custom-close-wrapper')).toBeTruthy(); |
|||
}); |
|||
}); |
@ -0,0 +1,43 @@ |
|||
import { CloseOutlined } from '@ant-design/icons'; |
|||
import type { ReactNode } from 'react'; |
|||
import React from 'react'; |
|||
|
|||
function useInnerClosable( |
|||
closable?: boolean, |
|||
closeIcon?: boolean | ReactNode, |
|||
defaultClosable?: boolean, |
|||
): boolean { |
|||
if (typeof closable === 'boolean') { |
|||
return closable; |
|||
} |
|||
if (closeIcon === undefined) { |
|||
return !!defaultClosable; |
|||
} |
|||
return closeIcon !== false && closeIcon !== null; |
|||
} |
|||
|
|||
export type UseClosableParams = { |
|||
closable?: boolean; |
|||
closeIcon?: boolean | ReactNode; |
|||
defaultClosable?: boolean; |
|||
defaultCloseIcon?: ReactNode; |
|||
customCloseIconRender?: (closeIcon: ReactNode) => ReactNode; |
|||
}; |
|||
|
|||
export default function useClosable( |
|||
closable?: boolean, |
|||
closeIcon?: boolean | ReactNode, |
|||
customCloseIconRender?: (closeIcon: ReactNode) => ReactNode, |
|||
defaultCloseIcon: ReactNode = <CloseOutlined />, |
|||
defaultClosable = false, |
|||
): [closable: boolean, closeIcon: React.ReactNode | null] { |
|||
const mergedClosable = useInnerClosable(closable, closeIcon, defaultClosable); |
|||
if (!mergedClosable) { |
|||
return [false, null]; |
|||
} |
|||
const mergedCloseIcon = |
|||
typeof closeIcon === 'boolean' || closeIcon === undefined || closeIcon === null |
|||
? defaultCloseIcon |
|||
: closeIcon; |
|||
return [true, customCloseIconRender ? customCloseIconRender(mergedCloseIcon) : mergedCloseIcon]; |
|||
} |
Loading…
Reference in new issue