UNPKG

@wordpress/block-library

Version:
224 lines (207 loc) 5.74 kB
/** * External dependencies */ import classnames from 'classnames'; /** * WordPress dependencies */ import { getBlobByURL, isBlobURL } from '@wordpress/blob'; import { Disabled, PanelBody, SelectControl, Spinner, ToggleControl, } from '@wordpress/components'; import { BlockControls, BlockIcon, InspectorControls, MediaPlaceholder, MediaReplaceFlow, RichText, useBlockProps, store as blockEditorStore, __experimentalGetElementClassName, } from '@wordpress/block-editor'; import { useEffect } from '@wordpress/element'; import { __, _x } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; import { audio as icon } from '@wordpress/icons'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ import { createUpgradedEmbedBlock } from '../embed/util'; const ALLOWED_MEDIA_TYPES = [ 'audio' ]; function AudioEdit( { attributes, className, setAttributes, onReplace, isSelected, insertBlocksAfter, } ) { const { id, autoplay, caption, loop, preload, src } = attributes; const isTemporaryAudio = ! id && isBlobURL( src ); const mediaUpload = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); return getSettings().mediaUpload; }, [] ); useEffect( () => { if ( ! id && isBlobURL( src ) ) { const file = getBlobByURL( src ); if ( file ) { mediaUpload( { filesList: [ file ], onFileChange: ( [ media ] ) => onSelectAudio( media ), onError: ( e ) => onUploadError( e ), allowedTypes: ALLOWED_MEDIA_TYPES, } ); } } }, [] ); function toggleAttribute( attribute ) { return ( newValue ) => { setAttributes( { [ attribute ]: newValue } ); }; } function onSelectURL( newSrc ) { // Set the block's src from the edit component's state, and switch off // the editing UI. if ( newSrc !== src ) { // Check if there's an embed block that handles this URL. const embedBlock = createUpgradedEmbedBlock( { attributes: { url: newSrc }, } ); if ( undefined !== embedBlock && onReplace ) { onReplace( embedBlock ); return; } setAttributes( { src: newSrc, id: undefined } ); } } const { createErrorNotice } = useDispatch( noticesStore ); function onUploadError( message ) { createErrorNotice( message, { type: 'snackbar' } ); } function getAutoplayHelp( checked ) { return checked ? __( 'Autoplay may cause usability issues for some users.' ) : null; } function onSelectAudio( media ) { if ( ! media || ! media.url ) { // In this case there was an error and we should continue in the editing state // previous attributes should be removed because they may be temporary blob urls. setAttributes( { src: undefined, id: undefined } ); return; } // Sets the block's attribute and updates the edit component from the // selected media, then switches off the editing UI. setAttributes( { src: media.url, id: media.id } ); } const classes = classnames( className, { 'is-transient': isTemporaryAudio, } ); const blockProps = useBlockProps( { className: classes, } ); if ( ! src ) { return ( <div { ...blockProps }> <MediaPlaceholder icon={ <BlockIcon icon={ icon } /> } onSelect={ onSelectAudio } onSelectURL={ onSelectURL } accept="audio/*" allowedTypes={ ALLOWED_MEDIA_TYPES } value={ attributes } onError={ onUploadError } /> </div> ); } return ( <> <BlockControls group="other"> <MediaReplaceFlow mediaId={ id } mediaURL={ src } allowedTypes={ ALLOWED_MEDIA_TYPES } accept="audio/*" onSelect={ onSelectAudio } onSelectURL={ onSelectURL } onError={ onUploadError } /> </BlockControls> <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <ToggleControl label={ __( 'Autoplay' ) } onChange={ toggleAttribute( 'autoplay' ) } checked={ autoplay } help={ getAutoplayHelp } /> <ToggleControl label={ __( 'Loop' ) } onChange={ toggleAttribute( 'loop' ) } checked={ loop } /> <SelectControl label={ _x( 'Preload', 'noun; Audio block parameter' ) } value={ preload || '' } // `undefined` is required for the preload attribute to be unset. onChange={ ( value ) => setAttributes( { preload: value || undefined, } ) } options={ [ { value: '', label: __( 'Browser default' ) }, { value: 'auto', label: __( 'Auto' ) }, { value: 'metadata', label: __( 'Metadata' ) }, { value: 'none', label: _x( 'None', 'Preload value' ), }, ] } /> </PanelBody> </InspectorControls> <figure { ...blockProps }> { /* Disable the audio tag if the block is not selected so the user clicking on it won't play the file or change the position slider when the controls are enabled. */ } <Disabled isDisabled={ ! isSelected }> <audio controls="controls" src={ src } /> </Disabled> { isTemporaryAudio && <Spinner /> } { ( ! RichText.isEmpty( caption ) || isSelected ) && ( <RichText tagName="figcaption" className={ __experimentalGetElementClassName( 'caption' ) } aria-label={ __( 'Audio caption text' ) } placeholder={ __( 'Add caption' ) } value={ caption } onChange={ ( value ) => setAttributes( { caption: value } ) } inlineToolbar __unstableOnSplitAtEnd={ () => insertBlocksAfter( createBlock( getDefaultBlockName() ) ) } /> ) } </figure> </> ); } export default AudioEdit;