Files
controller-v2/client/src/components/FeatureGate.tsx
T

84 lines
2.2 KiB
TypeScript
Raw Normal View History

import { useState, type ReactNode, type SyntheticEvent } from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { cn } from "@/lib/utils";
export type FeatureGateLabels = {
title: string;
description: string;
cancel: string;
confirm: string;
};
type FeatureGateProps = {
enabled: boolean;
labels: FeatureGateLabels;
onEnable: () => void | Promise<void>;
className?: string;
children: ReactNode;
};
/** 功能关闭时拦截子区域交互,提示是否开启总开关 */
export function FeatureGate({
enabled,
labels,
onEnable,
className,
children,
}: FeatureGateProps) {
const [open, setOpen] = useState(false);
const intercept = (e: SyntheticEvent) => {
if (enabled) return;
e.preventDefault();
e.stopPropagation();
setOpen(true);
};
const handleConfirm = () => {
void Promise.resolve(onEnable()).then(() => setOpen(false));
};
return (
<>
<div
className={cn(className)}
onPointerDownCapture={intercept}
onClickCapture={intercept}
>
{children}
</div>
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogContent className="border-white/10 bg-zinc-900 text-white sm:max-w-md">
<AlertDialogHeader>
<AlertDialogTitle className="text-white">{labels.title}</AlertDialogTitle>
<AlertDialogDescription className="text-white/60">
{labels.description}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel className="border-white/20 bg-transparent text-white hover:bg-white/10">
{labels.cancel}
</AlertDialogCancel>
<AlertDialogAction
className="bg-[#00FFF6] text-black hover:brightness-95 focus-visible:ring-[#00FFF6]"
onClick={handleConfirm}
>
{labels.confirm}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
}