Files
teatea-pension/components/ui/table.tsx

155 lines
4.1 KiB
TypeScript

import * as React from "react";
import { cn } from "@/lib/utils";
export type KumoTableLayout = "auto" | "fixed";
export type KumoTableRowVariant = "default" | "selected";
type TableProps = React.TableHTMLAttributes<HTMLTableElement> & {
layout?: KumoTableLayout;
};
type TableHeaderProps = React.HTMLAttributes<HTMLTableSectionElement> & {
sticky?: boolean;
variant?: "default" | "compact";
};
type StickyColumn = "left" | "right";
type TableHeadProps = React.ThHTMLAttributes<HTMLTableCellElement> & {
sticky?: StickyColumn;
};
type TableRowProps = React.HTMLAttributes<HTMLTableRowElement> & {
variant?: KumoTableRowVariant;
};
type TableCellProps = React.TdHTMLAttributes<HTMLTableCellElement> & {
sticky?: StickyColumn;
};
function stickyClass(sticky?: StickyColumn): string | undefined {
if (sticky === "left") {
return "sticky left-0 z-10 bg-kumo-base";
}
if (sticky === "right") {
return "sticky right-0 z-10 bg-kumo-base";
}
return undefined;
}
const TableRoot = React.forwardRef<HTMLTableElement, TableProps>(function Table(
{ className, layout = "auto", ...props },
ref,
): React.ReactElement {
return (
<table
ref={ref}
className={cn("border-collapse text-kumo-default", layout === "fixed" && "table-fixed", className)}
{...props}
/>
);
});
const TableHeader = React.forwardRef<HTMLTableSectionElement, TableHeaderProps>(function TableHeader(
{ className, sticky, variant, ...props },
ref,
): React.ReactElement {
return (
<thead
ref={ref}
className={cn(
"border-b border-kumo-line",
sticky && "sticky top-0 z-20",
variant === "compact" && "text-xs",
className,
)}
{...props}
/>
);
});
const TableHead = React.forwardRef<HTMLTableCellElement, TableHeadProps>(function TableHead(
{ className, sticky, ...props },
ref,
): React.ReactElement {
return (
<th
ref={ref}
className={cn("text-left font-medium text-kumo-subtle", stickyClass(sticky), className)}
{...props}
/>
);
});
const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
function TableBody({ className, ...props }, ref): React.ReactElement {
return <tbody ref={ref} className={cn("divide-y divide-kumo-line", className)} {...props} />;
},
);
const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(function TableRow(
{ className, variant = "default", ...props },
ref,
): React.ReactElement {
return (
<tr
ref={ref}
className={cn(
"transition-colors",
variant === "selected" && "bg-kumo-tint",
className,
)}
{...props}
/>
);
});
const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps>(function TableCell(
{ className, sticky, ...props },
ref,
): React.ReactElement {
return <td ref={ref} className={cn("text-kumo-default", stickyClass(sticky), className)} {...props} />;
});
const TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
function TableFooter({ className, ...props }, ref): React.ReactElement {
return <tfoot ref={ref} className={cn("border-t border-kumo-line bg-kumo-recessed", className)} {...props} />;
},
);
const TableResizeHandle = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(
function TableResizeHandle({ className, type = "button", ...props }, ref): React.ReactElement {
return (
<button
ref={ref}
className={cn("h-full w-1 cursor-col-resize bg-transparent hover:bg-kumo-line", className)}
type={type}
{...props}
/>
);
},
);
type TableComponent = typeof TableRoot & {
Header: typeof TableHeader;
Head: typeof TableHead;
Row: typeof TableRow;
Body: typeof TableBody;
Cell: typeof TableCell;
Footer: typeof TableFooter;
ResizeHandle: typeof TableResizeHandle;
};
export const Table = Object.assign(TableRoot, {
Header: TableHeader,
Head: TableHead,
Row: TableRow,
Body: TableBody,
Cell: TableCell,
Footer: TableFooter,
ResizeHandle: TableResizeHandle,
}) satisfies TableComponent;