summaryrefslogtreecommitdiff
path: root/components/data-table/data-table-pin-right.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-04-28 02:13:30 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-04-28 02:13:30 +0000
commitef4c533ebacc2cdc97e518f30e9a9350004fcdfb (patch)
tree345251a3ed0f4429716fa5edaa31024d8f4cb560 /components/data-table/data-table-pin-right.tsx
parent9ceed79cf32c896f8a998399bf1b296506b2cd4a (diff)
~20250428 작업사항
Diffstat (limited to 'components/data-table/data-table-pin-right.tsx')
-rw-r--r--components/data-table/data-table-pin-right.tsx150
1 files changed, 116 insertions, 34 deletions
diff --git a/components/data-table/data-table-pin-right.tsx b/components/data-table/data-table-pin-right.tsx
index 3ed42402..ad52e44d 100644
--- a/components/data-table/data-table-pin-right.tsx
+++ b/components/data-table/data-table-pin-right.tsx
@@ -68,15 +68,48 @@ function areAllSubColumnsPinned<TData>(
}
/**
+ * Helper function to get the display name of a column
+ */
+function getColumnDisplayName<TData>(column: Column<TData>): string {
+ // First try to use excelHeader from meta if available
+ const excelHeader = column.columnDef.meta?.excelHeader
+ if (excelHeader) {
+ return excelHeader
+ }
+
+ // Fall back to converting the column ID to sentence case
+ return toSentenceCase(column.id)
+}
+
+/**
+ * Array of column IDs that should be auto-pinned to the right when available
+ */
+const AUTO_PIN_RIGHT_COLUMNS = ['actions']
+
+/**
* "Pin Right" Popover. Supports pinning both individual columns and header groups.
*/
export function PinRightButton<TData>({ table }: { table: Table<TData> }) {
const [open, setOpen] = React.useState(false)
const triggerRef = React.useRef<HTMLButtonElement>(null)
- // Get all columns that can be pinned, including parent columns
+ // Try to auto-pin actions columns if they exist
+ React.useEffect(() => {
+ AUTO_PIN_RIGHT_COLUMNS.forEach((columnId) => {
+ const column = table.getColumn(columnId)
+ if (column?.getCanPin?.()) {
+ column.pin?.("right")
+ }
+ })
+ }, [table])
+ // Get all columns that can be pinned (excluding auto-pinned columns)
const pinnableColumns = React.useMemo(() => {
return table.getAllColumns().filter((column) => {
+ // Skip auto-pinned columns
+ if (AUTO_PIN_RIGHT_COLUMNS.includes(column.id)) {
+ return false
+ }
+
// If it's a leaf column, check if it can be pinned
if (!isParentColumn(column)) {
return column.getCanPin?.()
@@ -93,6 +126,25 @@ export function PinRightButton<TData>({ table }: { table: Table<TData> }) {
})
}, [table])
+ // Get flat list of all leaf columns for display
+ const allPinnableLeafColumns = React.useMemo(() => {
+ const leafColumns: Column<TData>[] = []
+
+ // Function to recursively collect leaf columns
+ const collectLeafColumns = (column: Column<TData>) => {
+ if (isParentColumn(column)) {
+ column.columns.forEach(collectLeafColumns)
+ } else if (column.getCanPin?.() && !AUTO_PIN_RIGHT_COLUMNS.includes(column.id)) {
+ leafColumns.push(column)
+ }
+ }
+
+ // Process all columns
+ table.getAllColumns().forEach(collectLeafColumns)
+
+ return leafColumns
+ }, [table])
+
// Handle column pinning
const handleColumnPin = React.useCallback((column: Column<TData>) => {
// For parent columns, pin/unpin all subcolumns
@@ -127,7 +179,7 @@ export function PinRightButton<TData>({ table }: { table: Table<TData> }) {
<MoveRight className="size-4" />
<span className="hidden sm:inline">
- Right
+ 오른 고정
</span>
<ChevronsUpDown className="ml-1 size-4 opacity-50 hidden sm:inline" />
</Button>
@@ -140,42 +192,72 @@ export function PinRightButton<TData>({ table }: { table: Table<TData> }) {
>
<Command>
<CommandInput placeholder="Search columns..." />
- <CommandList>
+ <CommandList className="max-h-[300px]">
<CommandEmpty>No columns found.</CommandEmpty>
<CommandGroup>
- {/* Header Columns (Parent Columns) */}
+ {/* Parent Columns with subcolumns */}
{pinnableColumns
.filter(isParentColumn)
- .map((column) => (
- <CommandItem
- key={column.id}
- onSelect={() => {
- handleColumnPin(column)
- }}
- className="font-medium"
- >
- <span className="truncate">
- {column.id === "Basic Info" || column.id === "Metadata"
- ? column.id // Use column ID directly for common groups
- : toSentenceCase(column.id)}
- </span>
- <Check
- className={cn(
- "ml-auto size-4 shrink-0",
- isColumnPinned(column) ? "opacity-100" : "opacity-0"
- )}
- />
- </CommandItem>
+ .map((parentColumn) => (
+ <React.Fragment key={parentColumn.id}>
+ {/* Parent column header - can pin/unpin all children at once */}
+ <CommandItem
+ onSelect={() => {
+ handleColumnPin(parentColumn)
+ }}
+ className="font-medium bg-muted/50"
+ >
+ <span className="truncate">
+ {getColumnDisplayName(parentColumn)}
+ </span>
+ <Check
+ className={cn(
+ "ml-auto size-4 shrink-0",
+ isColumnPinned(parentColumn) ? "opacity-100" : "opacity-0"
+ )}
+ />
+ </CommandItem>
+
+ {/* Individual subcolumns */}
+ {parentColumn.columns
+ .filter(col => !isParentColumn(col) && col.getCanPin?.())
+ .map(subColumn => (
+ <CommandItem
+ key={subColumn.id}
+ onSelect={() => {
+ handleColumnPin(subColumn)
+ }}
+ className="pl-6 text-sm"
+ >
+ <span className="truncate">
+ {getColumnDisplayName(subColumn)}
+ </span>
+ <Check
+ className={cn(
+ "ml-auto size-4 shrink-0",
+ isColumnPinned(subColumn) ? "opacity-100" : "opacity-0"
+ )}
+ />
+ </CommandItem>
+ ))}
+ </React.Fragment>
))}
-
- {pinnableColumns.some(isParentColumn) &&
- pinnableColumns.some(col => !isParentColumn(col)) && (
- <CommandSeparator />
- )}
-
- {/* Leaf Columns (individual columns) */}
- {pinnableColumns
- .filter(col => !isParentColumn(col))
+ </CommandGroup>
+
+ {/* Separator if we have both parent columns and standalone leaf columns */}
+ {pinnableColumns.some(isParentColumn) &&
+ allPinnableLeafColumns.some(col => !pinnableColumns.find(parent =>
+ isParentColumn(parent) && parent.columns.includes(col))
+ ) && (
+ <CommandSeparator />
+ )}
+
+ {/* Standalone leaf columns (not part of any parent column group) */}
+ <CommandGroup>
+ {allPinnableLeafColumns
+ .filter(col => !pinnableColumns.find(parent =>
+ isParentColumn(parent) && parent.columns.includes(col)
+ ))
.map((column) => (
<CommandItem
key={column.id}
@@ -184,7 +266,7 @@ export function PinRightButton<TData>({ table }: { table: Table<TData> }) {
}}
>
<span className="truncate">
- {toSentenceCase(column.id)}
+ {getColumnDisplayName(column)}
</span>
<Check
className={cn(