ant-design/components/badge/index.tsx
Saeed Rahimi 676de29eb4 feat: added rtl direction to all of ant-design components (#19380)
* rtl demo change en-us description

* change bundlesize css limit

* RTL: modal component (exclude confirm)

* RTL: table component

* RTL: pagination component

* cleanup rtl demo

* fix pagination.tsx compile error

* RTL: button and button-group

* RTL: Steps component

* fix rtl demo style

* fix input suffix icon alignment

* fix select component arrow issue

* RTL: form component

* add pagination rtl test

* fix test lint error

* RTL: rate component

* RTL: radio and radio group components

* RTL: tree-select component

* some fixes to RTL components

* RTL: badge component

* fix rtl issue in inline form

* fix input component rtl padding issue

* fix switch component text rtl issue

* fix table grouped header text-align

* add rtl support to whole demo with RTL button

* Update rtl demo responsive

* RTL: page-header component

* RTL: typography component

* RTL: Dropdown (Partial)

* update config-provider doc

* RTL: input component

* RTL: select component

* RTL: switch component

* RTL: tree component

* fix rtl demo lint

* rtl demo change en-us description

* RTL: modal component (exclude confirm)

* RTL: table component

* RTL: pagination component

* cleanup rtl demo

* RTL: button and button-group

* RTL: Steps component

* fix rtl demo style

* fix input suffix icon alignment

* RTL: form component

* RTL: rate component

* RTL: radio and radio group components

* RTL: tree-select component

* RTL: badge component

* fix rtl issue in inline form

* fix input component rtl padding issue

* add rtl support to whole demo with RTL button

* fix lost changes after rebase

* fix lint errors

* RTL: Transfer Component

* RTL: upload component

* RTL: update avatar demo

* RTL: comment component

* RTL: collapse component

* RTL: carousel component

* update snapshots

* RTL: Card component

* RTL: descriptions component

* RTL:  Empty component

* RTL: list component

* RTL: slider component

* slider component import/order

* add shared rtlTest

* RTL: Statistic component

* RTL: tooltip components

* RTL: popover component

* RTL: timeline component

* RTL: tag component

* RTL: alert component

* RTL: drawer component

* RTL: Tab component

* change direction definition

* RTL: progress component

* input.tsx, remove duplicate after rebase

* fix demo.less after rebase

* fix ant-row-rtl after rebase

* fix upload issues in rtl

* badge rtl demo margin fix

* fix: tabs with icon margin

* fix: radio-wrapper margin

* fix: table component after rebase

* fix: centered modal text-align

* update slider snapshot

* RTL: popconfirm component

* RTL: back-top component

* RTL: spin component

* RTL: result component

* RTL: skeleton component

* RTL: menu component

* RTL: time-picker component

* RTL: calendar component

* RTL: date-picker component

* RTL: home page

* update snapshots

* test: add auto-complete rtl test

* test: add avatar component rtl tests

* test: add badge component rtl tests

* test: add breadcrumb component rtl tests

* test: add button components rtl tests

* test: add card component rtl tests

* test: add carousel component rtl tests

* test: add cascader component rtl tests

* test: add checkbox component rtl tests

* test: add collapse component rtl tests

* test: add comment component rtl tests

* test: add dropdown component rtl tests

* test: add empty component rtl tests

* test: add form component rtl tests

* test: add grid component rtl tests

* test: add input component rtl tests

* test: add search component rtl tests

* test: add input-number component rtl tests

* test: add layout component rtl tests

* test: add list component rtl tests

* test: add mentions component rtl tests

* test: add modal component rtl tests

* test: add page-header component rtl tests

* test: add pagination component rtl tests

* test: add radio component rtl tests

* test: add rate component rtl tests

* test: add select component rtl tests

* test: add slider component rtl tests

* test: add steps component rtl tests

* test: add switch component rtl tests

* test: add table component rtl tests

* test: add transfer component rtl tests

* test: add tree component rtl tests

* test: add tree-select component rtl tests

* test: add typography component rtl tests

* test: add upload component rtl tests

* test: add affix component rtl tests

* update calendar tests

* increase css file maxSize

* update snapshots

* remove workflows to allow push

* remove duplicate reverse prop from slider

* fix: remove table demo from config-provider

* fix: remove table demo from config-provider

* fix lint error

* Added direction property to ConfigProvider

* cascader rtl tests added

* update config-provider doc

* RTL: grid system

* RTL: input component

* RTL: switch component

* fix rtl demo lint

* RTL: modal component (exclude confirm)

* RTL: table component

* RTL: pagination component

* cleanup rtl demo

* fix pagination.tsx compile error

* RTL: button and button-group

* RTL: Steps component

* fix rtl demo style

* RTL: form component

* add pagination rtl test

* RTL: rate component

* RTL: radio and radio group components

* RTL: tree-select component

* RTL: badge component

* fix rtl issue in inline form

* fix input component rtl padding issue

* add rtl support to whole demo with RTL button

* RTL: input component

* RTL: select component

* RTL: switch component

* RTL: tree component

* fix rtl demo lint

* rtl demo change en-us description

* RTL: modal component (exclude confirm)

* RTL: table component

* RTL: pagination component

* cleanup rtl demo

* RTL: button and button-group

* RTL: Steps component

* fix rtl demo style

* fix input suffix icon alignment

* RTL: form component

* RTL: rate component

* RTL: radio and radio group components

* RTL: tree-select component

* RTL: badge component

* fix rtl issue in inline form

* fix input component rtl padding issue

* add rtl support to whole demo with RTL button

* input.tsx, remove duplicate after rebase

* fix ant-row-rtl after rebase

* update snapshots

* test: add cascader component rtl tests

* test: add pagination component rtl tests

* update calendar tests

* update snapshots

* fix: remove table demo from config-provider

* fix: remove table demo from config-provider

* fix lint error

* update direction.md icons

* dropdown and cascader default placement in rtl

* update snapshots

* fix lint errors

* remove duplicate import

* update snapshots

* update snapshot

* update calendar snapshot

* update snapshots

* integrate with new rc-picker

* update snapshots

* fix lint errors

* update snapshot

* update snapshots

* update snapshots

* update snapshots :|

* update snapshots

* fix compile error.

* fix typo after rebase

* update snapshots

* remove workflows to allow push

* update snapshots

* update snapshots

* fix dist error

* front-page css fix

* update snapshots

* fix lint and test issues

* restore cascader index.less

* update snapshots

* fix logo in rtl and demo controls

* ci errors

* resolve steps/index.tsx conflicts

* tooltip family demo remove inline style

* resolve table/Table.tsx conflicts

* resolve modal/Modal.tsx conflicts

* resolve cascader/index.tsx conflicts

* add workflows from upstream

* update snapshots

* revert logo to default

* fix codebox demo direction of placements

* resolve tooltip overlayClassName conflicts

* update snapshots

* update popover test

* fix: cascader miss popupClassName

* fix: fix select missing dropdownClassName

* chore: Update snapshot

* chore: Adjust menu use rtl logic

* docs: Update demo line color

Co-authored-by: 二货机器人 <smith3816@gmail.com>
2020-01-02 19:10:16 +08:00

235 lines
6.6 KiB
TypeScript

import * as React from 'react';
import Animate from 'rc-animate';
import omit from 'omit.js';
import classNames from 'classnames';
import ScrollNumber from './ScrollNumber';
import { PresetColorTypes } from '../_util/colors';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
export { ScrollNumberProps } from './ScrollNumber';
export interface BadgeProps {
/** Number to show in badge */
count?: React.ReactNode;
showZero?: boolean;
/** Max count to show */
overflowCount?: number;
/** whether to show red dot without number */
dot?: boolean;
style?: React.CSSProperties;
prefixCls?: string;
scrollNumberPrefixCls?: string;
className?: string;
status?: 'success' | 'processing' | 'default' | 'error' | 'warning';
color?: string;
text?: React.ReactNode;
offset?: [number | string, number | string];
title?: string;
}
function isPresetColor(color?: string): boolean {
return (PresetColorTypes as any[]).indexOf(color) !== -1;
}
export default class Badge extends React.Component<BadgeProps, any> {
static defaultProps = {
count: null,
showZero: false,
dot: false,
overflowCount: 99,
};
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();
}
getScrollNumberTitle() {
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;
}
getBadgeClassName(prefixCls: string, direction: string = 'ltr') {
const { className, children } = this.props;
return classNames(className, prefixCls, {
[`${prefixCls}-status`]: this.hasStatus(),
[`${prefixCls}-not-a-wrapper`]: !children,
[`${prefixCls}-rtl`]: direction === 'rtl',
}) as string;
}
hasStatus(): boolean {
const { status, color } = this.props;
return !!status || !!color;
}
isZero() {
const numberedDispayCount = this.getNumberedDispayCount();
return numberedDispayCount === '0' || numberedDispayCount === 0;
}
isDot() {
const { dot } = this.props;
const isZero = this.isZero();
return (dot && !isZero) || this.hasStatus();
}
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;
}
renderStatusText(prefixCls: string) {
const { text } = this.props;
const hidden = this.isHidden();
return hidden || !text ? null : <span className={`${prefixCls}-status-text`}>{text}</span>;
}
renderDispayComponent() {
const { count } = this.props;
const customNode = count as React.ReactElement<any>;
if (!customNode || typeof customNode !== 'object') {
return undefined;
}
return React.cloneElement(customNode, {
style: {
...this.getStyleWithOffset(),
...(customNode.props && customNode.props.style),
},
});
}
renderBadgeNumber(prefixCls: string, scrollNumberPrefixCls: string) {
const { status, count } = 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}`]: this.hasStatus(),
});
return hidden ? null : (
<ScrollNumber
prefixCls={scrollNumberPrefixCls}
data-show={!hidden}
className={scrollNumberCls}
count={displayCount}
displayComponent={this.renderDispayComponent()} // <Badge status="success" count={<Icon type="xxx" />}></Badge>
title={this.getScrollNumberTitle()}
style={this.getStyleWithOffset()}
key="scrollNumber"
/>
);
}
renderBadge = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
children,
status,
text,
color,
...restProps
} = this.props;
const omitArr = [
'count',
'showZero',
'overflowCount',
'className',
'style',
'dot',
'offset',
'title',
];
const prefixCls = getPrefixCls('badge', customizePrefixCls);
const scrollNumberPrefixCls = getPrefixCls('scroll-number', customizeScrollNumberPrefixCls);
const scrollNumber = this.renderBadgeNumber(prefixCls, scrollNumberPrefixCls);
const statusText = this.renderStatusText(prefixCls);
const statusCls = classNames({
[`${prefixCls}-status-dot`]: this.hasStatus(),
[`${prefixCls}-status-${status}`]: !!status,
[`${prefixCls}-status-${color}`]: isPresetColor(color),
});
const statusStyle: React.CSSProperties = {};
if (color && !isPresetColor(color)) {
statusStyle.background = color;
}
// <Badge status="success" />
if (!children && this.hasStatus()) {
const styleWithOffset = this.getStyleWithOffset();
const statusTextColor = styleWithOffset && styleWithOffset.color;
return (
<span
{...omit(restProps, omitArr)}
className={this.getBadgeClassName(prefixCls, direction)}
style={styleWithOffset}
>
<span className={statusCls} style={statusStyle} />
<span style={{ color: statusTextColor }} className={`${prefixCls}-status-text`}>
{text}
</span>
</span>
);
}
return (
<span {...omit(restProps, omitArr)} className={this.getBadgeClassName(prefixCls, direction)}>
{children}
<Animate
component=""
showProp="data-show"
transitionName={children ? `${prefixCls}-zoom` : ''}
transitionAppear
>
{scrollNumber}
</Animate>
{statusText}
</span>
);
};
render() {
return <ConfigConsumer>{this.renderBadge}</ConfigConsumer>;
}
}