UNPKG

@wordpress/components

Version:
129 lines (128 loc) 4.12 kB
// packages/components/src/snackbar/index.tsx import clsx from "clsx"; import { speak } from "@wordpress/a11y"; import { useEffect, useLayoutEffect, useRef, forwardRef, renderToString } from "@wordpress/element"; import { __ } from "@wordpress/i18n"; import warning from "@wordpress/warning"; import Button from "../button"; import ExternalLink from "../external-link"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; var NOTICE_TIMEOUT = 6e3; function useSpokenMessage(message, politeness) { const spokenMessage = typeof message === "string" ? message : renderToString(message); useEffect(() => { if (spokenMessage) { speak(spokenMessage, politeness); } }, [spokenMessage, politeness]); } function UnforwardedSnackbar({ className, children, spokenMessage = children, politeness = "polite", actions = [], onRemove, icon = null, explicitDismiss = false, // onDismiss is a callback executed when the snackbar is dismissed. // It is distinct from onRemove, which _looks_ like a callback but is // actually the function to call to remove the snackbar from the UI. onDismiss, listRef }, ref) { function dismissMe(event) { if (event && event.preventDefault) { event.preventDefault(); } listRef?.current?.focus(); onDismiss?.(); onRemove?.(); } function onActionClick(event, onClick) { event.stopPropagation(); onRemove?.(); if (onClick) { onClick(event); } } useSpokenMessage(spokenMessage, politeness); const callbacksRef = useRef({ onDismiss, onRemove }); useLayoutEffect(() => { callbacksRef.current = { onDismiss, onRemove }; }); useEffect(() => { const timeoutHandle = setTimeout(() => { if (!explicitDismiss) { callbacksRef.current.onDismiss?.(); callbacksRef.current.onRemove?.(); } }, NOTICE_TIMEOUT); return () => clearTimeout(timeoutHandle); }, [explicitDismiss]); const classes = clsx(className, "components-snackbar", { "components-snackbar-explicit-dismiss": !!explicitDismiss }); if (actions && actions.length > 1) { globalThis.SCRIPT_DEBUG === true ? warning("Snackbar can only have one action. Use Notice if your message requires many actions.") : void 0; actions = [actions[0]]; } const snackbarContentClassnames = clsx("components-snackbar__content", { "components-snackbar__content-with-icon": !!icon }); return /* @__PURE__ */ _jsx("div", { ref, className: classes, onClick: !explicitDismiss ? dismissMe : void 0, tabIndex: 0, role: !explicitDismiss ? "button" : void 0, onKeyPress: !explicitDismiss ? dismissMe : void 0, "aria-label": !explicitDismiss ? __("Dismiss this notice") : void 0, "data-testid": "snackbar", children: /* @__PURE__ */ _jsxs("div", { className: snackbarContentClassnames, children: [icon && /* @__PURE__ */ _jsx("div", { className: "components-snackbar__icon", children: icon }), children, actions.map(({ label, onClick, url, openInNewTab = false }, index) => url !== void 0 && openInNewTab ? /* @__PURE__ */ _jsx(ExternalLink, { href: url, onClick: (event) => onActionClick(event, onClick), className: "components-snackbar__action", children: label }, index) : /* @__PURE__ */ _jsx(Button, { __next40pxDefaultSize: true, href: url, variant: "link", onClick: (event) => onActionClick(event, onClick), className: "components-snackbar__action", children: label }, index)), explicitDismiss && /* @__PURE__ */ _jsx("span", { role: "button", "aria-label": __("Dismiss this notice"), tabIndex: 0, className: "components-snackbar__dismiss-button", onClick: dismissMe, onKeyPress: dismissMe, children: "\u2715" })] }) }); } var Snackbar = forwardRef(UnforwardedSnackbar); var snackbar_default = Snackbar; export { Snackbar, snackbar_default as default }; //# sourceMappingURL=index.js.map