返回 presentation-ai
grid-header.tsx
1 import { keyToLabel } from "../chart-utils";
2 import { EditableHeader } from "./editable-header";
3 import { type ChartDataField, type ChartEditorSchema } from "./schemas";
4 import { type SeriesChartType } from "./types";
5
6 const EMPTY_SERIES_CHART_TYPES: Record<string, SeriesChartType> = {};
7
8 interface GridHeaderProps {
9 fields: ChartDataField[];
10 schema: ChartEditorSchema;
11 seriesNames: string[];
12 onRenameSeries: (oldName: string, newName: string) => void;
13 onRemoveSeries: (name: string) => void;
14 seriesChartTypes?: Record<string, SeriesChartType>;
15 onSeriesChartTypeChange?: (
16 seriesName: string,
17 chartType: SeriesChartType,
18 ) => void;
19 isComposedChart?: boolean;
20 }
21
22 export function GridHeader({
23 fields,
24 schema,
25 seriesNames,
26 onRenameSeries,
27 onRemoveSeries,
28 seriesChartTypes = EMPTY_SERIES_CHART_TYPES,
29 onSeriesChartTypeChange,
30 isComposedChart = false,
31 }: GridHeaderProps) {
32 return (
33 <thead className="sticky top-0 z-10">
34 <tr className="border-b-2 border-border bg-muted/60">
35 <th className="h-8 w-10 border-r border-border bg-muted/80 text-center text-xs font-semibold text-muted-foreground">
36 #
37 </th>
38
39 {fields.map((field) => (
40 <th
41 key={field.key}
42 className="h-8 min-w-28 border-r border-border px-2 text-left text-xs font-semibold last:border-r-0"
43 >
44 {field.editableHeader ? (
45 <EditableHeader
46 value={field.key}
47 onRename={(newName) => onRenameSeries(field.key, newName)}
48 onRemove={() => onRemoveSeries(field.key)}
49 canRemove={seriesNames.length > 1}
50 colorIndex={field.colorIndex ?? 0}
51 chartType={seriesChartTypes[field.key] ?? "bar"}
52 onChartTypeChange={
53 onSeriesChartTypeChange
54 ? (type) => onSeriesChartTypeChange(field.key, type)
55 : undefined
56 }
57 showChartTypePicker={isComposedChart}
58 />
59 ) : (
60 <span>{keyToLabel(field.label)}</span>
61 )}
62 </th>
63 ))}
64
65 <th className="h-8 w-10 border-l border-border bg-muted/80">
66 <span className="sr-only">Delete row</span>
67 </th>
68 </tr>
69 {schema.mode === "hierarchical" && (
70 <tr className="border-b border-border bg-muted/30 text-[11px] text-muted-foreground">
71 <td
72 aria-label="Hierarchy indicator"
73 className="border-r border-border"
74 />
75 <td className="px-2 py-1" colSpan={fields.length + 1}>
76 Parent values must match another row's Name exactly.
77 </td>
78 </tr>
79 )}
80 </thead>
81 );
82 }
83
83 lines Plain Text