UNPKG

@wordpress/block-editor

Version:
224 lines (202 loc) 6.27 kB
import { createElement, Fragment } from "@wordpress/element"; /** * External dependencies */ import classnames from 'classnames'; /** * WordPress dependencies */ import { useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { speak } from '@wordpress/a11y'; import { FormFileUpload, NavigableMenu, MenuItem, ToolbarButton, Dropdown, withFilters, Tooltip } from '@wordpress/components'; import { useSelect, withDispatch } from '@wordpress/data'; import { DOWN } from '@wordpress/keycodes'; import { postFeaturedImage, upload, media as mediaIcon } from '@wordpress/icons'; import { compose } from '@wordpress/compose'; import { __unstableStripHTML as stripHTML } from '@wordpress/dom'; import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ import MediaUpload from '../media-upload'; import MediaUploadCheck from '../media-upload/check'; import LinkControl from '../link-control'; import { store as blockEditorStore } from '../../store'; const noop = () => {}; let uniqueId = 0; const MediaReplaceFlow = ({ mediaURL, mediaId, mediaIds, allowedTypes, accept, onError, onSelect, onSelectURL, onToggleFeaturedImage, useFeaturedImage, onFilesUpload = noop, name = __('Replace'), createNotice, removeNotice, children, multiple = false, addToGallery, handleUpload = true, popoverProps = { variant: 'toolbar' } }) => { const mediaUpload = useSelect(select => { return select(blockEditorStore).getSettings().mediaUpload; }, []); const canUpload = !!mediaUpload; const editMediaButtonRef = useRef(); const errorNoticeID = `block-editor/media-replace-flow/error-notice/${++uniqueId}`; const onUploadError = message => { const safeMessage = stripHTML(message); if (onError) { onError(safeMessage); return; } // We need to set a timeout for showing the notice // so that VoiceOver and possibly other screen readers // can announce the error afer the toolbar button // regains focus once the upload dialog closes. // Otherwise VO simply skips over the notice and announces // the focused element and the open menu. setTimeout(() => { createNotice('error', safeMessage, { speak: true, id: errorNoticeID, isDismissible: true }); }, 1000); }; const selectMedia = (media, closeMenu) => { if (useFeaturedImage && onToggleFeaturedImage) { onToggleFeaturedImage(); } closeMenu(); // Calling `onSelect` after the state update since it might unmount the component. onSelect(media); speak(__('The media file has been replaced')); removeNotice(errorNoticeID); }; const uploadFiles = (event, closeMenu) => { const files = event.target.files; if (!handleUpload) { closeMenu(); return onSelect(files); } onFilesUpload(files); mediaUpload({ allowedTypes, filesList: files, onFileChange: ([media]) => { selectMedia(media, closeMenu); }, onError: onUploadError }); }; const openOnArrowDown = event => { if (event.keyCode === DOWN) { event.preventDefault(); event.target.click(); } }; const onlyAllowsImages = () => { if (!allowedTypes || allowedTypes.length === 0) { return false; } return allowedTypes.every(allowedType => allowedType === 'image' || allowedType.startsWith('image/')); }; const gallery = multiple && onlyAllowsImages(); return createElement(Dropdown, { popoverProps: popoverProps, contentClassName: "block-editor-media-replace-flow__options", renderToggle: ({ isOpen, onToggle }) => createElement(ToolbarButton, { ref: editMediaButtonRef, "aria-expanded": isOpen, "aria-haspopup": "true", onClick: onToggle, onKeyDown: openOnArrowDown }, name), renderContent: ({ onClose }) => createElement(Fragment, null, createElement(NavigableMenu, { className: "block-editor-media-replace-flow__media-upload-menu" }, createElement(MediaUploadCheck, null, createElement(MediaUpload, { gallery: gallery, addToGallery: addToGallery, multiple: multiple, value: multiple ? mediaIds : mediaId, onSelect: media => selectMedia(media, onClose), allowedTypes: allowedTypes, render: ({ open }) => createElement(MenuItem, { icon: mediaIcon, onClick: open }, __('Open Media Library')) }), createElement(FormFileUpload, { onChange: event => { uploadFiles(event, onClose); }, accept: accept, multiple: multiple, render: ({ openFileDialog }) => { return createElement(MenuItem, { icon: upload, onClick: () => { openFileDialog(); } }, __('Upload')); } })), onToggleFeaturedImage && createElement(MenuItem, { icon: postFeaturedImage, onClick: onToggleFeaturedImage, isPressed: useFeaturedImage }, __('Use featured image')), children), onSelectURL && // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions createElement("form", { className: classnames('block-editor-media-flow__url-input', { 'has-siblings': canUpload || onToggleFeaturedImage }) }, createElement("span", { className: "block-editor-media-replace-flow__image-url-label" }, __('Current media URL:')), createElement(Tooltip, { text: mediaURL, position: "bottom" }, createElement("div", null, createElement(LinkControl, { value: { url: mediaURL }, settings: [], showSuggestions: false, onChange: ({ url }) => { onSelectURL(url); editMediaButtonRef.current.focus(); } }))))) }); }; /** * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-replace-flow/README.md */ export default compose([withDispatch(dispatch => { const { createNotice, removeNotice } = dispatch(noticesStore); return { createNotice, removeNotice }; }), withFilters('editor.MediaReplaceFlow')])(MediaReplaceFlow); //# sourceMappingURL=index.js.map