@wordpress/block-library
Version:
Block library for the WordPress editor.
367 lines (325 loc) • 11.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _lodash = require("lodash");
var _reactNative = require("react-native");
var _i18n = require("@wordpress/i18n");
var _blockEditor = require("@wordpress/block-editor");
var _components = require("@wordpress/components");
var _data = require("@wordpress/data");
var _compose = require("@wordpress/compose");
var _icons = require("@wordpress/icons");
var _mediaContainer = _interopRequireDefault(require("./media-container"));
var _style = _interopRequireDefault(require("./style.scss"));
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const TEMPLATE = [['core/paragraph']]; // this limits the resize to a safe zone to avoid making broken layouts
const WIDTH_CONSTRAINT_PERCENTAGE = 15;
const BREAKPOINTS = {
mobile: 480
};
const applyWidthConstraints = width => Math.max(WIDTH_CONSTRAINT_PERCENTAGE, Math.min(width, 100 - WIDTH_CONSTRAINT_PERCENTAGE));
class MediaTextEdit extends _element.Component {
constructor() {
super(...arguments);
this.onSelectMedia = this.onSelectMedia.bind(this);
this.onMediaUpdate = this.onMediaUpdate.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 = (0, _lodash.get)(media, ['sizes', 'large', 'url']) || (0, _lodash.get)(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
});
}
onWidthChange(width) {
this.setState({
mediaWidth: applyWidthConstraints(width)
});
}
commitWidthChange(width) {
const {
setAttributes
} = this.props;
setAttributes({
mediaWidth: applyWidthConstraints(width)
});
this.setState({
mediaWidth: null
});
}
onLayoutChange(_ref) {
let {
nativeEvent
} = _ref;
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 (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_components.PanelBody, {
title: (0, _i18n.__)('Settings')
}, (0, _element.createElement)(_components.ToggleControl, {
label: (0, _i18n.__)('Crop image to fill entire column'),
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 aligmentStyles = _style.default[`is-vertically-aligned-${verticalAlignment || 'center'}`];
return (0, _element.createElement)(_mediaContainer.default, {
commitWidthChange: this.commitWidthChange,
isMediaSelected: isMediaSelected,
onFocus: this.props.onFocus,
onMediaSelected: this.onMediaSelected,
onMediaUpdate: this.onMediaUpdate,
onSelectMedia: this.onSelectMedia,
onSetOpenPickerRef: this.onSetOpenPickerRef,
onWidthChange: this.onWidthChange,
mediaWidth: mediaAreaWidth,
mediaAlt,
mediaId,
mediaType,
mediaUrl,
mediaPosition,
imageFill,
focalPoint,
isSelected,
aligmentStyles,
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 === null || style === void 0 ? void 0 : 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 === null || style === void 0 ? void 0 : 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 (0, _element.createElement)(_element.Fragment, null, mediaType === _blockEditor.MEDIA_TYPE_IMAGE && this.getControls(), (0, _element.createElement)(_blockEditor.BlockControls, null, hasMedia && (0, _element.createElement)(_components.ToolbarGroup, null, (0, _element.createElement)(_components.Button, {
label: (0, _i18n.__)('Edit media'),
icon: _icons.replace,
onClick: this.onReplaceMedia
})), (!isMediaSelected || mediaType === _blockEditor.MEDIA_TYPE_VIDEO) && (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_components.ToolbarGroup, {
controls: toolbarControls
}), (0, _element.createElement)(_blockEditor.BlockVerticalAlignmentToolbar, {
onChange: onVerticalAlignmentChange,
value: verticalAlignment
}))), (0, _element.createElement)(_reactNative.View, {
style: containerStyles,
onLayout: this.onLayoutChange
}, (0, _element.createElement)(_reactNative.View, {
style: [(shouldStack || !imageFill) && {
width: widthString
}, mediaContainerStyle]
}, this.renderMediaArea(shouldStack)), (0, _element.createElement)(_reactNative.View, {
style: innerBlockContainerStyle
}, (0, _element.createElement)(_blockEditor.InnerBlocks, {
template: TEMPLATE,
blockWidth: blockWidth
}))));
}
}
var _default = (0, _compose.compose)((0, _blockEditor.withColors)('backgroundColor'), (0, _data.withSelect)((select, _ref2) => {
let {
clientId
} = _ref2;
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);
exports.default = _default;
//# sourceMappingURL=edit.native.js.map