@meta-1/design 0.0.170 → 0.0.171
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
type PaginationProps,
|
|
29
29
|
Spin,
|
|
30
30
|
} from "@meta-1/design";
|
|
31
|
+
import { ScrollArea } from "@meta-1/design/components/ui/scroll-area";
|
|
31
32
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../ui/table";
|
|
32
33
|
import "./style.css";
|
|
33
34
|
|
|
@@ -68,6 +69,8 @@ export interface DataTableProps<TData> {
|
|
|
68
69
|
empty?: string;
|
|
69
70
|
showHeader?: boolean;
|
|
70
71
|
onRowClick?: (row: Row<TData>) => void;
|
|
72
|
+
/** 表格最大高度,设置后内容区将滚动,表头固定。支持 CSS 单位如 '500px', '50vh' 等 */
|
|
73
|
+
maxHeight?: string | number;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
// 本地存储相关函数
|
|
@@ -173,6 +176,7 @@ export function DataTable<TData>(props: DataTableProps<TData>) {
|
|
|
173
176
|
showHeader = true,
|
|
174
177
|
autoHidePagination = true,
|
|
175
178
|
inCard = false,
|
|
179
|
+
maxHeight,
|
|
176
180
|
} = props;
|
|
177
181
|
|
|
178
182
|
const config = useContext(UIXContext);
|
|
@@ -363,6 +367,108 @@ export function DataTable<TData>(props: DataTableProps<TData>) {
|
|
|
363
367
|
return pagination;
|
|
364
368
|
}, [pagination, autoHidePagination]);
|
|
365
369
|
|
|
370
|
+
// 渲染表头的通用函数
|
|
371
|
+
const renderTableHeader = (options: { fixedHeader?: boolean } = {}) => {
|
|
372
|
+
const { fixedHeader = false } = options;
|
|
373
|
+
return (
|
|
374
|
+
<TableHeader className={cn(!showHeader && "hidden", fixedHeader && "sticky top-0 z-20 bg-background")}>
|
|
375
|
+
{table.getHeaderGroups().map((headerGroup) => (
|
|
376
|
+
<TableRow key={headerGroup.id}>
|
|
377
|
+
{headerGroup.headers.map((header) => {
|
|
378
|
+
const sticky = mounted
|
|
379
|
+
? getSticky(header.column.id, leftStickyColumns, rightStickyColumns)
|
|
380
|
+
: { enable: false };
|
|
381
|
+
const content = header.isPlaceholder
|
|
382
|
+
? null
|
|
383
|
+
: flexRender(header.column.columnDef.header, header.getContext());
|
|
384
|
+
return (
|
|
385
|
+
<TableHead
|
|
386
|
+
className={cn(
|
|
387
|
+
sticky.enable ? "table-sticky-col sticky" : null,
|
|
388
|
+
sticky.last ? "table-sticky-col-last" : null,
|
|
389
|
+
sticky.first ? "table-sticky-col-first" : null,
|
|
390
|
+
// biome-ignore lint/suspicious/noExplicitAny: <className>
|
|
391
|
+
(header.column.columnDef as any).className,
|
|
392
|
+
)}
|
|
393
|
+
key={header.id}
|
|
394
|
+
style={
|
|
395
|
+
sticky.enable
|
|
396
|
+
? {
|
|
397
|
+
zIndex: fixedHeader ? 30 : 10,
|
|
398
|
+
minWidth: sticky.width,
|
|
399
|
+
[sticky.position as string]: sticky.offset,
|
|
400
|
+
}
|
|
401
|
+
: undefined
|
|
402
|
+
}
|
|
403
|
+
>
|
|
404
|
+
{sticky.enable ? <div className="inner flex h-10 items-center px-2">{content}</div> : content}
|
|
405
|
+
</TableHead>
|
|
406
|
+
);
|
|
407
|
+
})}
|
|
408
|
+
</TableRow>
|
|
409
|
+
))}
|
|
410
|
+
</TableHeader>
|
|
411
|
+
);
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// 渲染表体的通用函数
|
|
415
|
+
const renderTableBody = () => {
|
|
416
|
+
return (
|
|
417
|
+
<TableBody>
|
|
418
|
+
{table.getRowModel().rows?.length ? (
|
|
419
|
+
table.getRowModel().rows.map((row) => (
|
|
420
|
+
<TableRow
|
|
421
|
+
data-state={row.getIsSelected() && "selected"}
|
|
422
|
+
key={row.id}
|
|
423
|
+
onClick={() => props.onRowClick?.(row)}
|
|
424
|
+
>
|
|
425
|
+
{row.getVisibleCells().map((cell) => {
|
|
426
|
+
const sticky = mounted
|
|
427
|
+
? getSticky(cell.column.id, leftStickyColumns, rightStickyColumns)
|
|
428
|
+
: { enable: false };
|
|
429
|
+
const ctx = cell.getContext();
|
|
430
|
+
const render = ctx.renderValue;
|
|
431
|
+
// biome-ignore lint/suspicious/noExplicitAny: <formatters>
|
|
432
|
+
const formatters = (cell.column.columnDef as any).formatters || [];
|
|
433
|
+
ctx.renderValue = () => {
|
|
434
|
+
return formatValue(render(), formatters, cellHandles);
|
|
435
|
+
};
|
|
436
|
+
const content = flexRender(cell.column.columnDef.cell, ctx);
|
|
437
|
+
return (
|
|
438
|
+
<TableCell
|
|
439
|
+
className={cn(
|
|
440
|
+
sticky.enable ? "table-sticky-col sticky" : null,
|
|
441
|
+
sticky.last ? "table-sticky-col-last" : null,
|
|
442
|
+
sticky.first ? "table-sticky-col-first" : null,
|
|
443
|
+
)}
|
|
444
|
+
key={cell.id}
|
|
445
|
+
style={
|
|
446
|
+
sticky.enable
|
|
447
|
+
? {
|
|
448
|
+
zIndex: 10,
|
|
449
|
+
minWidth: sticky.width,
|
|
450
|
+
[sticky.position as string]: sticky.offset,
|
|
451
|
+
}
|
|
452
|
+
: undefined
|
|
453
|
+
}
|
|
454
|
+
>
|
|
455
|
+
{sticky.enable ? <div className="inner flex h-10 items-center px-2">{content}</div> : content}
|
|
456
|
+
</TableCell>
|
|
457
|
+
);
|
|
458
|
+
})}
|
|
459
|
+
</TableRow>
|
|
460
|
+
))
|
|
461
|
+
) : (
|
|
462
|
+
<TableRow>
|
|
463
|
+
<TableCell className="h-24 text-center" colSpan={tableColumns.length}>
|
|
464
|
+
{empty}
|
|
465
|
+
</TableCell>
|
|
466
|
+
</TableRow>
|
|
467
|
+
)}
|
|
468
|
+
</TableBody>
|
|
469
|
+
);
|
|
470
|
+
};
|
|
471
|
+
|
|
366
472
|
return (
|
|
367
473
|
<>
|
|
368
474
|
{showToolbar ? (
|
|
@@ -384,99 +490,23 @@ export function DataTable<TData>(props: DataTableProps<TData>) {
|
|
|
384
490
|
</div>
|
|
385
491
|
) : null}
|
|
386
492
|
<div className={cn("relative")}>
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
sticky.first ? "table-sticky-col-first" : null,
|
|
405
|
-
// biome-ignore lint/suspicious/noExplicitAny: <className>
|
|
406
|
-
(header.column.columnDef as any).className,
|
|
407
|
-
)}
|
|
408
|
-
key={header.id}
|
|
409
|
-
style={
|
|
410
|
-
sticky.enable
|
|
411
|
-
? {
|
|
412
|
-
zIndex: 10,
|
|
413
|
-
minWidth: sticky.width,
|
|
414
|
-
[sticky.position as string]: sticky.offset,
|
|
415
|
-
}
|
|
416
|
-
: undefined
|
|
417
|
-
}
|
|
418
|
-
>
|
|
419
|
-
{sticky.enable ? <div className="inner flex h-10 items-center px-2">{content}</div> : content}
|
|
420
|
-
</TableHead>
|
|
421
|
-
);
|
|
422
|
-
})}
|
|
423
|
-
</TableRow>
|
|
424
|
-
))}
|
|
425
|
-
</TableHeader>
|
|
426
|
-
<TableBody>
|
|
427
|
-
{table.getRowModel().rows?.length ? (
|
|
428
|
-
table.getRowModel().rows.map((row) => (
|
|
429
|
-
<TableRow
|
|
430
|
-
data-state={row.getIsSelected() && "selected"}
|
|
431
|
-
key={row.id}
|
|
432
|
-
onClick={() => props.onRowClick?.(row)}
|
|
433
|
-
>
|
|
434
|
-
{row.getVisibleCells().map((cell) => {
|
|
435
|
-
// 在未挂载时禁用粘性列功能,避免 SSR 水合错误
|
|
436
|
-
const sticky = mounted
|
|
437
|
-
? getSticky(cell.column.id, leftStickyColumns, rightStickyColumns)
|
|
438
|
-
: { enable: false };
|
|
439
|
-
const ctx = cell.getContext();
|
|
440
|
-
const render = ctx.renderValue;
|
|
441
|
-
// biome-ignore lint/suspicious/noExplicitAny: <formatters>
|
|
442
|
-
const formatters = (cell.column.columnDef as any).formatters || [];
|
|
443
|
-
ctx.renderValue = () => {
|
|
444
|
-
return formatValue(render(), formatters, cellHandles);
|
|
445
|
-
};
|
|
446
|
-
const content = flexRender(cell.column.columnDef.cell, ctx);
|
|
447
|
-
return (
|
|
448
|
-
<TableCell
|
|
449
|
-
className={cn(
|
|
450
|
-
sticky.enable ? "table-sticky-col sticky" : null,
|
|
451
|
-
sticky.last ? "table-sticky-col-last" : null,
|
|
452
|
-
sticky.first ? "table-sticky-col-first" : null,
|
|
453
|
-
)}
|
|
454
|
-
key={cell.id}
|
|
455
|
-
style={
|
|
456
|
-
sticky.enable
|
|
457
|
-
? {
|
|
458
|
-
zIndex: 10,
|
|
459
|
-
minWidth: sticky.width,
|
|
460
|
-
[sticky.position as string]: sticky.offset,
|
|
461
|
-
}
|
|
462
|
-
: undefined
|
|
463
|
-
}
|
|
464
|
-
>
|
|
465
|
-
{sticky.enable ? <div className="inner flex h-10 items-center px-2">{content}</div> : content}
|
|
466
|
-
</TableCell>
|
|
467
|
-
);
|
|
468
|
-
})}
|
|
469
|
-
</TableRow>
|
|
470
|
-
))
|
|
471
|
-
) : (
|
|
472
|
-
<TableRow>
|
|
473
|
-
<TableCell className="h-24 text-center" colSpan={tableColumns.length}>
|
|
474
|
-
{empty}
|
|
475
|
-
</TableCell>
|
|
476
|
-
</TableRow>
|
|
477
|
-
)}
|
|
478
|
-
</TableBody>
|
|
479
|
-
</Table>
|
|
493
|
+
{maxHeight ? (
|
|
494
|
+
// 有高度限制时,使用 ScrollArea 包裹 TableBody,表头固定
|
|
495
|
+
<div className={cn("rounded-md border", !mounted && "invisible")}>
|
|
496
|
+
<Table className={classNames("data-table", inCard ? "in-card" : null)}>
|
|
497
|
+
{renderTableHeader({ fixedHeader: true })}
|
|
498
|
+
</Table>
|
|
499
|
+
<ScrollArea style={{ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight }}>
|
|
500
|
+
<Table className={classNames("data-table", inCard ? "in-card" : null)}>{renderTableBody()}</Table>
|
|
501
|
+
</ScrollArea>
|
|
502
|
+
</div>
|
|
503
|
+
) : (
|
|
504
|
+
// 无高度限制时,使用原有布局
|
|
505
|
+
<Table className={classNames("data-table", inCard ? "in-card" : null, !mounted && "invisible")}>
|
|
506
|
+
{renderTableHeader()}
|
|
507
|
+
{renderTableBody()}
|
|
508
|
+
</Table>
|
|
509
|
+
)}
|
|
480
510
|
<div className={cn("py-4", !mounted && "invisible")}>
|
|
481
511
|
{showPagination && (
|
|
482
512
|
<Pagination
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
DialogTitle,
|
|
10
10
|
Dialog as UIDialog,
|
|
11
11
|
} from "@meta-1/design/components/ui/dialog";
|
|
12
|
+
import { ScrollArea } from "@meta-1/design/components/ui/scroll-area";
|
|
12
13
|
import { Spin } from "@meta-1/design/components/uix/spin";
|
|
13
14
|
import { cn } from "@meta-1/design/lib";
|
|
14
15
|
|
|
@@ -55,7 +56,7 @@ export const Dialog: FC<DialogProps> = (props) => {
|
|
|
55
56
|
<DialogTitle className={cn(!title && "sr-only")}>{title || "Dialog"}</DialogTitle>
|
|
56
57
|
{description ? <DialogDescription>{description}</DialogDescription> : null}
|
|
57
58
|
</DialogHeader>
|
|
58
|
-
<
|
|
59
|
+
<ScrollArea className="min-h-0 flex-1 px-6 py-4">{props.children}</ScrollArea>
|
|
59
60
|
{footer ? <DialogFooter>{footer}</DialogFooter> : null}
|
|
60
61
|
{loading ? (
|
|
61
62
|
<div className={cn("absolute top-0 right-0 bottom-0 left-0 bg-white/50", "flex items-center justify-center")}>
|