import { AccessorFnColumnDef, ColumnDef, DisplayColumnDef, } from "@tanstack/react-table"; import * as React from "react"; import { SortIcon } from "../../icons"; import { useCollection, useShallowRender, type BaseCollection, type Node, } from "../Collection"; import { Checkbox, DataTable as DataTableInner } from "./DataTableImpl"; interface DataTableProps extends React.ComponentProps<"div"> { "data-id": string; data: TData[]; children?: React.ReactNode; __length?: number; searchTerm?: string; initialPageSize?: number; } const EMPTY_DATA = []; export function DataTable({ data = [], children, __length, ...props }: DataTableProps) { const { portal, collection } = useCollection({ children }); return ( <> {portal} ); } type DataTableComponentProps = DataTableProps & { collection: BaseCollection; "data-id": string; data: TData[]; searchTerm?: string; }; function DataTableComponent({ data, collection, ...props }: DataTableComponentProps) { const selectAbleRef = React.useRef(false); const cache = React.useMemo( () => new WeakMap, ColumnDef>(), [], ); const columns = React.useMemo(() => { selectAbleRef.current = false; const columnDefs: Array & { className?: string }> = []; for (const node of collection) { let columnDef = cache.get(node); if (!columnDef) { switch (node.type) { case "value": columnDef = { id: node.props.header, accessorFn: node.props.accessorFn, meta: { className: node.props.className, }, header: node.props.enableSorting === false ? node.props.header : ({ column }) => ( ), cell: ({ row: { original } }) => node.props.children?.(original), }; break; case "display": columnDef = { id: node.props.header, meta: { className: node.props.className, }, accessorFn: node.props.accessorFn, header: node.props.header, cell: ({ row: { original } }) => node.props.children?.(original), }; break; case "checkbox": selectAbleRef.current = true; columnDef = { id: node.props.id, header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value) } aria-label="Select all" /> ), cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="Select row" /> ), enableSorting: false, enableHiding: false, }; break; default: console.log("unknown child node", node); break; } if (columnDef) { cache.set(node, columnDef); } } if (columnDef) { columnDefs.push(columnDef); } } return columnDefs; }, [collection, cache]); return ( ); } type ValueProps = Omit< AccessorFnColumnDef, "cell" > & { children: (origional: TData) => React.ReactNode; className?: string; }; function ValueColumn( props: ValueProps & { ref?: React.ForwardedRef; }, ) { return useShallowRender("value", props, props.ref!); } DataTable.ValueColumn = ValueColumn; type DisplayProps = Omit< DisplayColumnDef, "cell" > & { children: (origional: TData) => React.ReactNode; className?: string; }; function DisplayColumn( props: DisplayProps & { ref?: React.ForwardedRef; }, ) { return useShallowRender("display", props, props.ref!); } DataTable.DisplayColumn = DisplayColumn; function CheckboxColumn(props: { id: string; className?: string; ref?: React.ForwardedRef; }) { return useShallowRender("checkbox", props, props.ref!); } DataTable.CheckboxColumn = CheckboxColumn;