/* * Copyright 2024 Palantir Technologies, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import classNames from "classnames"; import { forwardRef, useCallback, useEffect, useState } from "react"; import { CrossIcon } from "@blueprintjs/icons"; import { Classes } from "../../common"; import { DISPLAYNAME_PREFIX } from "../../common/props"; import { useTimeout } from "../../hooks/useTimeout"; import { ButtonGroup } from "../button/buttonGroup"; import { AnchorButton, Button } from "../button/buttons"; import { Icon } from "../icon/icon"; import type { ToastProps } from "./toastProps"; /** * Toast component. * * @see https://blueprintjs.com/docs/#core/components/toast */ export const Toast = forwardRef((props, ref) => { const { action, className, icon, intent, isCloseButtonShown = true, message, onDismiss, timeout = 5000 } = props; const [isTimeoutStarted, setIsTimeoutStarted] = useState(false); const startTimeout = useCallback(() => setIsTimeoutStarted(true), []); const clearTimeout = useCallback(() => setIsTimeoutStarted(false), []); // Per docs: "Providing a value less than or equal to 0 will disable the timeout (this is discouraged)." const isTimeoutEnabled = timeout != null && timeout > 0; // timeout is triggered & cancelled by updating `isTimeoutStarted` state useTimeout( () => { triggerDismiss(true); }, isTimeoutStarted && isTimeoutEnabled ? timeout : null, ); // start timeout on mount or change, cancel on unmount useEffect(() => { if (isTimeoutEnabled) { startTimeout(); } else { clearTimeout(); } return clearTimeout; }, [clearTimeout, startTimeout, isTimeoutEnabled, timeout]); const triggerDismiss = useCallback( (didTimeoutExpire: boolean) => { clearTimeout(); onDismiss?.(didTimeoutExpire); }, [clearTimeout, onDismiss], ); const handleCloseClick = useCallback(() => triggerDismiss(false), [triggerDismiss]); const handleActionClick = useCallback( (e: React.MouseEvent) => { action?.onClick?.(e); triggerDismiss(false); }, [action, triggerDismiss], ); return (
{message} {action && } {isCloseButtonShown &&
); }); Toast.displayName = `${DISPLAYNAME_PREFIX}.Toast`; /** @deprecated Use `Toast` instead */ export const Toast2 = Toast; export type Toast2 = typeof Toast;