snapshot of https://github.com/excalidraw/excalidraw.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Tests / test (push) Failing after 15s
Some checks failed
Tests / test (push) Failing after 15s
This commit is contained in:
80
packages/excalidraw/components/Toast.tsx
Normal file
80
packages/excalidraw/components/Toast.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
|
||||
import { CloseIcon } from "./icons";
|
||||
import { IconButton } from "./IconButton";
|
||||
|
||||
import "./Toast.scss";
|
||||
|
||||
import type { CSSProperties, ReactNode } from "react";
|
||||
|
||||
const DEFAULT_TOAST_TIMEOUT = 5000;
|
||||
|
||||
const ProgressBar = ({ progress }: { progress: number }) => (
|
||||
<div className="Toast__progress-bar">
|
||||
<div
|
||||
className="Toast__progress-bar-fill"
|
||||
style={{
|
||||
width: `${Math.min(5, Math.round(progress * 100))}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const ToastComponent = ({
|
||||
message,
|
||||
onClose,
|
||||
closable = false,
|
||||
// To prevent autoclose, pass duration as Infinity
|
||||
duration = DEFAULT_TOAST_TIMEOUT,
|
||||
style,
|
||||
}: {
|
||||
message: ReactNode;
|
||||
onClose: () => void;
|
||||
closable?: boolean;
|
||||
duration?: number;
|
||||
style?: CSSProperties;
|
||||
}) => {
|
||||
const timerRef = useRef<number>(0);
|
||||
const shouldAutoClose = duration !== Infinity;
|
||||
const scheduleTimeout = useCallback(() => {
|
||||
if (!shouldAutoClose) {
|
||||
return;
|
||||
}
|
||||
timerRef.current = window.setTimeout(() => onClose(), duration);
|
||||
}, [onClose, duration, shouldAutoClose]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldAutoClose) {
|
||||
return;
|
||||
}
|
||||
scheduleTimeout();
|
||||
return () => clearTimeout(timerRef.current);
|
||||
}, [scheduleTimeout, message, duration, shouldAutoClose]);
|
||||
|
||||
const onMouseEnter = shouldAutoClose
|
||||
? () => clearTimeout(timerRef?.current)
|
||||
: undefined;
|
||||
const onMouseLeave = shouldAutoClose ? scheduleTimeout : undefined;
|
||||
return (
|
||||
<div
|
||||
className="Toast"
|
||||
role="status"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
style={style}
|
||||
>
|
||||
<div className="Toast__message">{message}</div>
|
||||
{closable && (
|
||||
<IconButton
|
||||
icon={CloseIcon}
|
||||
aria-label="close"
|
||||
type="icon"
|
||||
onClick={onClose}
|
||||
className="close"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Toast = Object.assign(ToastComponent, { ProgressBar });
|
||||
Reference in New Issue
Block a user