ant-design/components/statistic/utils.ts
mr-chenguang bd13b3442b
feat: new component Statistic.Timer (#53401)
* feat: add reverse for countdown

* refactor var

* remove unuse logic

* feat: support timer component

* revert delete countdown

* Update components/statistic/utils.ts

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Signed-off-by: mr-chenguang <37072324+lcgash@users.noreply.github.com>

* update snapshots

* refactor countdown

* fix md

* fix test:site

* fix: deprecated & refactor

* refactor

* add version

* refactor: inline of effect

* test: update test case

* test: back of part

* test: back of part

* test: back of part

* add tests & fix md

* fix md& add devusewarnning

* fix warning and add test

* remove console

* remove countdown md

---------

Signed-off-by: mr-chenguang <37072324+lcgash@users.noreply.github.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: 二货机器人 <smith3816@gmail.com>
2025-04-11 16:11:31 +08:00

72 lines
2.0 KiB
TypeScript

import type * as React from 'react';
export type valueType = number | string;
// countdownValueType is deprecated but still support
export type countdownValueType = number | string;
export type Formatter =
| false
| 'number'
| 'countdown'
| ((value: valueType, config?: FormatConfig) => React.ReactNode);
export interface FormatConfig {
formatter?: Formatter;
decimalSeparator?: string;
groupSeparator?: string;
precision?: number;
}
export interface CountdownFormatConfig extends FormatConfig {
format?: string;
}
// Countdown
const timeUnits: [string, number][] = [
['Y', 1000 * 60 * 60 * 24 * 365], // years
['M', 1000 * 60 * 60 * 24 * 30], // months
['D', 1000 * 60 * 60 * 24], // days
['H', 1000 * 60 * 60], // hours
['m', 1000 * 60], // minutes
['s', 1000], // seconds
['S', 1], // million seconds
];
export function formatTimeStr(duration: number, format: string) {
let leftDuration: number = duration;
const escapeRegex = /\[[^\]]*]/g;
const keepList: string[] = (format.match(escapeRegex) || []).map((str) => str.slice(1, -1));
const templateText = format.replace(escapeRegex, '[]');
const replacedText = timeUnits.reduce((current, [name, unit]) => {
if (current.includes(name)) {
const value = Math.floor(leftDuration / unit);
leftDuration -= value * unit;
return current.replace(new RegExp(`${name}+`, 'g'), (match: string) => {
const len = match.length;
return value.toString().padStart(len, '0');
});
}
return current;
}, templateText);
let index = 0;
return replacedText.replace(escapeRegex, () => {
const match = keepList[index];
index += 1;
return match;
});
}
export function formatCounter(value: valueType, config: CountdownFormatConfig, down: boolean) {
const { format = '' } = config;
const target = new Date(value).getTime();
const current = Date.now();
const diff = down
? Math.max(target - current, 0)
: Math.max(current - target, 0);
return formatTimeStr(diff, format);
}