diff --git a/src/Step.tsx b/src/Step.tsx index 9f29512..a9c7258 100644 --- a/src/Step.tsx +++ b/src/Step.tsx @@ -1,6 +1,6 @@ /* eslint react/prop-types: 0 */ import * as React from 'react'; -import { isNonNullable } from '@rc-component/util'; +import { isNonNullable, isReactRenderable } from '@rc-component/util'; import { clsx } from 'clsx'; import type { Status, StepItem, StepsProps } from './Steps'; import Rail from './Rail'; @@ -126,7 +126,7 @@ export default function Step(props: StepProps) { itemCls, `${itemCls}-${mergedStatus}`, { - [`${itemCls}-custom`]: icon, + [`${itemCls}-custom`]: isReactRenderable(icon), [`${itemCls}-active`]: active, [`${itemCls}-disabled`]: disabled === true, [`${itemCls}-empty-header`]: !hasTitle && !hasSubTitle, @@ -228,7 +228,8 @@ export default function Step(props: StepProps) { ); if (itemRender) { - stepNode = (itemRender(stepNode, renderInfo) || null) as React.ReactElement; + const renderedNode = itemRender(stepNode, renderInfo); + stepNode = isReactRenderable(renderedNode) ? renderedNode : null; } return stepNode; diff --git a/tests/renderability.test.tsx b/tests/renderability.test.tsx new file mode 100644 index 0000000..720e695 --- /dev/null +++ b/tests/renderability.test.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Steps from '../src'; + +it('preserves a zero itemRender result', () => { + const { container } = render( 0} />); + expect(container.textContent).toBe('0'); +}); + +it('marks a zero icon as custom', () => { + const { container } = render(); + expect(container.querySelector('.rc-steps-item')).toHaveClass('rc-steps-item-custom'); +}); + +it.each([false, null, undefined, ''])('keeps an empty itemRender result hidden: %s', (value) => { + const { container } = render( value} />); + expect(container.querySelector('.rc-steps').textContent).toBe(''); +});