import { Locale } from '@lib';
import { Ohlc } from '@src/core/Legend';
import { getThemeStore } from '@src/theme/store';
import { getLocale } from '@src/translations';
import { getPercentPrecision, getPricePrecision } from '@src/utils/precision';
import { isBarData } from './typeGuards';
export function formatCompactNumber(
value: number,
locale: Locale = getLocale(),
maxFractionDigits: number = getPricePrecision(),
): string {
const unitList: { divisor: number; suffix: string }[] = [
{ divisor: 1, suffix: '' },
{ divisor: 1_000, suffix: 'k' },
{ divisor: 1_000_000, suffix: 'm' },
{ divisor: 1_000_000_000, suffix: 'b' },
{ divisor: 1_000_000_000_000, suffix: 't' },
];
let selectedUnit = unitList[0];
for (let i = unitList.length - 1; i >= 0; i--) {
if (Math.abs(value) >= unitList[i].divisor) {
selectedUnit = unitList[i];
break;
}
}
const divided = value / selectedUnit.divisor;
const formatter = new Intl.NumberFormat(locale, {
maximumFractionDigits: maxFractionDigits,
minimumFractionDigits: 0,
useGrouping: false,
});
const formattedNumber = formatter.format(divided);
return formattedNumber + selectedUnit.suffix;
}
export const formatPrice = (price?: number | string, precision = getPricePrecision()): string | undefined => {
if (price === undefined) {
return undefined;
}
return Number(price)
.toFixed(precision)
.replace(/\.?0+$/, '');
};
export const formatPercent = (value: number, precision = getPercentPrecision()): string => {
if (!Number.isFinite(value)) {
return '0%';
}
return `${value.toFixed(precision)}%`;
};
export const formatSignedNumber = (value: number): string => {
if (!Number.isFinite(value)) {
return '0';
}
const formatted = formatPrice(Math.abs(value)) ?? '0';
return value < 0 ? `-${formatted}` : formatted;
};
export const formatVolume = (volume?: number): string => {
if (!volume) return '';
if (volume >= 1000000) {
return `${(volume / 1000000).toFixed(1).replace(/\.0$/, '')}M`;
}
if (volume >= 1000) {
return `${(volume / 1000).toFixed(1).replace(/\.0$/, '')}K`;
}
return volume.toString();
};
export function getPriceColor(ohlc: Ohlc | null, upColor?: string, downColor?: string): string {
if (!ohlc) return '';
const { colors } = getThemeStore();
const positiveColor = upColor ?? colors.chartCandleUp;
const negativeColor = downColor ?? colors.chartCandleDown;
if (ohlc.open && ohlc.close && isBarData(ohlc)) {
return ohlc.close >= ohlc.open ? positiveColor : negativeColor;
}
if (typeof ohlc.absoluteChange === 'number') {
return ohlc.absoluteChange >= 0 ? positiveColor : negativeColor;
}
return '';
}