新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
159 lines
3.8 KiB
TypeScript
159 lines
3.8 KiB
TypeScript
import type { ReactNode } from 'react';
|
|
|
|
type PlatformStatGridColumns = 'two' | 'three' | 'four' | 'twoToFour';
|
|
type PlatformStatGridDensity = 'compact' | 'default';
|
|
type PlatformStatGridOrder = 'valueFirst' | 'labelFirst';
|
|
type PlatformStatGridSurface = 'soft' | 'plain';
|
|
type PlatformStatGridTextAlign = 'left' | 'center';
|
|
|
|
export type PlatformStatGridItem = {
|
|
label?: ReactNode;
|
|
value: ReactNode;
|
|
key?: string;
|
|
};
|
|
|
|
type PlatformStatGridProps = {
|
|
items: readonly PlatformStatGridItem[];
|
|
columns?: PlatformStatGridColumns;
|
|
density?: PlatformStatGridDensity;
|
|
order?: PlatformStatGridOrder;
|
|
surface?: PlatformStatGridSurface;
|
|
textAlign?: PlatformStatGridTextAlign;
|
|
className?: string;
|
|
itemClassName?:
|
|
| string
|
|
| ((item: PlatformStatGridItem, index: number) => string | null);
|
|
};
|
|
|
|
const PLATFORM_STAT_GRID_COLUMNS_CLASS: Record<
|
|
PlatformStatGridColumns,
|
|
string
|
|
> = {
|
|
two: 'grid-cols-2',
|
|
three: 'grid-cols-3',
|
|
four: 'grid-cols-4',
|
|
twoToFour: 'grid-cols-2 sm:grid-cols-4',
|
|
};
|
|
|
|
const PLATFORM_STAT_GRID_DENSITY_CLASS: Record<
|
|
PlatformStatGridDensity,
|
|
{ item: string; value: string; label: string }
|
|
> = {
|
|
compact: {
|
|
item: 'rounded-[1rem] px-2 py-2',
|
|
value: 'text-sm font-black',
|
|
label: 'mt-1 text-[0.68rem] font-bold tracking-[0.14em]',
|
|
},
|
|
default: {
|
|
item: 'rounded-[1rem] px-3 py-3',
|
|
value: 'text-lg font-black',
|
|
label: 'mt-1 text-[11px] font-bold tracking-[0.14em]',
|
|
},
|
|
};
|
|
|
|
const PLATFORM_STAT_GRID_SURFACE_CLASS: Record<
|
|
PlatformStatGridSurface,
|
|
string
|
|
> = {
|
|
soft: 'bg-white/76',
|
|
plain: 'border border-[var(--platform-subpanel-border)] bg-white/68',
|
|
};
|
|
|
|
const PLATFORM_STAT_GRID_TEXT_ALIGN_CLASS: Record<
|
|
PlatformStatGridTextAlign,
|
|
string
|
|
> = {
|
|
left: 'text-left',
|
|
center: 'text-center',
|
|
};
|
|
|
|
/**
|
|
* 平台统计小卡网格。
|
|
* 统一承接结果页里的“数值 / 标签”或轻量状态 chip 布局。
|
|
*/
|
|
export function PlatformStatGrid({
|
|
items,
|
|
columns = 'three',
|
|
density = 'default',
|
|
order = 'valueFirst',
|
|
surface = 'soft',
|
|
textAlign = 'center',
|
|
className,
|
|
itemClassName,
|
|
}: PlatformStatGridProps) {
|
|
const densityClass = PLATFORM_STAT_GRID_DENSITY_CLASS[density];
|
|
|
|
return (
|
|
<div
|
|
className={[
|
|
'grid gap-2',
|
|
PLATFORM_STAT_GRID_COLUMNS_CLASS[columns],
|
|
PLATFORM_STAT_GRID_TEXT_ALIGN_CLASS[textAlign],
|
|
className,
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
>
|
|
{items.map((item, index) => {
|
|
const extraClassName =
|
|
typeof itemClassName === 'function'
|
|
? itemClassName(item, index)
|
|
: itemClassName;
|
|
const key =
|
|
item.key ??
|
|
(typeof item.label === 'string'
|
|
? item.label
|
|
: typeof item.value === 'string'
|
|
? item.value
|
|
: index);
|
|
|
|
const valueNode = (
|
|
<div
|
|
className={[
|
|
densityClass.value,
|
|
'text-[var(--platform-text-strong)]',
|
|
].join(' ')}
|
|
>
|
|
{item.value}
|
|
</div>
|
|
);
|
|
const labelNode = item.label ? (
|
|
<div
|
|
className={[
|
|
densityClass.label,
|
|
'text-[var(--platform-text-soft)]',
|
|
].join(' ')}
|
|
>
|
|
{item.label}
|
|
</div>
|
|
) : null;
|
|
|
|
return (
|
|
<div
|
|
key={key}
|
|
className={[
|
|
densityClass.item,
|
|
PLATFORM_STAT_GRID_SURFACE_CLASS[surface],
|
|
extraClassName,
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ')}
|
|
>
|
|
{order === 'labelFirst' ? (
|
|
<>
|
|
{labelNode}
|
|
{valueNode}
|
|
</>
|
|
) : (
|
|
<>
|
|
{valueNode}
|
|
{labelNode}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|