UNPKG

@wordpress/block-editor

Version:
266 lines (265 loc) 8.88 kB
// packages/block-editor/src/components/inserter/media-tab/media-preview.js import clsx from "clsx"; import { Tooltip, DropdownMenu, MenuGroup, MenuItem, Spinner, Modal, Flex, FlexItem, Button, Composite, __experimentalVStack as VStack } from "@wordpress/components"; import { __, sprintf } from "@wordpress/i18n"; import { useMemo, useCallback, useState } from "@wordpress/element"; import { cloneBlock } from "@wordpress/blocks"; import { moreVertical, external } from "@wordpress/icons"; import { useSelect, useDispatch } from "@wordpress/data"; import { store as noticesStore } from "@wordpress/notices"; import { isBlobURL } from "@wordpress/blob"; import { getFilename } from "@wordpress/url"; import InserterDraggableBlocks from "../../inserter-draggable-blocks/index.mjs"; import { getBlockAndPreviewFromMedia } from "./utils.mjs"; import { store as blockEditorStore } from "../../../store/index.mjs"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var ALLOWED_MEDIA_TYPES = ["image"]; var MEDIA_OPTIONS_POPOVER_PROPS = { placement: "bottom-end", className: "block-editor-inserter__media-list__item-preview-options__popover" }; function MediaPreviewOptions({ category, media }) { if (!category.getReportUrl) { return null; } const reportUrl = category.getReportUrl(media); return /* @__PURE__ */ jsx( DropdownMenu, { className: "block-editor-inserter__media-list__item-preview-options", label: __("Options"), popoverProps: MEDIA_OPTIONS_POPOVER_PROPS, icon: moreVertical, children: () => /* @__PURE__ */ jsx(MenuGroup, { children: /* @__PURE__ */ jsx( MenuItem, { onClick: () => window.open(reportUrl, "_blank").focus(), icon: external, children: sprintf( /* translators: %s: The media type to report e.g: "image", "video", "audio" */ __("Report %s"), category.mediaType ) } ) }) } ); } function InsertExternalImageModal({ onClose, onSubmit }) { return /* @__PURE__ */ jsxs( Modal, { title: __("Insert external image"), onRequestClose: onClose, className: "block-editor-inserter-media-tab-media-preview-inserter-external-image-modal", children: [ /* @__PURE__ */ jsxs(VStack, { spacing: 3, children: [ /* @__PURE__ */ jsx("p", { children: __( "This image cannot be uploaded to your Media Library, but it can still be inserted as an external image." ) }), /* @__PURE__ */ jsx("p", { children: __( "External images can be removed by the external provider without warning and could even have legal compliance issues related to privacy legislation." ) }) ] }), /* @__PURE__ */ jsxs( Flex, { className: "block-editor-block-lock-modal__actions", justify: "flex-end", expanded: false, children: [ /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx( Button, { __next40pxDefaultSize: true, variant: "tertiary", onClick: onClose, children: __("Cancel") } ) }), /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx( Button, { __next40pxDefaultSize: true, variant: "primary", onClick: onSubmit, children: __("Insert") } ) }) ] } ) ] } ); } function MediaPreview({ media, onClick, category }) { const [showExternalUploadModal, setShowExternalUploadModal] = useState(false); const [isHovered, setIsHovered] = useState(false); const [isInserting, setIsInserting] = useState(false); const [block, preview] = useMemo( () => getBlockAndPreviewFromMedia(media, category.mediaType), [media, category.mediaType] ); const { createErrorNotice, createSuccessNotice } = useDispatch(noticesStore); const { getSettings, getBlock } = useSelect(blockEditorStore); const { updateBlockAttributes } = useDispatch(blockEditorStore); const onMediaInsert = useCallback( (previewBlock) => { if (isInserting) { return; } const settings = getSettings(); const clonedBlock = cloneBlock(previewBlock); const { id, url, caption } = clonedBlock.attributes; if (!id && !settings.mediaUpload) { setShowExternalUploadModal(true); return; } if (!!id) { onClick(clonedBlock); return; } setIsInserting(true); window.fetch(url).then((response) => response.blob()).then((blob) => { const fileName = getFilename(url) || "image.jpg"; const file = new File([blob], fileName, { type: blob.type }); settings.mediaUpload({ filesList: [file], additionalData: { caption }, onFileChange([img]) { if (isBlobURL(img.url)) { return; } if (!getBlock(clonedBlock.clientId)) { onClick({ ...clonedBlock, attributes: { ...clonedBlock.attributes, id: img.id, url: img.url } }); createSuccessNotice( __("Image uploaded and inserted."), { type: "snackbar", id: "inserter-notice" } ); } else { updateBlockAttributes(clonedBlock.clientId, { ...clonedBlock.attributes, id: img.id, url: img.url }); } setIsInserting(false); }, allowedTypes: ALLOWED_MEDIA_TYPES, onError(message) { createErrorNotice(message, { type: "snackbar", id: "inserter-notice" }); setIsInserting(false); } }); }).catch(() => { setShowExternalUploadModal(true); setIsInserting(false); }); }, [ isInserting, getSettings, onClick, createSuccessNotice, updateBlockAttributes, createErrorNotice, getBlock ] ); const title = typeof media.title === "string" ? media.title : media.title?.rendered || __("no title"); const onMouseEnter = useCallback(() => setIsHovered(true), []); const onMouseLeave = useCallback(() => setIsHovered(false), []); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(InserterDraggableBlocks, { isEnabled: true, blocks: [block], children: ({ draggable, onDragStart, onDragEnd }) => /* @__PURE__ */ jsx( "div", { className: clsx( "block-editor-inserter__media-list__list-item", { "is-hovered": isHovered } ), draggable, onDragStart, onDragEnd, children: /* @__PURE__ */ jsxs( "div", { onMouseEnter, onMouseLeave, children: [ /* @__PURE__ */ jsx(Tooltip, { text: title, children: /* @__PURE__ */ jsx( Composite.Item, { render: /* @__PURE__ */ jsx( "div", { "aria-label": title, role: "option", className: "block-editor-inserter__media-list__item" } ), onClick: () => onMediaInsert(block), children: /* @__PURE__ */ jsxs("div", { className: "block-editor-inserter__media-list__item-preview", children: [ preview, isInserting && /* @__PURE__ */ jsx("div", { className: "block-editor-inserter__media-list__item-preview-spinner", children: /* @__PURE__ */ jsx(Spinner, {}) }) ] }) } ) }), !isInserting && /* @__PURE__ */ jsx( MediaPreviewOptions, { category, media } ) ] } ) } ) }), showExternalUploadModal && /* @__PURE__ */ jsx( InsertExternalImageModal, { onClose: () => setShowExternalUploadModal(false), onSubmit: () => { onClick(cloneBlock(block)); createSuccessNotice(__("Image inserted."), { type: "snackbar", id: "inserter-notice" }); setShowExternalUploadModal(false); } } ) ] }); } export { MediaPreview }; //# sourceMappingURL=media-preview.mjs.map