/* Copyright 2026 Marimo. All rights reserved. */ "use no memo"; import type { Column, Table } from "@tanstack/react-table"; import { EllipsisIcon, FilterIcon, ListFilterIcon } from "lucide-react"; import { useLocale } from "react-aria"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import type { CalculateTopKRows } from "@/plugins/impl/DataTablePlugin"; import { cn } from "@/utils/cn"; import { useFilterEditor } from "./filter-editor-context"; import { EDITABLE_FILTER_TYPES, isMembershipFilterType } from "./filters"; import { ClearFilterMenuItem, ColumnPinning, ColumnWrapping, CopyColumn, DataType, FormatOptions, HideColumn, renderSortIcon, Sorts, } from "./header-items"; interface DataTableColumnHeaderProps< TData, TValue, > extends React.HTMLAttributes { column: Column; header: React.ReactNode; subheader?: React.ReactNode; justify?: "left" | "center" | "right"; calculateTopKRows?: CalculateTopKRows; /** * Optional: only used to surface multi-column sort actions ("Clear all * sorts"). Omitted by call sites that define their header inside column * definitions, where the table instance isn't yet available. */ table?: Table; } export const DataTableColumnHeader = ({ column, header, subheader, justify, className, table, }: DataTableColumnHeaderProps) => { const { locale } = useLocale(); const editor = useFilterEditor(); // No header if (!header) { return null; } // No sorting or filtering if (!column.getCanSort() && !column.getCanFilter()) { return (
{header} {subheader}
); } const hasFilter = column.getFilterValue() !== undefined; const filterType = column.columnDef.meta?.filterType; const canEditFilter = editor !== null && column.getCanFilter() && filterType !== undefined && EDITABLE_FILTER_TYPES.has(filterType); const canFilterByValues = canEditFilter && filterType !== undefined && isMembershipFilterType(filterType); return (
{justify === "center" ? ( <> {column.getCanSort() && } {hasFilter && } {header} ) : ( <> {header} {hasFilter && } {column.getCanSort() && } )} {canEditFilter && } {canEditFilter && ( editor.requestAddFilter({ columnId: column.id }) } > Filter )} {canFilterByValues && ( editor.requestAddFilter({ columnId: column.id, operator: "in", }) } > Filter by values )} {hasFilter && }
{subheader}
); }; const FilterIndicator = () => ( ); const SortButton = ({ column, }: { column: Column; }) => { const sortDirection = column.getIsSorted(); const handleClick = (e: React.MouseEvent) => { e.stopPropagation(); if (!sortDirection) { column.toggleSorting(false, true); // asc } else if (sortDirection === "asc") { column.toggleSorting(true, true); // desc } else { column.clearSorting(); } }; return ( ); };