feat(table): support card layout

This commit is contained in:
CaIon
2026-06-19 17:43:13 +08:00
parent 68585568d6
commit 29c3dcb927
18 changed files with 320 additions and 111 deletions
+39 -7
View File
@@ -94,6 +94,20 @@ export interface CurrencyFormatOptions {
abbreviate?: boolean
/** Minimal absolute value to display when rounding would produce zero */
minimumNonZero?: number
/**
* Use locale-aware compact notation for large values (e.g. "$28万" in zh,
* "$280K" in en). The currency symbol is preserved.
*/
compact?: boolean
/** Locale used for number formatting (defaults to the runtime locale) */
locale?: Intl.LocalesArgument | undefined
}
type ResolvedCurrencyFormatOptions = Omit<
Required<CurrencyFormatOptions>,
'locale'
> & {
locale: Intl.LocalesArgument | undefined
}
type DisplayMeta =
@@ -114,11 +128,13 @@ type DisplayMeta =
quotaPerUnit: number
}
const DEFAULT_FORMAT_OPTIONS: Required<CurrencyFormatOptions> = {
const DEFAULT_FORMAT_OPTIONS: ResolvedCurrencyFormatOptions = {
digitsLarge: 2,
digitsSmall: 4,
abbreviate: true,
minimumNonZero: 0,
compact: false,
locale: undefined,
}
const DISPLAY_TYPE_VALUES = ['USD', 'CNY', 'TOKENS', 'CUSTOM'] as const
@@ -211,7 +227,7 @@ function getBillingDisplayMeta(config: CurrencyConfig): DisplayMeta {
function mergeOptions(
options?: CurrencyFormatOptions
): Required<CurrencyFormatOptions> {
): ResolvedCurrencyFormatOptions {
if (!options) return DEFAULT_FORMAT_OPTIONS
return {
digitsLarge: options.digitsLarge ?? DEFAULT_FORMAT_OPTIONS.digitsLarge,
@@ -219,6 +235,8 @@ function mergeOptions(
abbreviate: options.abbreviate ?? DEFAULT_FORMAT_OPTIONS.abbreviate,
minimumNonZero:
options.minimumNonZero ?? DEFAULT_FORMAT_OPTIONS.minimumNonZero,
compact: options.compact ?? DEFAULT_FORMAT_OPTIONS.compact,
locale: options.locale ?? DEFAULT_FORMAT_OPTIONS.locale,
}
}
@@ -260,10 +278,16 @@ function adjustForMinimum(
function formatCurrencyValue(
value: number,
options: Required<CurrencyFormatOptions>,
options: ResolvedCurrencyFormatOptions,
meta: DisplayMeta
): string {
if (meta.kind === 'tokens') {
if (options.compact) {
return new Intl.NumberFormat(options.locale, {
notation: 'compact',
maximumFractionDigits: 1,
}).format(value)
}
return formatNumberWithSuffix(
value,
options.digitsLarge,
@@ -277,19 +301,21 @@ function formatCurrencyValue(
const adjustedValue = adjustForMinimum(value, digits, options.minimumNonZero)
if (meta.kind === 'currency') {
const formatted = new Intl.NumberFormat(undefined, {
const formatted = new Intl.NumberFormat(options.locale, {
style: 'currency',
currency: meta.currencyCode,
currencyDisplay: 'narrowSymbol',
notation: options.compact ? 'compact' : 'standard',
minimumFractionDigits: 0,
maximumFractionDigits: digits,
maximumFractionDigits: options.compact ? 1 : digits,
}).format(adjustedValue)
return formatted
}
const decimal = new Intl.NumberFormat(undefined, {
const decimal = new Intl.NumberFormat(options.locale, {
notation: options.compact ? 'compact' : 'standard',
minimumFractionDigits: 0,
maximumFractionDigits: digits,
maximumFractionDigits: options.compact ? 1 : digits,
}).format(adjustedValue)
return `${meta.symbol} ${decimal}`
@@ -358,6 +384,12 @@ export function formatCurrencyFromUSD(
if (meta.kind === 'tokens') {
const tokens = amountUSD * config.quotaPerUnit
if (merged.compact) {
return new Intl.NumberFormat(merged.locale, {
notation: 'compact',
maximumFractionDigits: 1,
}).format(tokens)
}
return formatNumberWithSuffix(
tokens,
0,