"use client" import * as React from "react" import { type Column, type Table } from "@tanstack/react-table" import { Check, ChevronsUpDown, MoveRight } from "lucide-react" import { cn, toSentenceCase } from "@/lib/utils" import { Button } from "@/components/ui/button" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@/components/ui/command" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" /** * Helper function to check if a column is a parent column (has subcolumns) */ function isParentColumn(column: Column): boolean { return column.columns && column.columns.length > 0 } /** * Helper function to pin all subcolumns of a parent column */ function pinSubColumns( column: Column, pinType: false | "left" | "right" ): void { // If this is a parent column, pin all its subcolumns if (isParentColumn(column)) { column.columns.forEach((subColumn) => { // Recursively handle nested columns pinSubColumns(subColumn, pinType) }) } else { // For leaf columns, apply the pin if possible if (column.getCanPin?.()) { column.pin?.(pinType) } } } /** * Checks if all subcolumns of a parent column are pinned to the specified side */ function areAllSubColumnsPinned( column: Column, pinType: "left" | "right" ): boolean { if (isParentColumn(column)) { // Check if all subcolumns are pinned return column.columns.every((subColumn) => areAllSubColumnsPinned(subColumn, pinType) ) } else { // For leaf columns, check if it's pinned to the specified side return column.getIsPinned?.() === pinType } } /** * "Pin Right" Popover. Supports pinning both individual columns and header groups. */ export function PinRightButton({ table }: { table: Table }) { const [open, setOpen] = React.useState(false) const triggerRef = React.useRef(null) // Get all columns that can be pinned, including parent columns const pinnableColumns = React.useMemo(() => { return table.getAllColumns().filter((column) => { // If it's a leaf column, check if it can be pinned if (!isParentColumn(column)) { return column.getCanPin?.() } // If it's a parent column, check if at least one subcolumn can be pinned return column.columns.some((subCol) => { if (isParentColumn(subCol)) { // Recursively check nested columns return subCol.columns.some(c => c.getCanPin?.()) } return subCol.getCanPin?.() }) }) }, [table]) // Handle column pinning const handleColumnPin = React.useCallback((column: Column) => { // For parent columns, pin/unpin all subcolumns if (isParentColumn(column)) { const allPinned = areAllSubColumnsPinned(column, "right") pinSubColumns(column, allPinned ? false : "right") } else { // For leaf columns, toggle pin state const isPinned = column.getIsPinned?.() === "right" column.pin?.(isPinned ? false : "right") } }, []) // Check if a column or its subcolumns are pinned right const isColumnPinned = React.useCallback((column: Column): boolean => { if (isParentColumn(column)) { return areAllSubColumnsPinned(column, "right") } else { return column.getIsPinned?.() === "right" } }, []) return ( triggerRef.current?.focus()} > No columns found. {/* Header Columns (Parent Columns) */} {pinnableColumns .filter(isParentColumn) .map((column) => ( { handleColumnPin(column) }} className="font-medium" > {column.id === "Basic Info" || column.id === "Metadata" ? column.id // Use column ID directly for common groups : toSentenceCase(column.id)} ))} {pinnableColumns.some(isParentColumn) && pinnableColumns.some(col => !isParentColumn(col)) && ( )} {/* Leaf Columns (individual columns) */} {pinnableColumns .filter(col => !isParentColumn(col)) .map((column) => ( { handleColumnPin(column) }} > {toSentenceCase(column.id)} ))} ) }