From 2785d22e5c2dd3eb1bc3c179a155d06e9bd89676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=81=8F=E5=8F=B3?= Date: Sat, 25 Apr 2020 19:49:45 +0800 Subject: [PATCH 1/4] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f85cef4754..f630b4c87a 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,9 @@ An enterprise-class UI design language and React UI library. [help-wanted-url]: https://github.com/ant-design/ant-design/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 [twitter-image]: https://img.shields.io/twitter/follow/AntDesignUI.svg?label=Ant%20Design&style=social [twitter-url]: https://twitter.com/AntDesignUI -[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D +[gitter-english-image]: https://img.shields.io/gitter/room/ant-design/ant-design-english.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D [gitter-english-url]: https://gitter.im/ant-design/ant-design-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge -[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D +[gitter-chinese-image]: https://img.shields.io/gitter/room/ant-design/ant-design.svg?style=flat-square&logoWidth=18&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D [gitter-chinese-url]: https://gitter.im/ant-design/ant-design?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge [semver-stability-url]: https://dependabot.com/compatibility-score.html/?dependency-name=antd&package-manager=npm_and_yarn&new-version=latest [semver-stability-image]: https://api.dependabot.com/badges/compatibility_score?dependency-name=antd&package-manager=npm_and_yarn&target-version=latest&version-scheme=semver From 8f30a14790bee4071075f791c87e95222f22d01b Mon Sep 17 00:00:00 2001 From: Tom Xu Date: Sat, 25 Apr 2020 20:53:21 +0800 Subject: [PATCH 2/4] refactor(badge): rewrite with hook (#23488) * refactor(badge): rewrite with hook * Update ScrollNumber.tsx --- components/badge/ScrollNumber.tsx | 130 +++++++++--------------- components/badge/index.tsx | 160 +++++++++++++++--------------- 2 files changed, 125 insertions(+), 165 deletions(-) diff --git a/components/badge/ScrollNumber.tsx b/components/badge/ScrollNumber.tsx index ba1f5ab96a..cae853e521 100644 --- a/components/badge/ScrollNumber.tsx +++ b/components/badge/ScrollNumber.tsx @@ -50,73 +50,50 @@ export interface ScrollNumberState { count?: string | number | null; } -class ScrollNumber extends React.Component { - static defaultProps = { - count: null, - onAnimated() {}, - }; - - static getDerivedStateFromProps(nextProps: ScrollNumberProps, nextState: ScrollNumberState) { - if ('count' in nextProps) { - if (nextState.count === nextProps.count) { - return null; - } - return { - animateStarted: true, - }; - } - return null; - } - - lastCount?: string | number | null; - - private timeout?: number; - - constructor(props: ScrollNumberProps) { - super(props); - this.state = { - animateStarted: true, - count: props.count, - }; +const ScrollNumber: React.FC = props => { + const [animateStarted, setAnimateStarted] = React.useState(true); + const [count, setCount] = React.useState(props.count); + const [prevCount, setPrevCount] = React.useState(props.count); + const [lastCount, setLastCount] = React.useState(props.count); + + if (prevCount !== props.count) { + setAnimateStarted(true); + setPrevCount(props.count); } - componentDidUpdate(_: any, prevState: ScrollNumberState) { - this.lastCount = prevState.count; - const { animateStarted } = this.state; + React.useEffect(() => { + setLastCount(count); + let timeout: number; if (animateStarted) { - this.clearTimeout(); // Let browser has time to reset the scroller before actually // performing the transition. - this.timeout = setTimeout(() => { - // eslint-disable-next-line react/no-did-update-set-state - this.setState( - (__, props) => ({ - animateStarted: false, - count: props.count, - }), - this.onAnimated, - ); + timeout = setTimeout(() => { + setAnimateStarted(false); + setCount(props.count); + if (props.onAnimated) { + props.onAnimated(); + } }); } - } - - componentWillUnmount() { - this.clearTimeout(); - } + return () => { + if (timeout) { + clearTimeout(timeout); + } + }; + }, [animateStarted, count, props.count, props.onAnimated]); - getPositionByNum(num: number, i: number) { - const { count } = this.state; + const getPositionByNum = (num: number, i: number) => { const currentCount = Math.abs(Number(count)); - const lastCount = Math.abs(Number(this.lastCount)); - const currentDigit = Math.abs(getNumberArray(this.state.count)[i] as number); - const lastDigit = Math.abs(getNumberArray(this.lastCount)[i] as number); + const lstCount = Math.abs(Number(lastCount)); + const currentDigit = Math.abs(getNumberArray(count)[i] as number); + const lastDigit = Math.abs(getNumberArray(lstCount)[i] as number); - if (this.state.animateStarted) { + if (animateStarted) { return 10 + num; } // 同方向则在同一侧切换数字 - if (currentCount > lastCount) { + if (currentCount > lstCount) { if (currentDigit >= lastDigit) { return 10 + num; } @@ -126,20 +103,12 @@ class ScrollNumber extends React.Component return 10 + num; } return num; - } - - onAnimated = () => { - const { onAnimated } = this.props; - if (onAnimated) { - onAnimated(); - } }; - renderCurrentNumber(prefixCls: string, num: number | string, i: number) { + const renderCurrentNumber = (prefixCls: string, num: number | string, i: number) => { if (typeof num === 'number') { - const position = this.getPositionByNum(num, i); - const removeTransition = - this.state.animateStarted || getNumberArray(this.lastCount)[i] === undefined; + const position = getPositionByNum(num, i); + const removeTransition = animateStarted || getNumberArray(lastCount)[i] === undefined; return React.createElement( 'span', { @@ -161,19 +130,18 @@ class ScrollNumber extends React.Component {num} ); - } + }; - renderNumberElement(prefixCls: string) { - const { count } = this.state; + const renderNumberElement = (prefixCls: string) => { if (count && Number(count) % 1 === 0) { return getNumberArray(count) - .map((num, i) => this.renderCurrentNumber(prefixCls, num, i)) + .map((num, i) => renderCurrentNumber(prefixCls, num, i)) .reverse(); } return count; - } + }; - renderScrollNumber = ({ getPrefixCls }: ConfigConsumerProps) => { + const renderScrollNumber = ({ getPrefixCls }: ConfigConsumerProps) => { const { prefixCls: customizePrefixCls, className, @@ -181,9 +149,9 @@ class ScrollNumber extends React.Component title, component = 'sup', displayComponent, - } = this.props; + } = props; // fix https://fb.me/react-unknown-prop - const restProps = omit(this.props, [ + const restProps = omit(props, [ 'count', 'onAnimated', 'component', @@ -214,19 +182,15 @@ class ScrollNumber extends React.Component ), }); } - return React.createElement(component as any, newProps, this.renderNumberElement(prefixCls)); + return React.createElement(component as any, newProps, renderNumberElement(prefixCls)); }; - render() { - return {this.renderScrollNumber}; - } + return {renderScrollNumber}; +}; - private clearTimeout(): void { - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = undefined; - } - } -} +ScrollNumber.defaultProps = { + count: null, + onAnimated() {}, +}; export default ScrollNumber; diff --git a/components/badge/index.tsx b/components/badge/index.tsx index 9aca29b8fb..4077b16208 100644 --- a/components/badge/index.tsx +++ b/components/badge/index.tsx @@ -32,40 +32,47 @@ function isPresetColor(color?: string): boolean { return (PresetColorTypes as any[]).indexOf(color) !== -1; } -export default class Badge extends React.Component { - static defaultProps = { - count: null, - showZero: false, - dot: false, - overflowCount: 99, - }; - - getNumberedDisplayCount() { - const { count, overflowCount } = this.props; +const Badge: React.FC = props => { + const getNumberedDisplayCount = () => { + const { count, overflowCount } = props; const displayCount = (count as number) > (overflowCount as number) ? `${overflowCount}+` : count; return displayCount as string | number | null; - } + }; - getDisplayCount() { - const isDot = this.isDot(); + const hasStatus = (): boolean => { + const { status, color } = props; + return !!status || !!color; + }; + + const isZero = () => { + const numberedDisplayCount = getNumberedDisplayCount(); + return numberedDisplayCount === '0' || numberedDisplayCount === 0; + }; + + const isDot = () => { + const { dot } = props; + return (dot && !isZero()) || hasStatus(); + }; + + const getDisplayCount = () => { // dot mode don't need count - if (isDot) { + if (isDot()) { return ''; } - return this.getNumberedDisplayCount(); - } + return getNumberedDisplayCount(); + }; - getScrollNumberTitle() { - const { title, count } = this.props; + const getScrollNumberTitle = () => { + const { title, count } = props; if (title) { return title; } return typeof count === 'string' || typeof count === 'number' ? count : undefined; - } + }; - getStyleWithOffset() { - const { offset, style } = this.props; + const getStyleWithOffset = () => { + const { offset, style } = props; return offset ? { right: -parseInt(offset[0] as string, 10), @@ -73,79 +80,61 @@ export default class Badge extends React.Component { ...style, } : style; - } + }; - getBadgeClassName(prefixCls: string, direction: string = 'ltr') { - const { className, children } = this.props; + const getBadgeClassName = (prefixCls: string, direction: string = 'ltr') => { + const { className, children } = props; return classNames(className, prefixCls, { - [`${prefixCls}-status`]: this.hasStatus(), + [`${prefixCls}-status`]: hasStatus(), [`${prefixCls}-not-a-wrapper`]: !children, [`${prefixCls}-rtl`]: direction === 'rtl', }) as string; - } - - hasStatus(): boolean { - const { status, color } = this.props; - return !!status || !!color; - } + }; - isZero() { - const numberedDisplayCount = this.getNumberedDisplayCount(); - return numberedDisplayCount === '0' || numberedDisplayCount === 0; - } - - isDot() { - const { dot } = this.props; - const isZero = this.isZero(); - return (dot && !isZero) || this.hasStatus(); - } - - isHidden() { - const { showZero } = this.props; - const displayCount = this.getDisplayCount(); - const isZero = this.isZero(); - const isDot = this.isDot(); + const isHidden = () => { + const { showZero } = props; + const displayCount = getDisplayCount(); const isEmpty = displayCount === null || displayCount === undefined || displayCount === ''; - return (isEmpty || (isZero && !showZero)) && !isDot; - } + return (isEmpty || (isZero() && !showZero)) && !isDot(); + }; - renderStatusText(prefixCls: string) { - const { text } = this.props; - const hidden = this.isHidden(); + const renderStatusText = (prefixCls: string) => { + const { text } = props; + const hidden = isHidden(); return hidden || !text ? null : {text}; - } + }; - renderDisplayComponent() { - const { count } = this.props; + const renderDisplayComponent = () => { + const { count } = props; const customNode = count as React.ReactElement; if (!customNode || typeof customNode !== 'object') { return undefined; } return React.cloneElement(customNode, { style: { - ...this.getStyleWithOffset(), + ...getStyleWithOffset(), ...(customNode.props && customNode.props.style), }, }); - } + }; - renderBadgeNumber(prefixCls: string, scrollNumberPrefixCls: string) { - const { status, count, color } = this.props; + const renderBadgeNumber = (prefixCls: string, scrollNumberPrefixCls: string) => { + const { status, count, color } = props; - const displayCount = this.getDisplayCount(); - const isDot = this.isDot(); - const hidden = this.isHidden(); + const displayCount = getDisplayCount(); + const dot = isDot(); + const hidden = isHidden(); const scrollNumberCls = classNames({ - [`${prefixCls}-dot`]: isDot, - [`${prefixCls}-count`]: !isDot, + [`${prefixCls}-dot`]: dot, + [`${prefixCls}-count`]: !dot, [`${prefixCls}-multiple-words`]: - !isDot && count && count.toString && count.toString().length > 1, + !dot && count && count.toString && count.toString().length > 1, [`${prefixCls}-status-${status}`]: !!status, [`${prefixCls}-status-${color}`]: isPresetColor(color), }); - let statusStyle: React.CSSProperties | undefined = this.getStyleWithOffset(); + let statusStyle: React.CSSProperties | undefined = getStyleWithOffset(); if (color && !isPresetColor(color)) { statusStyle = statusStyle || {}; statusStyle.background = color; @@ -157,15 +146,15 @@ export default class Badge extends React.Component { data-show={!hidden} className={scrollNumberCls} count={displayCount} - displayComponent={this.renderDisplayComponent()} // }> - title={this.getScrollNumberTitle()} + displayComponent={renderDisplayComponent()} // }> + title={getScrollNumberTitle()} style={statusStyle} key="scrollNumber" /> ); - } + }; - renderBadge = ({ getPrefixCls, direction }: ConfigConsumerProps) => { + const renderBadge = ({ getPrefixCls, direction }: ConfigConsumerProps) => { const { prefixCls: customizePrefixCls, scrollNumberPrefixCls: customizeScrollNumberPrefixCls, @@ -174,7 +163,7 @@ export default class Badge extends React.Component { text, color, ...restProps - } = this.props; + } = props; const omitArr = [ 'count', 'showZero', @@ -189,11 +178,11 @@ export default class Badge extends React.Component { const prefixCls = getPrefixCls('badge', customizePrefixCls); const scrollNumberPrefixCls = getPrefixCls('scroll-number', customizeScrollNumberPrefixCls); - const scrollNumber = this.renderBadgeNumber(prefixCls, scrollNumberPrefixCls); - const statusText = this.renderStatusText(prefixCls); + const scrollNumber = renderBadgeNumber(prefixCls, scrollNumberPrefixCls); + const statusText = renderStatusText(prefixCls); const statusCls = classNames({ - [`${prefixCls}-status-dot`]: this.hasStatus(), + [`${prefixCls}-status-dot`]: hasStatus(), [`${prefixCls}-status-${status}`]: !!status, [`${prefixCls}-status-${color}`]: isPresetColor(color), }); @@ -203,13 +192,13 @@ export default class Badge extends React.Component { } // - if (!children && this.hasStatus()) { - const styleWithOffset = this.getStyleWithOffset(); + if (!children && hasStatus()) { + const styleWithOffset = getStyleWithOffset(); const statusTextColor = styleWithOffset && styleWithOffset.color; return ( @@ -221,7 +210,7 @@ export default class Badge extends React.Component { } return ( - + {children} { ); }; - render() { - return {this.renderBadge}; - } -} + return {renderBadge}; +}; + +Badge.defaultProps = { + count: null, + showZero: false, + dot: false, + overflowCount: 99, +}; + +export default Badge; From 8cdf1c017ae242868d43a0d577ce641945260310 Mon Sep 17 00:00:00 2001 From: Tom Xu Date: Sat, 25 Apr 2020 22:46:21 +0800 Subject: [PATCH 3/4] fix: ConfigProvider getPopupContainer invalid (#23594) * fix: ConfigProvider getPopupContainer invalid * slider getPopupContainer * Create container.test.js * Update container.test.js --- .../__tests__/container.test.js | 28 +++++++ .../generatePicker/generateRangePicker.tsx | 4 +- .../generatePicker/generateSinglePicker.tsx | 4 +- components/slider/index.tsx | 82 +++++++++---------- 4 files changed, 74 insertions(+), 44 deletions(-) create mode 100644 components/config-provider/__tests__/container.test.js diff --git a/components/config-provider/__tests__/container.test.js b/components/config-provider/__tests__/container.test.js new file mode 100644 index 0000000000..6f0a06f40e --- /dev/null +++ b/components/config-provider/__tests__/container.test.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import ConfigProvider from '..'; +import DatePicker from '../../date-picker'; +import Slider from '../../slider'; + +describe('ConfigProvider.GetPopupContainer', () => { + it('Datepicker', () => { + const getPopupContainer = jest.fn(node => node.parentNode); + mount( + + + , + ); + expect(getPopupContainer).toHaveBeenCalled(); + }); + + it('Slider', () => { + const getPopupContainer = jest.fn(node => node.parentNode); + const wrapper = mount( + + + , + ); + wrapper.find('.ant-slider-handle').first().simulate('mouseenter'); + expect(getPopupContainer).toHaveBeenCalled(); + }); +}); diff --git a/components/date-picker/generatePicker/generateRangePicker.tsx b/components/date-picker/generatePicker/generateRangePicker.tsx index 9355152b69..999eb964ea 100644 --- a/components/date-picker/generatePicker/generateRangePicker.tsx +++ b/components/date-picker/generatePicker/generateRangePicker.tsx @@ -49,9 +49,10 @@ export default function generateRangePicker( }; renderPicker = (locale: PickerLocale) => { - const { getPrefixCls, direction } = this.context; + const { getPrefixCls, direction, getPopupContainer } = this.context; const { prefixCls: customizePrefixCls, + getPopupContainer: customGetPopupContainer, className, size: customizeSize, bordered = true, @@ -94,6 +95,7 @@ export default function generateRangePicker( {...additionalOverrideProps} locale={locale!.lang} prefixCls={prefixCls} + getPopupContainer={customGetPopupContainer || getPopupContainer} generateConfig={generateConfig} prevIcon={} nextIcon={} diff --git a/components/date-picker/generatePicker/generateSinglePicker.tsx b/components/date-picker/generatePicker/generateSinglePicker.tsx index 3c28fe4d23..9d09604ea6 100644 --- a/components/date-picker/generatePicker/generateSinglePicker.tsx +++ b/components/date-picker/generatePicker/generateSinglePicker.tsx @@ -62,9 +62,10 @@ export default function generatePicker(generateConfig: GenerateConfig< }; renderPicker = (locale: PickerLocale) => { - const { getPrefixCls, direction } = this.context; + const { getPrefixCls, direction, getPopupContainer } = this.context; const { prefixCls: customizePrefixCls, + getPopupContainer: customizeGetPopupContainer, className, size: customizeSize, bordered = true, @@ -115,6 +116,7 @@ export default function generatePicker(generateConfig: GenerateConfig< [`${prefixCls}-borderless`]: !bordered, })} prefixCls={prefixCls} + getPopupContainer={customizeGetPopupContainer || getPopupContainer} generateConfig={generateConfig} prevIcon={} nextIcon={} diff --git a/components/slider/index.tsx b/components/slider/index.tsx index 65f83b611c..d868dfbeb8 100644 --- a/components/slider/index.tsx +++ b/components/slider/index.tsx @@ -5,7 +5,7 @@ import RcHandle from 'rc-slider/lib/Handle'; import classNames from 'classnames'; import { TooltipPlacement } from '../tooltip'; import SliderTooltip from './SliderTooltip'; -import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; +import { ConfigContext } from '../config-provider'; export interface SliderMarks { [key: number]: @@ -60,6 +60,7 @@ export interface SliderProps { export type Visibles = { [index: number]: boolean }; const Slider = React.forwardRef((props, ref) => { + const { getPrefixCls, direction, getPopupContainer } = React.useContext(ConfigContext); const [visibles, setVisibles] = React.useState({}); const toggleTooltipVisible = (index: number, visible: boolean) => { @@ -91,7 +92,7 @@ const Slider = React.forwardRef((props, ref) => { transitionName="zoom-down" key={index} overlayClassName={`${prefixCls}-tooltip`} - getPopupContainer={getTooltipPopupContainer || (() => document.body)} + getPopupContainer={getTooltipPopupContainer || getPopupContainer || (() => document.body)} > ((props, ref) => { ); }; - - const renderSlider = ({ getPrefixCls, direction }: ConfigConsumerProps) => { - const { - prefixCls: customizePrefixCls, - tooltipPrefixCls: customizeTooltipPrefixCls, - range, - className, - ...restProps - } = props; - const prefixCls = getPrefixCls('slider', customizePrefixCls); - const tooltipPrefixCls = getPrefixCls('tooltip', customizeTooltipPrefixCls); - const cls = classNames(className, { - [`${prefixCls}-rtl`]: direction === 'rtl', - }); - // make reverse default on rtl direction - if (direction === 'rtl' && !restProps.vertical) { - restProps.reverse = !restProps.reverse; - } - if (range) { - return ( - - handleWithTooltip({ - tooltipPrefixCls, - prefixCls, - info, - }) - } - prefixCls={prefixCls} - tooltipPrefixCls={tooltipPrefixCls} - /> - ); - } + const { + prefixCls: customizePrefixCls, + tooltipPrefixCls: customizeTooltipPrefixCls, + range, + className, + ...restProps + } = props; + const prefixCls = getPrefixCls('slider', customizePrefixCls); + const tooltipPrefixCls = getPrefixCls('tooltip', customizeTooltipPrefixCls); + const cls = classNames(className, { + [`${prefixCls}-rtl`]: direction === 'rtl', + }); + // make reverse default on rtl direction + if (direction === 'rtl' && !restProps.vertical) { + restProps.reverse = !restProps.reverse; + } + if (range) { return ( - ((props, ref) => { tooltipPrefixCls={tooltipPrefixCls} /> ); - }; - - return {renderSlider}; + } + return ( + + handleWithTooltip({ + tooltipPrefixCls, + prefixCls, + info, + }) + } + prefixCls={prefixCls} + tooltipPrefixCls={tooltipPrefixCls} + /> + ); }); +Slider.displayName = 'Slider'; + Slider.defaultProps = { tipFormatter(value: number) { return typeof value === 'number' ? value.toString() : ''; From 569b6539d32be6f92c10e96d2e127c042ac3ff99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=81=8F=E5=8F=B3?= Date: Sat, 25 Apr 2020 23:20:30 +0800 Subject: [PATCH 4/4] :up: eslint-plugin-unicorn --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a599d9a5d3..da990b5672 100644 --- a/package.json +++ b/package.json @@ -191,7 +191,7 @@ "eslint-plugin-markdown": "^1.0.0", "eslint-plugin-react": "^7.14.2", "eslint-plugin-react-hooks": "^3.0.0", - "eslint-plugin-unicorn": "^18.0.1", + "eslint-plugin-unicorn": "^19.0.0", "eslint-tinker": "^0.5.0", "fetch-jsonp": "^1.1.3", "fs-extra": "^9.0.0",