mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 17:44:35 +08:00
feat: make statistic component support html role and data-* and aria-* attributes (#47149)
* feat: make statistic component support html attributes * fix: types * chore: improve * feat: use pickAttrs for data-* and aria-* and role
This commit is contained in:
parent
119f8aaf79
commit
2aca1fff22
5
components/_util/aria-data-attrs.ts
Normal file
5
components/_util/aria-data-attrs.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type * as React from 'react';
|
||||||
|
|
||||||
|
export type HTMLAriaDataAttributes = React.AriaAttributes & {
|
||||||
|
[key: `data-${string}`]: unknown;
|
||||||
|
} & Pick<React.HTMLAttributes<HTMLDivElement>, 'role'>;
|
@ -9,7 +9,6 @@ import { formatCountdown } from './utils';
|
|||||||
const REFRESH_INTERVAL = 1000 / 30;
|
const REFRESH_INTERVAL = 1000 / 30;
|
||||||
|
|
||||||
export interface CountdownProps extends StatisticProps {
|
export interface CountdownProps extends StatisticProps {
|
||||||
value?: valueType;
|
|
||||||
format?: string;
|
format?: string;
|
||||||
onFinish?: () => void;
|
onFinish?: () => void;
|
||||||
onChange?: (value?: valueType) => void;
|
onChange?: (value?: valueType) => void;
|
||||||
@ -20,7 +19,7 @@ function getTime(value?: valueType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Countdown: React.FC<CountdownProps> = (props) => {
|
const Countdown: React.FC<CountdownProps> = (props) => {
|
||||||
const { value, format = 'HH:mm:ss', onChange, onFinish } = props;
|
const { value, format = 'HH:mm:ss', onChange, onFinish, ...rest } = props;
|
||||||
|
|
||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
|
|
||||||
@ -63,7 +62,7 @@ const Countdown: React.FC<CountdownProps> = (props) => {
|
|||||||
const valueRender = (node: React.ReactElement<HTMLDivElement>) =>
|
const valueRender = (node: React.ReactElement<HTMLDivElement>) =>
|
||||||
cloneElement(node, { title: undefined });
|
cloneElement(node, { title: undefined });
|
||||||
|
|
||||||
return <Statistic {...props} valueRender={valueRender} formatter={formatter} />;
|
return <Statistic {...rest} value={value} valueRender={valueRender} formatter={formatter} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default React.memo(Countdown);
|
export default React.memo(Countdown);
|
||||||
|
@ -3,6 +3,7 @@ import type { FormatConfig, valueType } from './utils';
|
|||||||
|
|
||||||
interface NumberProps extends FormatConfig {
|
interface NumberProps extends FormatConfig {
|
||||||
value: valueType;
|
value: valueType;
|
||||||
|
prefixCls?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatisticNumber: React.FC<NumberProps> = (props) => {
|
const StatisticNumber: React.FC<NumberProps> = (props) => {
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import pickAttrs from 'rc-util/lib/pickAttrs';
|
||||||
|
|
||||||
import type { ConfigConsumerProps } from '../config-provider';
|
import type { ConfigConsumerProps } from '../config-provider';
|
||||||
import { ConfigContext } from '../config-provider';
|
import { ConfigContext } from '../config-provider';
|
||||||
import Skeleton from '../skeleton';
|
import Skeleton from '../skeleton';
|
||||||
import StatisticNumber from './Number';
|
import StatisticNumber from './Number';
|
||||||
import useStyle from './style';
|
import useStyle from './style';
|
||||||
import type { FormatConfig, valueType } from './utils';
|
import type { FormatConfig, valueType } from './utils';
|
||||||
|
import type { HTMLAriaDataAttributes } from '../_util/aria-data-attrs';
|
||||||
|
|
||||||
export interface StatisticProps extends FormatConfig {
|
interface StatisticReactProps extends FormatConfig {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
rootClassName?: string;
|
rootClassName?: string;
|
||||||
@ -23,7 +26,9 @@ export interface StatisticProps extends FormatConfig {
|
|||||||
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Statistic: React.FC<StatisticProps> = (props) => {
|
export type StatisticProps = HTMLAriaDataAttributes & StatisticReactProps;
|
||||||
|
|
||||||
|
const Statistic: React.FC<StatisticProps & HTMLAriaDataAttributes> = (props) => {
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
className,
|
className,
|
||||||
@ -36,10 +41,15 @@ const Statistic: React.FC<StatisticProps> = (props) => {
|
|||||||
prefix,
|
prefix,
|
||||||
suffix,
|
suffix,
|
||||||
loading = false,
|
loading = false,
|
||||||
onMouseEnter,
|
/* --- FormatConfig starts --- */
|
||||||
onMouseLeave,
|
formatter,
|
||||||
|
precision,
|
||||||
decimalSeparator = '.',
|
decimalSeparator = '.',
|
||||||
groupSeparator = ',',
|
groupSeparator = ',',
|
||||||
|
/* --- FormatConfig starts --- */
|
||||||
|
onMouseEnter,
|
||||||
|
onMouseLeave,
|
||||||
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { getPrefixCls, direction, statistic } =
|
const { getPrefixCls, direction, statistic } =
|
||||||
@ -54,7 +64,8 @@ const Statistic: React.FC<StatisticProps> = (props) => {
|
|||||||
decimalSeparator={decimalSeparator}
|
decimalSeparator={decimalSeparator}
|
||||||
groupSeparator={groupSeparator}
|
groupSeparator={groupSeparator}
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls}
|
||||||
{...props}
|
formatter={formatter}
|
||||||
|
precision={precision}
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -71,8 +82,11 @@ const Statistic: React.FC<StatisticProps> = (props) => {
|
|||||||
cssVarCls,
|
cssVarCls,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const restProps = pickAttrs(rest, { aria: true, data: true });
|
||||||
|
|
||||||
return wrapCSSVar(
|
return wrapCSSVar(
|
||||||
<div
|
<div
|
||||||
|
{...restProps}
|
||||||
className={cls}
|
className={cls}
|
||||||
style={{ ...statistic?.style, ...style }}
|
style={{ ...statistic?.style, ...style }}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
|
@ -81,6 +81,28 @@ describe('Statistic', () => {
|
|||||||
expect(container.querySelectorAll('.ant-statistic-content')).toHaveLength(0);
|
expect(container.querySelectorAll('.ant-statistic-content')).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('data attrs', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Statistic value={1128} data-abc="1" aria-label="2" role="status" />,
|
||||||
|
);
|
||||||
|
expect(container.querySelector('.ant-statistic')!.getAttribute('data-abc')).toEqual('1');
|
||||||
|
expect(container.querySelector('.ant-statistic')!.getAttribute('aria-label')).toEqual('2');
|
||||||
|
expect(container.querySelector('.ant-statistic')!.getAttribute('role')).toEqual('status');
|
||||||
|
|
||||||
|
const { container: countdownContainer } = render(
|
||||||
|
<Statistic.Countdown data-xyz="x" aria-label="y" role="contentinfo" />,
|
||||||
|
);
|
||||||
|
expect(countdownContainer.querySelector('.ant-statistic')!.getAttribute('data-xyz')).toEqual(
|
||||||
|
'x',
|
||||||
|
);
|
||||||
|
expect(countdownContainer.querySelector('.ant-statistic')!.getAttribute('aria-label')).toEqual(
|
||||||
|
'y',
|
||||||
|
);
|
||||||
|
expect(countdownContainer.querySelector('.ant-statistic')!.getAttribute('role')).toEqual(
|
||||||
|
'contentinfo',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
describe('Countdown', () => {
|
describe('Countdown', () => {
|
||||||
it('render correctly', () => {
|
it('render correctly', () => {
|
||||||
const now = dayjs()
|
const now = dayjs()
|
||||||
|
@ -15,7 +15,6 @@ export interface FormatConfig {
|
|||||||
decimalSeparator?: string;
|
decimalSeparator?: string;
|
||||||
groupSeparator?: string;
|
groupSeparator?: string;
|
||||||
precision?: number;
|
precision?: number;
|
||||||
prefixCls?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CountdownFormatConfig extends FormatConfig {
|
export interface CountdownFormatConfig extends FormatConfig {
|
||||||
|
Loading…
Reference in New Issue
Block a user