"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 (
);
}
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}
|
);
}
|