Files
sam-react-prod/src/components/molecules/TableActions.tsx

89 lines
2.6 KiB
TypeScript
Raw Normal View History

"use client";
import { Button } from "@/components/ui/button";
import { LucideIcon, Eye, Edit, Trash2, Copy, Download, MoreHorizontal } from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export interface TableAction {
type: "view" | "edit" | "delete" | "copy" | "download" | "custom";
label?: string;
icon?: LucideIcon;
onClick: () => void;
variant?: "default" | "ghost" | "outline" | "destructive";
hidden?: boolean;
}
interface TableActionsProps {
actions: TableAction[];
layout?: "buttons" | "dropdown" | "auto";
}
const defaultIcons: Record<string, LucideIcon> = {
view: Eye,
edit: Edit,
delete: Trash2,
copy: Copy,
download: Download
};
export const TableActions = ({ actions, layout = "auto" }: TableActionsProps) => {
const visibleActions = actions.filter(a => !a.hidden);
// 자동 레이아웃: 3개 이하는 버튼, 4개 이상은 드롭다운
const useDropdown = layout === "dropdown" || (layout === "auto" && visibleActions.length > 3);
if (visibleActions.length === 0) return null;
// 드롭다운 레이아웃
if (useDropdown) {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm">
<MoreHorizontal className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{visibleActions.map((action, index) => {
const Icon = action.icon || (action.type !== "custom" ? defaultIcons[action.type] : null);
return (
<DropdownMenuItem
key={index}
onClick={action.onClick}
className={action.variant === "destructive" ? "text-destructive" : ""}
>
{Icon && <Icon className="w-4 h-4 mr-2" />}
{action.label || action.type.charAt(0).toUpperCase() + action.type.slice(1)}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
);
}
// 버튼 레이아웃
return (
<div className="flex gap-1">
{visibleActions.map((action, index) => {
const Icon = action.icon || (action.type !== "custom" ? defaultIcons[action.type] : null);
return (
<Button
key={index}
variant={action.variant || "ghost"}
size="sm"
onClick={action.onClick}
title={action.label || action.type}
>
{Icon && <Icon className="w-4 h-4" />}
</Button>
);
})}
</div>
);
};