@meta-1/design 0.0.170 → 0.0.172
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
|
@@ -52,7 +52,7 @@ function DialogContent({
|
|
|
52
52
|
<DialogOverlay onClick={onOverlayClick} />
|
|
53
53
|
<DialogPrimitive.Content
|
|
54
54
|
className={cn(
|
|
55
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col w-full max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border bg-background shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg",
|
|
55
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col gap-4 w-full max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border bg-background shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg",
|
|
56
56
|
className,
|
|
57
57
|
)}
|
|
58
58
|
data-slot="dialog-content"
|
|
@@ -5,7 +5,7 @@ import { cn } from "@meta-1/design/lib/utils";
|
|
|
5
5
|
|
|
6
6
|
function ScrollArea({ className, children, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
|
|
7
7
|
return (
|
|
8
|
-
<ScrollAreaPrimitive.Root className={cn("relative", className)} data-slot="scroll-area" {...props}>
|
|
8
|
+
<ScrollAreaPrimitive.Root className={cn("relative overflow-hidden", className)} data-slot="scroll-area" {...props}>
|
|
9
9
|
<ScrollAreaPrimitive.Viewport
|
|
10
10
|
className="size-full rounded-[inherit] outline-none transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50"
|
|
11
11
|
data-slot="scroll-area-viewport"
|
|
@@ -68,6 +68,8 @@ export interface DataTableProps<TData> {
|
|
|
68
68
|
empty?: string;
|
|
69
69
|
showHeader?: boolean;
|
|
70
70
|
onRowClick?: (row: Row<TData>) => void;
|
|
71
|
+
/** 表格最大高度,设置后内容区将滚动,表头固定。支持 CSS 单位如 '500px', '50vh' 等 */
|
|
72
|
+
maxHeight?: string | number;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
// 本地存储相关函数
|
|
@@ -173,6 +175,7 @@ export function DataTable<TData>(props: DataTableProps<TData>) {
|
|
|
173
175
|
showHeader = true,
|
|
174
176
|
autoHidePagination = true,
|
|
175
177
|
inCard = false,
|
|
178
|
+
maxHeight,
|
|
176
179
|
} = props;
|
|
177
180
|
|
|
178
181
|
const config = useContext(UIXContext);
|
|
@@ -363,6 +366,107 @@ export function DataTable<TData>(props: DataTableProps<TData>) {
|
|
|
363
366
|
return pagination;
|
|
364
367
|
}, [pagination, autoHidePagination]);
|
|
365
368
|
|
|
369
|
+
// 渲染表头的通用函数
|
|
370
|
+
const renderTableHeader = () => {
|
|
371
|
+
return (
|
|
372
|
+
<TableHeader className={cn(!showHeader && "hidden")}>
|
|
373
|
+
{table.getHeaderGroups().map((headerGroup) => (
|
|
374
|
+
<TableRow key={headerGroup.id}>
|
|
375
|
+
{headerGroup.headers.map((header) => {
|
|
376
|
+
const sticky = mounted
|
|
377
|
+
? getSticky(header.column.id, leftStickyColumns, rightStickyColumns)
|
|
378
|
+
: { enable: false };
|
|
379
|
+
const content = header.isPlaceholder
|
|
380
|
+
? null
|
|
381
|
+
: flexRender(header.column.columnDef.header, header.getContext());
|
|
382
|
+
return (
|
|
383
|
+
<TableHead
|
|
384
|
+
className={cn(
|
|
385
|
+
sticky.enable ? "table-sticky-col sticky" : null,
|
|
386
|
+
sticky.last ? "table-sticky-col-last" : null,
|
|
387
|
+
sticky.first ? "table-sticky-col-first" : null,
|
|
388
|
+
// biome-ignore lint/suspicious/noExplicitAny: <className>
|
|
389
|
+
(header.column.columnDef as any).className,
|
|
390
|
+
)}
|
|
391
|
+
key={header.id}
|
|
392
|
+
style={
|
|
393
|
+
sticky.enable
|
|
394
|
+
? {
|
|
395
|
+
zIndex: 10,
|
|
396
|
+
minWidth: sticky.width,
|
|
397
|
+
[sticky.position as string]: sticky.offset,
|
|
398
|
+
}
|
|
399
|
+
: undefined
|
|
400
|
+
}
|
|
401
|
+
>
|
|
402
|
+
{sticky.enable ? <div className="inner flex h-10 items-center px-2">{content}</div> : content}
|
|
403
|
+
</TableHead>
|
|
404
|
+
);
|
|
405
|
+
})}
|
|
406
|
+
</TableRow>
|
|
407
|
+
))}
|
|
408
|
+
</TableHeader>
|
|
409
|
+
);
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// 渲染表体的通用函数
|
|
413
|
+
const renderTableBody = () => {
|
|
414
|
+
return (
|
|
415
|
+
<TableBody>
|
|
416
|
+
{table.getRowModel().rows?.length ? (
|
|
417
|
+
table.getRowModel().rows.map((row) => (
|
|
418
|
+
<TableRow
|
|
419
|
+
data-state={row.getIsSelected() && "selected"}
|
|
420
|
+
key={row.id}
|
|
421
|
+
onClick={() => props.onRowClick?.(row)}
|
|
422
|
+
>
|
|
423
|
+
{row.getVisibleCells().map((cell) => {
|
|
424
|
+
const sticky = mounted
|
|
425
|
+
? getSticky(cell.column.id, leftStickyColumns, rightStickyColumns)
|
|
426
|
+
: { enable: false };
|
|
427
|
+
const ctx = cell.getContext();
|
|
428
|
+
const render = ctx.renderValue;
|
|
429
|
+
// biome-ignore lint/suspicious/noExplicitAny: <formatters>
|
|
430
|
+
const formatters = (cell.column.columnDef as any).formatters || [];
|
|
431
|
+
ctx.renderValue = () => {
|
|
432
|
+
return formatValue(render(), formatters, cellHandles);
|
|
433
|
+
};
|
|
434
|
+
const content = flexRender(cell.column.columnDef.cell, ctx);
|
|
435
|
+
return (
|
|
436
|
+
<TableCell
|
|
437
|
+
className={cn(
|
|
438
|
+
sticky.enable ? "table-sticky-col sticky" : null,
|
|
439
|
+
sticky.last ? "table-sticky-col-last" : null,
|
|
440
|
+
sticky.first ? "table-sticky-col-first" : null,
|
|
441
|
+
)}
|
|
442
|
+
key={cell.id}
|
|
443
|
+
style={
|
|
444
|
+
sticky.enable
|
|
445
|
+
? {
|
|
446
|
+
zIndex: 10,
|
|
447
|
+
minWidth: sticky.width,
|
|
448
|
+
[sticky.position as string]: sticky.offset,
|
|
449
|
+
}
|
|
450
|
+
: undefined
|
|
451
|
+
}
|
|
452
|
+
>
|
|
453
|
+
{sticky.enable ? <div className="inner flex h-10 items-center px-2">{content}</div> : content}
|
|
454
|
+
</TableCell>
|
|
455
|
+
);
|
|
456
|
+
})}
|
|
457
|
+
</TableRow>
|
|
458
|
+
))
|
|
459
|
+
) : (
|
|
460
|
+
<TableRow>
|
|
461
|
+
<TableCell className="h-24 text-center" colSpan={tableColumns.length}>
|
|
462
|
+
{empty}
|
|
463
|
+
</TableCell>
|
|
464
|
+
</TableRow>
|
|
465
|
+
)}
|
|
466
|
+
</TableBody>
|
|
467
|
+
);
|
|
468
|
+
};
|
|
469
|
+
|
|
366
470
|
return (
|
|
367
471
|
<>
|
|
368
472
|
{showToolbar ? (
|
|
@@ -384,99 +488,32 @@ export function DataTable<TData>(props: DataTableProps<TData>) {
|
|
|
384
488
|
</div>
|
|
385
489
|
) : null}
|
|
386
490
|
<div className={cn("relative")}>
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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>
|
|
491
|
+
{maxHeight ? (
|
|
492
|
+
// 有高度限制时:直接渲染 table 元素,避免 Table 组件自带的 overflow-x-auto 包裹层
|
|
493
|
+
<div className={cn("overflow-x-auto", !mounted && "invisible")}>
|
|
494
|
+
<div
|
|
495
|
+
className="overflow-y-auto"
|
|
496
|
+
style={{ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight }}
|
|
497
|
+
>
|
|
498
|
+
<table
|
|
499
|
+
className={classNames(
|
|
500
|
+
"data-table data-table-sticky-header w-full caption-bottom text-sm",
|
|
501
|
+
inCard ? "in-card" : null,
|
|
502
|
+
)}
|
|
503
|
+
data-slot="table"
|
|
504
|
+
>
|
|
505
|
+
{renderTableHeader()}
|
|
506
|
+
{renderTableBody()}
|
|
507
|
+
</table>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
510
|
+
) : (
|
|
511
|
+
// 无高度限制时,使用原有布局
|
|
512
|
+
<Table className={classNames("data-table", inCard ? "in-card" : null, !mounted && "invisible")}>
|
|
513
|
+
{renderTableHeader()}
|
|
514
|
+
{renderTableBody()}
|
|
515
|
+
</Table>
|
|
516
|
+
)}
|
|
480
517
|
<div className={cn("py-4", !mounted && "invisible")}>
|
|
481
518
|
{showPagination && (
|
|
482
519
|
<Pagination
|
|
@@ -38,3 +38,39 @@
|
|
|
38
38
|
.data-table tr[data-state="selected"] td.table-sticky-col .inner {
|
|
39
39
|
@apply bg-[hsl(var(--muted))];
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
.data-table-sticky-header thead {
|
|
43
|
+
position: sticky;
|
|
44
|
+
top: 0;
|
|
45
|
+
z-index: 20;
|
|
46
|
+
@apply bg-background;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.data-table-sticky-header.in-card thead {
|
|
50
|
+
@apply bg-card;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.data-table-sticky-header thead th {
|
|
54
|
+
@apply bg-background;
|
|
55
|
+
z-index: 20;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.data-table-sticky-header.in-card thead th {
|
|
59
|
+
@apply bg-card;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.data-table-sticky-header thead th.table-sticky-col {
|
|
63
|
+
z-index: 30;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.data-table-sticky-header thead th.table-sticky-col.sticky {
|
|
67
|
+
position: sticky !important;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.data-table-sticky-header thead th.table-sticky-col .inner {
|
|
71
|
+
@apply bg-background;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.data-table-sticky-header.in-card thead th.table-sticky-col .inner {
|
|
75
|
+
@apply bg-card;
|
|
76
|
+
}
|
|
@@ -55,7 +55,7 @@ export const Dialog: FC<DialogProps> = (props) => {
|
|
|
55
55
|
<DialogTitle className={cn(!title && "sr-only")}>{title || "Dialog"}</DialogTitle>
|
|
56
56
|
{description ? <DialogDescription>{description}</DialogDescription> : null}
|
|
57
57
|
</DialogHeader>
|
|
58
|
-
<div className="min-h-0 flex-1 overflow-
|
|
58
|
+
<div className="min-h-0 flex-1 overflow-auto px-6">{props.children}</div>
|
|
59
59
|
{footer ? <DialogFooter>{footer}</DialogFooter> : null}
|
|
60
60
|
{loading ? (
|
|
61
61
|
<div className={cn("absolute top-0 right-0 bottom-0 left-0 bg-white/50", "flex items-center justify-center")}>
|