PettyUI/packages/core/src/components/data-table/data-table-header-cell.tsx
2026-03-29 21:17:56 +07:00

47 lines
1.6 KiB
TypeScript

// packages/core/src/components/data-table/data-table-header-cell.tsx
import type { JSX } from "solid-js";
import { Show } from "solid-js";
import { useInternalDataTableContext } from "./data-table-context";
export interface DataTableHeaderCellProps {
columnId: string;
header: string;
sortable?: boolean;
}
/** Maps the current sort state to an aria-sort attribute value. */
function toAriaSort(direction: string): JSX.AriaAttributes["aria-sort"] {
if (direction === "asc") return "ascending";
if (direction === "desc") return "descending";
return "none";
}
/**
* Renders a single `<th>` column header.
* When the column is sortable, clicking toggles sort asc → desc → none
* and the appropriate aria-sort attribute and visual indicator are applied.
*/
export function DataTableHeaderCell(props: DataTableHeaderCellProps): JSX.Element {
const ctx = useInternalDataTableContext();
const isActive = () => ctx.sortColumnId() === props.columnId;
const direction = () => (isActive() ? ctx.sortDirection() : "none");
function handleClick(): void {
if (props.sortable) ctx.toggleSort(props.columnId);
}
return (
<th
aria-sort={props.sortable ? toAriaSort(direction()) : undefined}
onClick={handleClick}
style={{ cursor: props.sortable ? "pointer" : undefined }}
data-sort-direction={isActive() ? direction() : undefined}
>
{props.header}
<Show when={props.sortable && isActive() && direction() === "asc"}> </Show>
<Show when={props.sortable && isActive() && direction() === "desc"}> </Show>
</th>
);
}