UNPKG

@wordpress/block-library

Version:
356 lines (352 loc) 11.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _reactNative = require("react-native"); var _i18n = require("@wordpress/i18n"); var _blockEditor = require("@wordpress/block-editor"); var _element = require("@wordpress/element"); var _components = require("@wordpress/components"); var _data = require("@wordpress/data"); var _compose = require("@wordpress/compose"); var _icons = require("@wordpress/icons"); var _constants = require("./constants"); var _mediaContainer = _interopRequireDefault(require("./media-container")); var _style = _interopRequireDefault(require("./style.scss")); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const TEMPLATE = [['core/paragraph']]; // this limits the resize to a safe zone to avoid making broken layouts const BREAKPOINTS = { mobile: 480 }; const applyWidthConstraints = width => Math.max(_constants.WIDTH_CONSTRAINT_PERCENTAGE, Math.min(width, 100 - _constants.WIDTH_CONSTRAINT_PERCENTAGE)); class MediaTextEdit extends _element.Component { constructor() { super(...arguments); this.onSelectMedia = this.onSelectMedia.bind(this); this.onMediaUpdate = this.onMediaUpdate.bind(this); this.onMediaThumbnailUpdate = this.onMediaThumbnailUpdate.bind(this); this.onWidthChange = this.onWidthChange.bind(this); this.commitWidthChange = this.commitWidthChange.bind(this); this.onLayoutChange = this.onLayoutChange.bind(this); this.onMediaSelected = this.onMediaSelected.bind(this); this.onReplaceMedia = this.onReplaceMedia.bind(this); this.onSetOpenPickerRef = this.onSetOpenPickerRef.bind(this); this.onSetImageFill = this.onSetImageFill.bind(this); this.state = { mediaWidth: null, containerWidth: 0, isMediaSelected: false }; } static getDerivedStateFromProps(props, state) { return { isMediaSelected: state.isMediaSelected && props.isSelected && !props.isAncestorSelected }; } onSelectMedia(media) { const { setAttributes } = this.props; 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' && media.sizes) { // Try the "large" size URL, falling back to the "full" size URL below. src = media.sizes.large?.url || media?.media_details?.sizes?.large?.source_url; } setAttributes({ mediaAlt: media.alt, mediaId: media.id, mediaType, mediaUrl: src || media.url, imageFill: undefined, focalPoint: undefined }); } onMediaUpdate(media) { const { setAttributes } = this.props; setAttributes({ mediaId: media.id, mediaUrl: media.url }); } onMediaThumbnailUpdate(mediaUrl) { const { setAttributes } = this.props; setAttributes({ mediaUrl }); } onWidthChange(width) { this.setState({ mediaWidth: applyWidthConstraints(width) }); } commitWidthChange(width) { const { setAttributes } = this.props; setAttributes({ mediaWidth: applyWidthConstraints(width) }); this.setState({ mediaWidth: null }); } onLayoutChange({ nativeEvent }) { const { width } = nativeEvent.layout; const { containerWidth } = this.state; if (containerWidth === width) { return null; } this.setState({ containerWidth: width }); } onMediaSelected() { this.setState({ isMediaSelected: true }); } onReplaceMedia() { if (this.openPickerRef) { this.openPickerRef(); } } onSetOpenPickerRef(openPicker) { this.openPickerRef = openPicker; } onSetImageFill() { const { attributes, setAttributes } = this.props; const { imageFill } = attributes; setAttributes({ imageFill: !imageFill }); } getControls() { const { attributes } = this.props; const { imageFill } = attributes; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.InspectorControls, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.PanelBody, { title: (0, _i18n.__)('Settings'), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToggleControl, { label: (0, _i18n.__)('Crop image to fill'), checked: imageFill, onChange: this.onSetImageFill }) }) }); } renderMediaArea(shouldStack) { const { isMediaSelected, containerWidth } = this.state; const { attributes, isSelected } = this.props; const { mediaAlt, mediaId, mediaPosition, mediaType, mediaUrl, mediaWidth, imageFill, focalPoint, verticalAlignment } = attributes; const mediaAreaWidth = mediaWidth && !shouldStack ? containerWidth * mediaWidth / 100 - _style.default.mediaAreaPadding.width : containerWidth; const alignmentStyles = _style.default[`is-vertically-aligned-${verticalAlignment || 'center'}`]; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_mediaContainer.default, { commitWidthChange: this.commitWidthChange, isMediaSelected: isMediaSelected, onFocus: this.props.onFocus, onMediaSelected: this.onMediaSelected, onMediaUpdate: this.onMediaUpdate, onMediaThumbnailUpdate: this.onMediaThumbnailUpdate, onSelectMedia: this.onSelectMedia, onSetOpenPickerRef: this.onSetOpenPickerRef, onWidthChange: this.onWidthChange, mediaWidth: mediaAreaWidth, mediaAlt, mediaId, mediaType, mediaUrl, mediaPosition, imageFill, focalPoint, isSelected, alignmentStyles, shouldStack }); } render() { const { attributes, backgroundColor, setAttributes, isSelected, isRTL, style, blockWidth } = this.props; const { isStackedOnMobile, imageFill, mediaPosition, mediaWidth, mediaType, verticalAlignment } = attributes; const { containerWidth, isMediaSelected } = this.state; const isMobile = containerWidth < BREAKPOINTS.mobile; const shouldStack = isStackedOnMobile && isMobile; const temporaryMediaWidth = shouldStack ? 100 : this.state.mediaWidth || mediaWidth; const widthString = `${temporaryMediaWidth}%`; const innerBlockWidth = shouldStack ? 100 : 100 - temporaryMediaWidth; const innerBlockWidthString = `${innerBlockWidth}%`; const hasMedia = mediaType === _blockEditor.MEDIA_TYPE_IMAGE || mediaType === _blockEditor.MEDIA_TYPE_VIDEO; const innerBlockContainerStyle = [{ width: innerBlockWidthString }, !shouldStack ? _style.default.innerBlock : { ...(mediaPosition === 'left' ? _style.default.innerBlockStackMediaLeft : _style.default.innerBlockStackMediaRight) }, (style?.backgroundColor || backgroundColor.color) && _style.default.innerBlockPaddings]; const containerStyles = { ..._style.default['wp-block-media-text'], ..._style.default[`is-vertically-aligned-${verticalAlignment || 'center'}`], ...(mediaPosition === 'right' ? _style.default['has-media-on-the-right'] : {}), ...(shouldStack && _style.default['is-stacked-on-mobile']), ...(shouldStack && mediaPosition === 'right' ? _style.default['is-stacked-on-mobile.has-media-on-the-right'] : {}), ...(isSelected && _style.default['is-selected']), backgroundColor: style?.backgroundColor || backgroundColor.color, paddingBottom: 0 }; const mediaContainerStyle = [{ flex: 1 }, shouldStack ? { ...(mediaPosition === 'left' && _style.default.mediaStackLeft), ...(mediaPosition === 'right' && _style.default.mediaStackRight) } : { ...(mediaPosition === 'left' && _style.default.mediaLeft), ...(mediaPosition === 'right' && _style.default.mediaRight) }]; const toolbarControls = [{ icon: isRTL ? _icons.pullRight : _icons.pullLeft, title: (0, _i18n.__)('Show media on left'), isActive: mediaPosition === 'left', onClick: () => setAttributes({ mediaPosition: 'left' }) }, { icon: isRTL ? _icons.pullLeft : _icons.pullRight, title: (0, _i18n.__)('Show media on right'), isActive: mediaPosition === 'right', onClick: () => setAttributes({ mediaPosition: 'right' }) }]; const onVerticalAlignmentChange = alignment => { setAttributes({ verticalAlignment: alignment }); }; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [mediaType === _blockEditor.MEDIA_TYPE_IMAGE && this.getControls(), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_blockEditor.BlockControls, { children: [hasMedia && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarGroup, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, { label: (0, _i18n.__)('Edit media'), icon: _icons.replace, onClick: this.onReplaceMedia }) }), (!isMediaSelected || mediaType === _blockEditor.MEDIA_TYPE_VIDEO) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarGroup, { controls: toolbarControls }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.BlockVerticalAlignmentToolbar, { onChange: onVerticalAlignmentChange, value: verticalAlignment })] })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: containerStyles, onLayout: this.onLayoutChange, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [(shouldStack || !imageFill) && { width: widthString }, mediaContainerStyle], children: this.renderMediaArea(shouldStack) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: innerBlockContainerStyle, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.InnerBlocks, { template: TEMPLATE, blockWidth: blockWidth }) })] })] }); } } var _default = exports.default = (0, _compose.compose)((0, _blockEditor.withColors)('backgroundColor'), (0, _data.withSelect)((select, { clientId }) => { const { getSelectedBlockClientId, getBlockParents, getSettings } = select(_blockEditor.store); const parents = getBlockParents(clientId, true); const selectedBlockClientId = getSelectedBlockClientId(); const isAncestorSelected = selectedBlockClientId && parents.includes(selectedBlockClientId); return { isSelected: selectedBlockClientId === clientId, isAncestorSelected, isRTL: getSettings().isRTL }; }))(MediaTextEdit); //# sourceMappingURL=edit.native.js.map