UNPKG

@wordpress/block-library

Version:
456 lines (450 loc) 15.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _clsx = _interopRequireDefault(require("clsx")); var _i18n = require("@wordpress/i18n"); var _data = require("@wordpress/data"); var _element = require("@wordpress/element"); var _blockEditor = require("@wordpress/block-editor"); var _components = require("@wordpress/components"); var _blob = require("@wordpress/blob"); var _icons = require("@wordpress/icons"); var _coreData = require("@wordpress/core-data"); var _mediaContainer = _interopRequireDefault(require("./media-container")); var _constants = require("./constants"); var _lockUnlock = require("../lock-unlock"); var _hooks = require("../utils/hooks"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const { ResolutionTool } = (0, _lockUnlock.unlock)(_blockEditor.privateApis); // this limits the resize to a safe zone to avoid making broken layouts const applyWidthConstraints = width => Math.max(_constants.WIDTH_CONSTRAINT_PERCENTAGE, Math.min(width, 100 - _constants.WIDTH_CONSTRAINT_PERCENTAGE)); function getImageSourceUrlBySizeSlug(image, slug) { // eslint-disable-next-line camelcase return image?.media_details?.sizes?.[slug]?.source_url; } function attributesFromMedia({ attributes: { linkDestination, href }, setAttributes }) { return media => { if (!media || !media.url) { setAttributes({ mediaAlt: undefined, mediaId: undefined, mediaType: undefined, mediaUrl: undefined, mediaLink: undefined, href: undefined, focalPoint: undefined, useFeaturedImage: false }); return; } if ((0, _blob.isBlobURL)(media.url)) { media.type = (0, _blob.getBlobTypeByURL)(media.url); } let mediaType; let src; // For media selections originated from a file upload. if (media.media_type) { if (media.media_type === 'image') { mediaType = 'image'; } else { // only images and videos are accepted so if the media_type is not an image we can assume it is a video. // video contain the media type of 'file' in the object returned from the rest api. mediaType = 'video'; } } else { // For media selections originated from existing files in the media library. mediaType = media.type; } if (mediaType === 'image') { // Try the "large" size URL, falling back to the "full" size URL below. src = media.sizes?.large?.url || // eslint-disable-next-line camelcase media.media_details?.sizes?.large?.source_url; } let newHref = href; if (linkDestination === _constants.LINK_DESTINATION_MEDIA) { // Update the media link. newHref = media.url; } // Check if the image is linked to the attachment page. if (linkDestination === _constants.LINK_DESTINATION_ATTACHMENT) { // Update the media link. newHref = media.link; } setAttributes({ mediaAlt: media.alt, mediaId: media.id, mediaType, mediaUrl: src || media.url, mediaLink: media.link || undefined, href: newHref, focalPoint: undefined, useFeaturedImage: false }); }; } function MediaTextResolutionTool({ image, value, onChange }) { const { imageSizes } = (0, _data.useSelect)(select => { const { getSettings } = select(_blockEditor.store); return { imageSizes: getSettings().imageSizes }; }, []); if (!imageSizes?.length) { return null; } const imageSizeOptions = imageSizes.filter(({ slug }) => getImageSourceUrlBySizeSlug(image, slug)).map(({ name, slug }) => ({ value: slug, label: name })); return /*#__PURE__*/(0, _jsxRuntime.jsx)(ResolutionTool, { value: value, defaultValue: _constants.DEFAULT_MEDIA_SIZE_SLUG, options: imageSizeOptions, onChange: onChange }); } function MediaTextEdit({ attributes, isSelected, setAttributes, context: { postId, postType } }) { const { focalPoint, href, imageFill, isStackedOnMobile, linkClass, linkDestination, linkTarget, mediaAlt, mediaId, mediaPosition, mediaType, mediaUrl, mediaWidth, mediaSizeSlug, rel, verticalAlignment, allowedBlocks, useFeaturedImage } = attributes; const [featuredImage] = (0, _coreData.useEntityProp)('postType', postType, 'featured_media', postId); const { featuredImageMedia } = (0, _data.useSelect)(select => { return { featuredImageMedia: featuredImage && useFeaturedImage ? select(_coreData.store).getMedia(featuredImage, { context: 'view' }) : undefined }; }, [featuredImage, useFeaturedImage]); const { image } = (0, _data.useSelect)(select => { return { image: mediaId && isSelected ? select(_coreData.store).getMedia(mediaId, { context: 'view' }) : null }; }, [isSelected, mediaId]); const featuredImageURL = useFeaturedImage ? featuredImageMedia?.source_url : ''; const featuredImageAlt = useFeaturedImage ? featuredImageMedia?.alt_text : ''; const toggleUseFeaturedImage = () => { setAttributes({ imageFill: false, mediaType: 'image', mediaId: undefined, mediaUrl: undefined, mediaAlt: undefined, mediaLink: undefined, linkDestination: undefined, linkTarget: undefined, linkClass: undefined, rel: undefined, href: undefined, useFeaturedImage: !useFeaturedImage }); }; const refMedia = (0, _element.useRef)(); const imperativeFocalPointPreview = value => { const { style } = refMedia.current; const { x, y } = value; style.objectPosition = `${x * 100}% ${y * 100}%`; }; const [temporaryMediaWidth, setTemporaryMediaWidth] = (0, _element.useState)(null); const onSelectMedia = attributesFromMedia({ attributes, setAttributes }); const onSetHref = props => { setAttributes(props); }; const onWidthChange = width => { setTemporaryMediaWidth(applyWidthConstraints(width)); }; const commitWidthChange = width => { setAttributes({ mediaWidth: applyWidthConstraints(width) }); setTemporaryMediaWidth(null); }; const classNames = (0, _clsx.default)({ 'has-media-on-the-right': 'right' === mediaPosition, 'is-selected': isSelected, 'is-stacked-on-mobile': isStackedOnMobile, [`is-vertically-aligned-${verticalAlignment}`]: verticalAlignment, 'is-image-fill-element': imageFill }); const widthString = `${temporaryMediaWidth || mediaWidth}%`; const gridTemplateColumns = 'right' === mediaPosition ? `1fr ${widthString}` : `${widthString} 1fr`; const style = { gridTemplateColumns, msGridColumns: gridTemplateColumns }; const onMediaAltChange = newMediaAlt => { setAttributes({ mediaAlt: newMediaAlt }); }; const onVerticalAlignmentChange = alignment => { setAttributes({ verticalAlignment: alignment }); }; const updateImage = newMediaSizeSlug => { const newUrl = getImageSourceUrlBySizeSlug(image, newMediaSizeSlug); if (!newUrl) { return null; } setAttributes({ mediaUrl: newUrl, mediaSizeSlug: newMediaSizeSlug }); }; const dropdownMenuProps = (0, _hooks.useToolsPanelDropdownMenuProps)(); const mediaTextGeneralSettings = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalToolsPanel, { label: (0, _i18n.__)('Settings'), resetAll: () => { setAttributes({ isStackedOnMobile: true, imageFill: false, mediaAlt: '', focalPoint: undefined, mediaWidth: 50, mediaSizeSlug: undefined }); }, dropdownMenuProps: dropdownMenuProps, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Media width'), isShownByDefault: true, hasValue: () => mediaWidth !== 50, onDeselect: () => setAttributes({ mediaWidth: 50 }), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.RangeControl, { __nextHasNoMarginBottom: true, __next40pxDefaultSize: true, label: (0, _i18n.__)('Media width'), value: temporaryMediaWidth || mediaWidth, onChange: commitWidthChange, min: _constants.WIDTH_CONSTRAINT_PERCENTAGE, max: 100 - _constants.WIDTH_CONSTRAINT_PERCENTAGE }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Stack on mobile'), isShownByDefault: true, hasValue: () => !isStackedOnMobile, onDeselect: () => setAttributes({ isStackedOnMobile: true }), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToggleControl, { __nextHasNoMarginBottom: true, label: (0, _i18n.__)('Stack on mobile'), checked: isStackedOnMobile, onChange: () => setAttributes({ isStackedOnMobile: !isStackedOnMobile }) }) }), mediaType === 'image' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Crop image to fill'), isShownByDefault: true, hasValue: () => !!imageFill, onDeselect: () => setAttributes({ imageFill: false }), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToggleControl, { __nextHasNoMarginBottom: true, label: (0, _i18n.__)('Crop image to fill'), checked: !!imageFill, onChange: () => setAttributes({ imageFill: !imageFill }) }) }), imageFill && (mediaUrl || featuredImageURL) && mediaType === 'image' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Focal point'), isShownByDefault: true, hasValue: () => !!focalPoint, onDeselect: () => setAttributes({ focalPoint: undefined }), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FocalPointPicker, { __nextHasNoMarginBottom: true, label: (0, _i18n.__)('Focal point'), url: useFeaturedImage && featuredImageURL ? featuredImageURL : mediaUrl, value: focalPoint, onChange: value => setAttributes({ focalPoint: value }), onDragStart: imperativeFocalPointPreview, onDrag: imperativeFocalPointPreview }) }), mediaType === 'image' && mediaUrl && !useFeaturedImage && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Alternative text'), isShownByDefault: true, hasValue: () => !!mediaAlt, onDeselect: () => setAttributes({ mediaAlt: '' }), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.TextareaControl, { __nextHasNoMarginBottom: true, label: (0, _i18n.__)('Alternative text'), value: mediaAlt, onChange: onMediaAltChange, help: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ExternalLink, { href: // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. (0, _i18n.__)('https://www.w3.org/WAI/tutorials/images/decision-tree/'), children: (0, _i18n.__)('Describe the purpose of the image.') }), /*#__PURE__*/(0, _jsxRuntime.jsx)("br", {}), (0, _i18n.__)('Leave empty if decorative.')] }) }) }), mediaType === 'image' && !useFeaturedImage && /*#__PURE__*/(0, _jsxRuntime.jsx)(MediaTextResolutionTool, { image: image, value: mediaSizeSlug, onChange: updateImage })] }); const blockProps = (0, _blockEditor.useBlockProps)({ className: classNames, style }); const innerBlocksProps = (0, _blockEditor.useInnerBlocksProps)({ className: 'wp-block-media-text__content' }, { template: _constants.TEMPLATE, allowedBlocks }); const blockEditingMode = (0, _blockEditor.useBlockEditingMode)(); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.InspectorControls, { children: mediaTextGeneralSettings }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_blockEditor.BlockControls, { group: "block", children: [blockEditingMode === 'default' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.BlockVerticalAlignmentControl, { onChange: onVerticalAlignmentChange, value: verticalAlignment }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarButton, { icon: _icons.pullLeft, title: (0, _i18n.__)('Show media on left'), isActive: mediaPosition === 'left', onClick: () => setAttributes({ mediaPosition: 'left' }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarButton, { icon: _icons.pullRight, title: (0, _i18n.__)('Show media on right'), isActive: mediaPosition === 'right', onClick: () => setAttributes({ mediaPosition: 'right' }) })] }), mediaType === 'image' && !useFeaturedImage && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.__experimentalImageURLInputUI, { url: href || '', onChangeUrl: onSetHref, linkDestination: linkDestination, mediaType: mediaType, mediaUrl: image && image.source_url, mediaLink: image && image.link, linkTarget: linkTarget, linkClass: linkClass, rel: rel })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { ...blockProps, children: [mediaPosition === 'right' && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { ...innerBlocksProps }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_mediaContainer.default, { className: "wp-block-media-text__media", onSelectMedia: onSelectMedia, onWidthChange: onWidthChange, commitWidthChange: commitWidthChange, refMedia: refMedia, enableResize: blockEditingMode === 'default', toggleUseFeaturedImage: toggleUseFeaturedImage, focalPoint, imageFill, isSelected, isStackedOnMobile, mediaAlt, mediaId, mediaPosition, mediaType, mediaUrl, mediaWidth, useFeaturedImage, featuredImageURL, featuredImageAlt }), mediaPosition !== 'right' && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { ...innerBlocksProps })] })] }); } var _default = exports.default = MediaTextEdit; //# sourceMappingURL=edit.js.map