74 lines
2.7 KiB
TypeScript
74 lines
2.7 KiB
TypeScript
import { useTranslation } from "@repo/rdx-ui/locales/i18n.ts";
|
|
import {
|
|
Button,
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuShortcut,
|
|
DropdownMenuTrigger,
|
|
} from "@repo/shadcn-ui/components";
|
|
import { CellContext } from "@tanstack/react-table";
|
|
import { MoreVerticalIcon } from "lucide-react";
|
|
import { ReactElement } from "react";
|
|
|
|
export type DataTablaRowActionFunction<TData> = (
|
|
props: CellContext<TData, unknown>
|
|
) => DataTableRowActionDefinition<TData>[];
|
|
|
|
export type DataTableRowActionDefinition<TData> = {
|
|
label: string | "-";
|
|
icon?: ReactElement<any, any>;
|
|
shortcut?: string;
|
|
onClick?: (props: CellContext<TData, unknown>, e: React.BaseSyntheticEvent) => void;
|
|
};
|
|
|
|
export type DataTableRowActionsProps<TData, _TValue = unknown> = {
|
|
className?: string;
|
|
actions?: DataTablaRowActionFunction<TData>;
|
|
rowContext: CellContext<TData, unknown>;
|
|
};
|
|
|
|
export function DataTableRowActions<TData = any, TValue = unknown>({
|
|
actions,
|
|
rowContext,
|
|
}: DataTableRowActionsProps<TData, TValue>) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button size='icon' variant='outline' className='w-8 h-8'>
|
|
<MoreVerticalIcon className='h-3.5 w-3.5' />
|
|
<span className='sr-only'>{t("common.open_menu")}</span>
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
|
|
<DropdownMenuContent align='end'>
|
|
<DropdownMenuLabel>{t("common.actions")} </DropdownMenuLabel>
|
|
{actions &&
|
|
actions(rowContext).map((action, index) => {
|
|
// Use a more stable key: for separators, combine 'separator' and index; for items, use label and index
|
|
if (action.label === "-") {
|
|
// Use a more stable key by combining a static string and the previous/next action label if possible
|
|
const prevLabel = actions(rowContext)[index - 1]?.label ?? "start";
|
|
const nextLabel = actions(rowContext)[index + 1]?.label ?? "end";
|
|
return <DropdownMenuSeparator key={`separator-${prevLabel}-${nextLabel}`} />;
|
|
}
|
|
return (
|
|
<DropdownMenuItem
|
|
key={`action-${typeof action.label === "string" ? action.label : "item"}-${index}`}
|
|
onClick={(event) => (action.onClick ? action.onClick(rowContext, event) : null)}
|
|
>
|
|
{action.icon && <>{action.icon}</>}
|
|
{action.label}
|
|
{action.shortcut && <DropdownMenuShortcut>{action.shortcut}</DropdownMenuShortcut>}
|
|
</DropdownMenuItem>
|
|
);
|
|
})}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|