"use client"; import clsx from "clsx"; import type { ComponentProps, CSSProperties, ReactNode } from "react"; import type { RowProps, ColumnProps, TableBodyProps, } from "react-aria-components"; import styles from "./index.module.scss"; import { Button } from "../Button/index.js"; import { Skeleton } from "../Skeleton/index.js"; import { Cell, Column, Row, Table as UnstyledTable, TableBody, TableHeader, } from "../unstyled/Table/index.js"; export type { SortDescriptor } from "../unstyled/Table/index.js"; type TableProps = ComponentProps & { className?: string | undefined; headerCellClassName?: string | undefined; stickyHeader?: boolean | string | undefined; fill?: boolean | undefined; rounded?: boolean | undefined; label: string; columns: ColumnConfig[]; isLoading?: boolean | undefined; isUpdating?: boolean | undefined; dependencies?: TableBodyProps["dependencies"] | undefined; } & ( | { isLoading: true; rows?: RowConfig[] | undefined } | { isLoading?: false | undefined; rows: RowConfig[] } ) & ( | { hideHeadersInEmptyState?: undefined } | ({ hideHeadersInEmptyState?: boolean } & ( | { emptyState: ReactNode } | { renderEmptyState: NonNullable< TableBodyProps["renderEmptyState"] >; } )) ); export type ColumnConfig = Omit & { name: ReactNode; id: T; fill?: boolean | undefined; sticky?: boolean | undefined; alignment?: Alignment | undefined; width?: number | undefined; } & ( | { loadingSkeleton?: ReactNode } | { loadingSkeletonWidth?: number | undefined } ); type Alignment = "left" | "center" | "right" | undefined; export type RowConfig = Omit< RowProps, "columns" | "children" | "value" > & { id: string | number; data: Record; }; export const Table = ({ className, fill, rounded, label, rows, columns, isLoading, isUpdating, dependencies, headerCellClassName, stickyHeader, ...props }: TableProps) => (
{isUpdating && (
)} {props.hideHeadersInEmptyState === true && rows?.length === 0 ? ( <> {"renderEmptyState" in props ? props.renderEmptyState({ isEmpty: true, isDropTarget: false }) : props.emptyState} ) : ( {(column: ColumnConfig) => ( {({ allowsSorting, sort, sortDirection }) => ( <>
{column.name}
{allowsSorting && ( )}
)} )} props.emptyState, })} > {isLoading ? ( {(column: ColumnConfig) => ( {"loadingSkeleton" in column ? ( column.loadingSkeleton ) : ( )} )} ) : ( ({ className: rowClassName, data, ...row }: RowConfig) => ( {(column: ColumnConfig) => ( {data[column.id]} )} ) )} )}
); const cellProps = ( { className, alignment, width, fill, sticky, }: Pick< ColumnConfig, "alignment" | "width" | "fill" | "sticky" | "className" >, extraClassName?: string | undefined, extraStyle?: CSSProperties, ) => ({ className: clsx(styles.cell, extraClassName, className), "data-alignment": alignment ?? "left", "data-fill": fill ? "" : undefined, "data-sticky": sticky ? "" : undefined, style: { ...extraStyle, ...(width && ({ "--width": width } as CSSProperties)), }, });