"use client"; import * as React from "react"; import { cn } from "@/lib/utils"; /** * The panel's data table. * * From md up it's an ordinary table. Below xl, long values (emails, URLs) * may wrap anywhere so the columns fit a tablet; if they still can't, the * table scrolls sideways inside its card as a last resort. * * On a phone (below md) each row becomes a stacked card: one line per cell, labelled * with its column heading. The labels are read from the table's own s * and stamped onto the cells as `data-label`, so pages need no extra markup * — every table in the panel gets the card layout for free. Cells under an * empty heading (an actions column) simply go unlabelled. */ export function Table({ children }: { children: React.ReactNode }) { const ref = React.useRef(null); // Runs after every render: rows arrive and change with the data. React.useLayoutEffect(() => { const table = ref.current; if (!table) return; const heads = Array.from(table.querySelectorAll("thead th")).map( (th) => th.textContent?.trim() ?? "", ); table.querySelectorAll("tbody tr").forEach((tr) => { let col = 0; Array.from(tr.children).forEach((cell) => { const td = cell as HTMLTableCellElement; const label = td.colSpan > 1 ? "" : (heads[col] ?? ""); if (label) td.dataset.label = label; else delete td.dataset.label; col += td.colSpan || 1; }); }); }); return (
{children}
); } export function THead({ children }: { children: React.ReactNode }) { return ( {children} ); } export function TH({ children, className, }: { children?: React.ReactNode; className?: string; }) { return ( {children} ); } export function TR({ children, className, }: { children: React.ReactNode; className?: string; }) { return ( {children} ); } export function TD({ children, className, }: { children?: React.ReactNode; className?: string; }) { return ( {children} ); }