UNPKG

@wordpress/block-editor

Version:
517 lines (515 loc) 17.4 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/block-editor/src/components/media-placeholder/index.js var media_placeholder_exports = {}; __export(media_placeholder_exports, { MediaPlaceholder: () => MediaPlaceholder, default: () => media_placeholder_default }); module.exports = __toCommonJS(media_placeholder_exports); var import_clsx = __toESM(require("clsx")); var import_components = require("@wordpress/components"); var import_i18n = require("@wordpress/i18n"); var import_element = require("@wordpress/element"); var import_data = require("@wordpress/data"); var import_icons = require("@wordpress/icons"); var import_deprecated = __toESM(require("@wordpress/deprecated")); var import_media_upload = __toESM(require("../media-upload")); var import_check = __toESM(require("../media-upload/check")); var import_url_popover = __toESM(require("../url-popover")); var import_store = require("../../store"); var import_use_on_block_drop = require("../use-on-block-drop"); var import_utils = require("./utils"); var import_jsx_runtime = require("react/jsx-runtime"); var noop = () => { }; var InsertFromURLPopover = ({ src, onChange, onSubmit, onClose, popoverAnchor }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_url_popover.default, { anchor: popoverAnchor, onClose, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "form", { className: "block-editor-media-placeholder__url-input-form", onSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.__experimentalInputControl, { __next40pxDefaultSize: true, label: (0, import_i18n.__)("URL"), type: "text", hideLabelFromVision: true, placeholder: (0, import_i18n.__)("Paste or type URL"), onChange, value: src, suffix: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalInputControlSuffixWrapper, { variant: "control", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { size: "small", icon: import_icons.keyboardReturn, label: (0, import_i18n.__)("Apply"), type: "submit" } ) }) } ) } ) }); var URLSelectionUI = ({ src, onChangeSrc, onSelectURL }) => { const [popoverAnchor, setPopoverAnchor] = (0, import_element.useState)(null); const [isURLInputVisible, setIsURLInputVisible] = (0, import_element.useState)(false); const openURLInput = () => { setIsURLInputVisible(true); }; const closeURLInput = () => { setIsURLInputVisible(false); popoverAnchor?.focus(); }; const onSubmitSrc = (event) => { event.preventDefault(); if (src && onSelectURL) { onSelectURL(src); closeURLInput(); } }; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "block-editor-media-placeholder__url-input-container", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, className: "block-editor-media-placeholder__button", onClick: openURLInput, isPressed: isURLInputVisible, variant: "secondary", "aria-haspopup": "dialog", ref: setPopoverAnchor, children: (0, import_i18n.__)("Insert from URL") } ), isURLInputVisible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( InsertFromURLPopover, { src, onChange: onChangeSrc, onSubmit: onSubmitSrc, onClose: closeURLInput, popoverAnchor } ) ] }); }; function MediaPlaceholder({ value = {}, allowedTypes, className, icon, labels = {}, mediaPreview, notices, isAppender, accept, addToGallery, multiple = false, handleUpload = true, disableDropZone, disableMediaButtons, onError, onSelect, onCancel, onSelectURL, onToggleFeaturedImage, onDoubleClick, onFilesPreUpload = noop, onHTMLDrop: deprecatedOnHTMLDrop, children, mediaLibraryButton, placeholder, style }) { if (deprecatedOnHTMLDrop) { (0, import_deprecated.default)("wp.blockEditor.MediaPlaceholder onHTMLDrop prop", { since: "6.2", version: "6.4" }); } const { mediaUpload, allowedMimeTypes } = (0, import_data.useSelect)((select) => { const { getSettings } = select(import_store.store); const settings = getSettings(); return { mediaUpload: settings.mediaUpload, allowedMimeTypes: settings.allowedMimeTypes }; }, []); const [src, setSrc] = (0, import_element.useState)(""); (0, import_element.useEffect)(() => { setSrc(value?.src ?? ""); }, [value?.src]); const computedAccept = (0, import_element.useMemo)( () => (0, import_utils.getComputedAcceptAttribute)( allowedTypes, allowedMimeTypes, accept ), [allowedTypes, allowedMimeTypes, accept] ); const onlyAllowsImages = () => { if (!allowedTypes || allowedTypes.length === 0) { return false; } return allowedTypes.every( (allowedType) => allowedType === "image" || allowedType.startsWith("image/") ); }; const onFilesUpload = (files) => { if (!handleUpload || typeof handleUpload === "function" && !handleUpload(files)) { return onSelect(files); } onFilesPreUpload(files); let setMedia; if (multiple) { if (addToGallery) { let lastMediaPassed = []; setMedia = (newMedia) => { const filteredMedia = (value ?? []).filter((item) => { if (item.id) { return !lastMediaPassed.some( // Be sure to convert to number for comparison. ({ id }) => Number(id) === Number(item.id) ); } return !lastMediaPassed.some( ({ urlSlug }) => item.url.includes(urlSlug) ); }); onSelect(filteredMedia.concat(newMedia)); lastMediaPassed = newMedia.map((media) => { const cutOffIndex = media.url.lastIndexOf("."); const urlSlug = media.url.slice(0, cutOffIndex); return { id: media.id, urlSlug }; }); }; } else { setMedia = onSelect; } } else { setMedia = ([media]) => onSelect(media); } mediaUpload({ allowedTypes, filesList: files, onFileChange: setMedia, onError, multiple }); }; async function handleBlocksDrop(event) { const { blocks } = (0, import_use_on_block_drop.parseDropEvent)(event); if (!blocks?.length) { return; } const uploadedMediaList = await Promise.all( blocks.map((block) => { const blockType = block.name.split("/")[1]; if (block.attributes.id) { block.attributes.type = blockType; return block.attributes; } return new Promise((resolve, reject) => { window.fetch(block.attributes.url).then((response) => response.blob()).then( (blob) => mediaUpload({ filesList: [blob], additionalData: { title: block.attributes.title, alt_text: block.attributes.alt, caption: block.attributes.caption, type: blockType }, onFileChange: ([media]) => { if (media.id) { resolve(media); } }, allowedTypes, onError: reject }) ).catch(() => resolve(block.attributes.url)); }); }) ).catch((err) => onError(err)); if (!uploadedMediaList?.length) { return; } onSelect(multiple ? uploadedMediaList : uploadedMediaList[0]); } const onUpload = (event) => { onFilesUpload(event.target.files); }; const defaultRenderPlaceholder = (content) => { let { instructions, title } = labels; if (!mediaUpload && !onSelectURL) { instructions = (0, import_i18n.__)( "To edit this block, you need permission to upload media." ); } if (instructions === void 0 || title === void 0) { const typesAllowed = allowedTypes ?? []; const [firstAllowedType] = typesAllowed; const isOneType = 1 === typesAllowed.length; const isAudio = isOneType && "audio" === firstAllowedType; const isImage = isOneType && "image" === firstAllowedType; const isVideo = isOneType && "video" === firstAllowedType; if (instructions === void 0 && mediaUpload) { instructions = (0, import_i18n.__)( "Drag and drop an image or video, upload, or choose from your library." ); if (isAudio) { instructions = (0, import_i18n.__)( "Drag and drop an audio file, upload, or choose from your library." ); } else if (isImage) { instructions = (0, import_i18n.__)( "Drag and drop an image, upload, or choose from your library." ); } else if (isVideo) { instructions = (0, import_i18n.__)( "Drag and drop a video, upload, or choose from your library." ); } } if (title === void 0) { title = (0, import_i18n.__)("Media"); if (isAudio) { title = (0, import_i18n.__)("Audio"); } else if (isImage) { title = (0, import_i18n.__)("Image"); } else if (isVideo) { title = (0, import_i18n.__)("Video"); } } } const placeholderClassName = (0, import_clsx.default)( "block-editor-media-placeholder", className, { "is-appender": isAppender } ); return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_components.Placeholder, { icon, label: title, instructions, className: placeholderClassName, notices, onDoubleClick, preview: mediaPreview, style, children: [ content, children ] } ); }; const renderPlaceholder = placeholder ?? defaultRenderPlaceholder; const renderDropZone = () => { if (disableDropZone) { return null; } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.DropZone, { onFilesDrop: onFilesUpload, onDrop: handleBlocksDrop, isEligible: (dataTransfer) => { const prefix = "wp-block:core/"; const types = []; for (const type of dataTransfer.types) { if (type.startsWith(prefix)) { types.push(type.slice(prefix.length)); } } return types.every( (type) => allowedTypes.includes(type) ) && (multiple ? true : types.length === 1); } } ); }; const renderCancelLink = () => { return onCancel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, className: "block-editor-media-placeholder__cancel-button", title: (0, import_i18n.__)("Cancel"), variant: "link", onClick: onCancel, children: (0, import_i18n.__)("Cancel") } ); }; const renderUrlSelectionUI = () => { return onSelectURL && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( URLSelectionUI, { src, onChangeSrc: setSrc, onSelectURL } ); }; const renderFeaturedImageToggle = () => { return onToggleFeaturedImage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "block-editor-media-placeholder__url-input-container", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, className: "block-editor-media-placeholder__button", onClick: onToggleFeaturedImage, variant: "secondary", children: (0, import_i18n.__)("Use featured image") } ) }); }; const renderMediaUploadChecked = () => { const defaultButton = ({ open }) => { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, variant: "secondary", onClick: () => { open(); }, children: (0, import_i18n.__)("Media Library") } ); }; const libraryButton = mediaLibraryButton ?? defaultButton; const uploadMediaLibraryButton = /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_media_upload.default, { addToGallery, gallery: multiple && onlyAllowsImages(), multiple, onSelect, allowedTypes, mode: "browse", value: Array.isArray(value) ? value.map(({ id }) => id) : value.id, render: libraryButton } ); if (mediaUpload && isAppender) { return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ renderDropZone(), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.FormFileUpload, { onChange: onUpload, accept: computedAccept, multiple: !!multiple, render: ({ openFileDialog }) => { const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, variant: "primary", className: (0, import_clsx.default)( "block-editor-media-placeholder__button", "block-editor-media-placeholder__upload-button" ), onClick: openFileDialog, children: (0, import_i18n._x)("Upload", "verb") } ), uploadMediaLibraryButton, renderUrlSelectionUI(), renderFeaturedImageToggle(), renderCancelLink() ] }); return renderPlaceholder(content); } } ) ] }); } if (mediaUpload) { const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ renderDropZone(), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.FormFileUpload, { render: ({ openFileDialog }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Button, { __next40pxDefaultSize: true, onClick: openFileDialog, variant: "primary", className: (0, import_clsx.default)( "block-editor-media-placeholder__button", "block-editor-media-placeholder__upload-button" ), children: (0, import_i18n._x)("Upload", "verb") } ), onChange: onUpload, accept: computedAccept, multiple: !!multiple } ), uploadMediaLibraryButton, renderUrlSelectionUI(), renderFeaturedImageToggle(), renderCancelLink() ] }); return renderPlaceholder(content); } return renderPlaceholder(uploadMediaLibraryButton); }; if (disableMediaButtons) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_check.default, { children: renderDropZone() }); } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_check.default, { fallback: renderPlaceholder(renderUrlSelectionUI()), children: renderMediaUploadChecked() } ); } var media_placeholder_default = (0, import_components.withFilters)("editor.MediaPlaceholder")(MediaPlaceholder); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { MediaPlaceholder }); //# sourceMappingURL=index.js.map