diff --git a/components/badge/ScrollNumber.tsx b/components/badge/ScrollNumber.tsx index 2f973afe46..c9da6108bf 100644 --- a/components/badge/ScrollNumber.tsx +++ b/components/badge/ScrollNumber.tsx @@ -15,6 +15,7 @@ export interface ScrollNumberProps { prefixCls?: string; className?: string; count?: string | number | null; + displayComponent?: React.ReactElement; component?: string; onAnimated?: Function; style?: React.CSSProperties; @@ -116,22 +117,23 @@ export default class ScrollNumber extends Component this.renderCurrentNumber(num, i)).reverse(); } render() { - const { prefixCls, className, style, title, component = 'sup' } = this.props; + const { prefixCls, className, style, title, component = 'sup', displayComponent } = this.props; // fix https://fb.me/react-unknown-prop const restProps = omit(this.props, [ 'count', 'onAnimated', 'component', 'prefixCls', + 'displayComponent', ]); const newProps = { ...restProps, @@ -144,6 +146,11 @@ export default class ScrollNumber extends Component + + + + + + `; diff --git a/components/badge/demo/basic.md b/components/badge/demo/basic.md index 056dad78f4..75d817b355 100644 --- a/components/badge/demo/basic.md +++ b/components/badge/demo/basic.md @@ -14,7 +14,7 @@ title: Simplest Usage. Badge will be hidden when `count` is `0`, but we can use `showZero` to show it. ````jsx -import { Badge } from 'antd'; +import { Badge, Icon } from 'antd'; ReactDOM.render(
@@ -24,6 +24,9 @@ ReactDOM.render( + }> + +
, mountNode); ```` diff --git a/components/badge/index.tsx b/components/badge/index.tsx index d1b57d1ea5..5f40d5a4ea 100644 --- a/components/badge/index.tsx +++ b/components/badge/index.tsx @@ -8,7 +8,7 @@ export { ScrollNumberProps } from './ScrollNumber'; export interface BadgeProps { /** Number to show in badge */ - count?: number | string | null; + count?: React.ReactNode; showZero?: boolean; /** Max count to show */ overflowCount?: number; @@ -35,15 +35,125 @@ export default class Badge extends React.Component { }; static propTypes = { - count: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), + count: PropTypes.node, showZero: PropTypes.bool, dot: PropTypes.bool, overflowCount: PropTypes.number, }; + getBadgeClassName() { + const { + prefixCls, + className, + status, + children, + } = this.props; + return classNames(className, prefixCls, { + [`${prefixCls}-status`]: !!status, + [`${prefixCls}-not-a-wrapper`]: !children, + }) as string; + } + + isZero() { + const numberedDispayCount = this.getNumberedDispayCount(); + return numberedDispayCount === '0' || numberedDispayCount === 0; + } + + isDot() { + const { dot, status } = this.props; + const isZero = this.isZero(); + return (dot && !isZero) || status; + } + + isHidden() { + const { showZero } = this.props; + const displayCount = this.getDispayCount(); + const isZero = this.isZero(); + const isDot = this.isDot(); + const isEmpty = displayCount === null || displayCount === undefined || displayCount === ''; + return (isEmpty || (isZero && !showZero)) && !isDot; + } + + getNumberedDispayCount() { + const { count, overflowCount } = this.props; + const displayCount = (count as number) > (overflowCount as number) ? `${overflowCount}+` : count; + return displayCount as string | number | null; + } + + getDispayCount() { + const isDot = this.isDot(); + // dot mode don't need count + if (isDot) { + return ''; + } + return this.getNumberedDispayCount(); + } + + getScollNumberTitle() { + const { title, count } = this.props; + if (title) { + return title; + } + return (typeof count === 'string' || typeof count === 'number') ? count : undefined; + } + + getStyleWithOffset() { + const { offset, style } = this.props; + return offset ? { + right: -parseInt(offset[0] as string, 10), + marginTop: offset[1], + ...style, + } : style; + } + + renderStatusText() { + const { prefixCls, text } = this.props; + const hidden = this.isHidden(); + return (hidden || !text) ? null : ( + {text} + ); + } + + renderDispayComponent() { + const { count } = this.props; + return (count && typeof count === 'object') ? (count as React.ReactElement) : undefined; + } + + renderBadgeNumber() { + const { + count, + prefixCls, + scrollNumberPrefixCls, + status, + } = this.props; + + const displayCount = this.getDispayCount(); + const isDot = this.isDot(); + const hidden = this.isHidden(); + + const scrollNumberCls = classNames({ + [`${prefixCls}-dot`]: isDot, + [`${prefixCls}-count`]: !isDot, + [`${prefixCls}-multiple-words`]: !isDot && count && count.toString && count.toString().length > 1, + [`${prefixCls}-status-${status}`]: !!status, + }); + + const styleWithOffset = this.getStyleWithOffset(); + + return hidden ? null : ( + }> + title={this.getScollNumberTitle()} + style={styleWithOffset} + key="scrollNumber" + /> + ); + } + render() { const { count, @@ -61,62 +171,29 @@ export default class Badge extends React.Component { title, ...restProps } = this.props; - let displayCount = (count as number) > (overflowCount as number) ? `${overflowCount}+` : count; - const isZero = displayCount === '0' || displayCount === 0; - const isDot = (dot && !isZero) || status; - // dot mode don't need count - if (isDot) { - displayCount = ''; - } - const isEmpty = displayCount === null || displayCount === undefined || displayCount === ''; - const hidden = (isEmpty || (isZero && !showZero)) && !isDot; + + const scrollNumber = this.renderBadgeNumber(); + const statusText = this.renderStatusText(); + const statusCls = classNames({ [`${prefixCls}-status-dot`]: !!status, [`${prefixCls}-status-${status}`]: !!status, }); - const scrollNumberCls = classNames({ - [`${prefixCls}-dot`]: isDot, - [`${prefixCls}-count`]: !isDot, - [`${prefixCls}-multiple-words`]: !isDot && count && count.toString && count.toString().length > 1, - [`${prefixCls}-status-${status}`]: !!status, - }); - const badgeCls = classNames(className, prefixCls, { - [`${prefixCls}-status`]: !!status, - [`${prefixCls}-not-a-wrapper`]: !children, - }); - const styleWithOffset = offset ? { - right: -parseInt(offset[0] as string, 10), - marginTop: offset[1], - ...style, - } : style; + + const styleWithOffset = this.getStyleWithOffset(); + // if (!children && status) { return ( - + {text} ); } - const scrollNumber = hidden ? null : ( - - ); - - const statusText = (hidden || !text) ? null : ( - {text} - ); - return ( - + {children}