/**
* External dependencies
*/
import { noop } from 'lodash';
import classnames from 'classnames';
import { speak } from '@wordpress/a11y';
import {
RawHTML,
useEffect,
forwardRef,
renderToString,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import warning from '@wordpress/warning';
import { Button } from '@wordpress/components';
const NOTICE_TIMEOUT = 10000;
/** @typedef {import('@wordpress/element').WPElement} WPElement */
/**
* Custom hook which announces the message with the given politeness, if a
* valid message is provided.
*
* @param {string|WPElement} [message] Message to announce.
* @param {'polite'|'assertive'} politeness Politeness to announce.
*/
function useSpokenMessage( message, politeness ) {
const spokenMessage =
typeof message === 'string' ? message : renderToString( message );
useEffect( () => {
if ( spokenMessage ) {
speak( spokenMessage, politeness );
}
}, [ spokenMessage, politeness ] );
}
function Snackbar(
{
className,
children,
spokenMessage = children,
politeness = 'polite',
actions = [],
onRemove = noop,
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 = null,
__unstableHTML = false,
},
ref
) {
onDismiss = onDismiss || noop;
function dismissMe( event ) {
if ( event && event.preventDefault ) {
event.preventDefault();
}
onDismiss();
onRemove();
}
function onActionClick( event, onClick ) {
event.stopPropagation();
onRemove();
if ( onClick ) {
onClick( event );
}
}
useSpokenMessage( spokenMessage, politeness );
// Only set up the timeout dismiss if we're not explicitly dismissing.
useEffect( () => {
const timeoutHandle = setTimeout( () => {
if ( ! explicitDismiss ) {
onDismiss();
onRemove();
}
}, NOTICE_TIMEOUT );
return () => clearTimeout( timeoutHandle );
}, [ explicitDismiss, onDismiss, onRemove ] );
const classes = classnames( className, 'components-snackbar', {
'components-snackbar-explicit-dismiss': !! explicitDismiss,
} );
if ( actions && actions.length > 1 ) {
// we need to inform developers that snackbar only accepts 1 action
warning(
'Snackbar can only have 1 action, use Notice if your message require many messages'
);
// return first element only while keeping it inside an array
actions = [ actions[ 0 ] ];
}
const snackbarContentClassnames = classnames(
'components-snackbar__content',
{
'components-snackbar__content-with-icon': !! icon,
}
);
if ( __unstableHTML === true ) {
children =