forked from zhongyidian/robot-shanghai
Initial commit
This commit is contained in:
commit
6b1e803320
158 files changed
+16461
No files matched your search
@@ -0,0 +1,98 @@
|
||||
import type { CSSProperties, MouseEvent } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { Portal } from "@/components/ui/portal";
|
||||
import { cn } from "@/lib/cn";
|
||||
import styles from "./Overlay.module.css";
|
||||
import type { OverlayProps } from "./Overlay.types";
|
||||
|
||||
export function Overlay({
|
||||
open,
|
||||
children,
|
||||
variant = "dim",
|
||||
backgroundImage,
|
||||
backgroundClassName,
|
||||
closeOnBackgroundClick = true,
|
||||
closeOnEscape = true,
|
||||
lockScroll = true,
|
||||
onClose,
|
||||
container,
|
||||
disabledPortal = false,
|
||||
className,
|
||||
contentClassName,
|
||||
fixed,
|
||||
...props
|
||||
}: OverlayProps) {
|
||||
const isFixed = fixed ?? container == null;
|
||||
useEffect(() => {
|
||||
if (!open || !closeOnEscape) {
|
||||
return;
|
||||
}
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") {
|
||||
onClose?.();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [closeOnEscape, onClose, open]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !lockScroll || typeof document === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = "hidden";
|
||||
|
||||
return () => {
|
||||
document.body.style.overflow = previousOverflow;
|
||||
};
|
||||
}, [lockScroll, open]);
|
||||
|
||||
if (!open) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const backgroundImageStyle: CSSProperties | undefined = backgroundImage
|
||||
? { backgroundImage }
|
||||
: undefined;
|
||||
|
||||
const handleBackgroundClick = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
event.currentTarget.blur();
|
||||
onClose?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<Portal container={container} disabled={disabledPortal}>
|
||||
<div
|
||||
className={cn(
|
||||
styles.overlay,
|
||||
isFixed ? styles.fixed : styles.absolute,
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="关闭弹层背景"
|
||||
className={cn(
|
||||
styles.background,
|
||||
styles[variant],
|
||||
backgroundClassName,
|
||||
)}
|
||||
disabled={!closeOnBackgroundClick}
|
||||
style={backgroundImageStyle}
|
||||
onClick={handleBackgroundClick}
|
||||
/>
|
||||
<div className={cn(styles.content, contentClassName)}>
|
||||
<div className={styles.contentInner}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Portal>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user