import { useEffect, type ReactNode } from "react"; import { createPortal } from "react-dom"; import { Shield, X } from "lucide-react"; // 通用媒体预览灯箱:点击图片放大 / 点击视频弹窗播放(复用 .np-lightbox 样式) // 背景点击 / Esc / 关闭键都可关闭;点媒体本身不关闭。 export function MediaLightbox({ open, src, kind, name, close }: { open: boolean; src: string; kind?: "image" | "video"; name?: string; close: () => void; }) { useEffect(() => { if (!open) return; const onKey = (event: KeyboardEvent) => { if (event.key === "Escape") close(); }; document.addEventListener("keydown", onKey); return () => document.removeEventListener("keydown", onKey); }, [open, close]); if (!open || !src) return null; // 挂到 body:脱离 .content(z-index:1)层叠上下文,遮罩才能盖住头部/侧栏 return createPortal(
{kind === "video" ? (
, document.body, ); } export function SettingRow({ title, desc, action, toggle, checked }: { title: string; desc: string; action?: string; toggle?: boolean; checked?: boolean }) { return (
{title}{desc}
{toggle ? : }
); } export function TeamModal({ open, title, subtitle, icon, close, children, footer }: { open: boolean; title: string; subtitle: string; icon: ReactNode; close: () => void; children: ReactNode; footer?: ReactNode; }) { if (!open) return null; // 挂到 body:脱离 .content(z-index:1)层叠上下文,遮罩才能盖住头部/侧栏 return createPortal(
event.stopPropagation()}> ++
{icon}
{title}{subtitle}
{children}
{footer || }
, document.body, ); } export function ConfirmModal({ open, title, detail, confirmText, onCancel, onConfirm }: { open: boolean; title: string; detail: string; confirmText: string; onCancel: () => void; onConfirm: () => void | Promise; }) { if (!open) return null; // 挂到 body:脱离 .content(z-index:1)层叠上下文,遮罩才能盖住头部/侧栏 return createPortal(
event.stopPropagation()}> ++
{title}// CONFIRM
{detail}
, document.body, ); } export function Drawer({ title, open, close, children }: { title: string; open: boolean; close: () => void; children: ReactNode }) { if (!open) return null; // 挂到 body:脱离 .content(z-index:1)层叠上下文,遮罩才能盖住头部/侧栏 return createPortal( <>
, document.body, ); } export function EmptyPanel({ title, action, onAction }: { title: string; action: string; onAction: () => void }) { return

{title}

// 先创建资料后进入下一步

; }