117 lines
3.7 KiB
TypeScript
117 lines
3.7 KiB
TypeScript
import { MoreVerticalIcon } from "~/components/ui/icons/vendor";
|
|
import { Button } from "../button";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "../dropdown-menu";
|
|
import { Link } from "react-router";
|
|
import { Fragment } from "react/jsx-runtime";
|
|
import { cn } from "~/lib/utils";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
interface Props {
|
|
title?: string;
|
|
items: {
|
|
name: "separator" | React.ReactNode | (string & {});
|
|
href?: string;
|
|
target?: string;
|
|
onClick?: () => void;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
hidden?: boolean;
|
|
}[];
|
|
size?: "xs" | "sm" | "lg";
|
|
children?: React.ReactNode;
|
|
className?: string;
|
|
classMenuContent?: string;
|
|
variant?: "default" | "ghost" | "outline";
|
|
ariaLabel?: string;
|
|
}
|
|
export default function DropdownDots({ title, items, size = "sm", children, className, classMenuContent, variant = "ghost", ariaLabel }: Props) {
|
|
const { t } = useTranslation();
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger
|
|
asChild
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
}}
|
|
>
|
|
<Button type="button" variant={variant} size={size} className={className} aria-label={ariaLabel ?? (children ? undefined : t("shared.openMenu"))}>
|
|
{children ? (
|
|
children
|
|
) : (
|
|
<MoreVerticalIcon
|
|
className="opacity-90"
|
|
size={cn(
|
|
size === "xs" && 12,
|
|
size === "sm" && 16,
|
|
size === "lg" && 20
|
|
//
|
|
)}
|
|
/>
|
|
)}
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent className={cn("max-w-44", classMenuContent)}>
|
|
{title && (
|
|
<Fragment>
|
|
<DropdownMenuLabel>{title}</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
</Fragment>
|
|
)}
|
|
<DropdownMenuGroup>
|
|
{items
|
|
.filter((item) => !item.hidden)
|
|
.map((item, idx) => (
|
|
<Fragment key={idx}>
|
|
{item.name === "separator" ? (
|
|
<DropdownMenuSeparator />
|
|
) : (
|
|
<DropdownMenuItem key={idx} asChild>
|
|
{item.href && !item.disabled ? (
|
|
<Link
|
|
to={item.href}
|
|
className={item.className}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
}}
|
|
target={item.target}
|
|
>
|
|
{item.name}
|
|
</Link>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
className={cn("w-full", item.disabled && "cursor-not-allowed opacity-50", item.className)}
|
|
disabled={item.disabled}
|
|
aria-disabled={item.disabled || undefined}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
if (item.onClick) {
|
|
item.onClick();
|
|
}
|
|
}}
|
|
>
|
|
{item.name}
|
|
</button>
|
|
)}
|
|
</DropdownMenuItem>
|
|
)}
|
|
</Fragment>
|
|
))}
|
|
</DropdownMenuGroup>
|
|
{/* <DropdownMenuSeparator />
|
|
<DropdownMenuItem className="text-red-600" onClick={() => deleteItem(item.id)}>
|
|
Delete
|
|
</DropdownMenuItem> */}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|