@wordpress/block-library
Version:
Block library for the WordPress editor.
458 lines (396 loc) • 13.5 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _lodash = require("lodash");
var _compose = require("@wordpress/compose");
var _components = require("@wordpress/components");
var _blockEditor = require("@wordpress/block-editor");
var _i18n = require("@wordpress/i18n");
var _blob = require("@wordpress/blob");
var _data = require("@wordpress/data");
var _viewport = require("@wordpress/viewport");
var _primitives = require("@wordpress/primitives");
var _coreData = require("@wordpress/core-data");
var _sharedIcon = require("../shared-icon");
var _shared = require("./shared");
var _deprecated = require("../deprecated");
var _gallery = _interopRequireDefault(require("./gallery"));
var _constants = require("./constants");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const MAX_COLUMNS = 8;
const linkOptions = [{
value: _constants.LINK_DESTINATION_ATTACHMENT,
label: (0, _i18n.__)('Attachment Page')
}, {
value: _constants.LINK_DESTINATION_MEDIA,
label: (0, _i18n.__)('Media File')
}, {
value: _constants.LINK_DESTINATION_NONE,
label: (0, _i18n.__)('None')
}];
const ALLOWED_MEDIA_TYPES = ['image'];
const PLACEHOLDER_TEXT = _element.Platform.select({
web: (0, _i18n.__)('Drag images, upload new ones or select files from your library.'),
native: (0, _i18n.__)('ADD MEDIA')
});
const MOBILE_CONTROL_PROPS_RANGE_CONTROL = _element.Platform.select({
web: {},
native: {
type: 'stepper'
}
});
function GalleryEdit(props) {
const {
attributes,
clientId,
isSelected,
noticeUI,
noticeOperations,
onFocus
} = props;
const {
columns = (0, _deprecated.defaultColumnsNumberV1)(attributes),
imageCrop,
images,
linkTo,
sizeSlug
} = attributes;
const [selectedImage, setSelectedImage] = (0, _element.useState)();
const [attachmentCaptions, setAttachmentCaptions] = (0, _element.useState)();
const {
__unstableMarkNextChangeAsNotPersistent
} = (0, _data.useDispatch)(_blockEditor.store);
const {
imageSizes,
mediaUpload,
getMedia,
wasBlockJustInserted
} = (0, _data.useSelect)(select => {
const settings = select(_blockEditor.store).getSettings();
return {
imageSizes: settings.imageSizes,
mediaUpload: settings.mediaUpload,
getMedia: select(_coreData.store).getMedia,
wasBlockJustInserted: select(_blockEditor.store).wasBlockJustInserted(clientId, 'inserter_menu')
};
});
const resizedImages = (0, _element.useMemo)(() => {
if (isSelected) {
return (0, _lodash.reduce)(attributes.ids, (currentResizedImages, id) => {
if (!id) {
return currentResizedImages;
}
const image = getMedia(id);
const sizes = (0, _lodash.reduce)(imageSizes, (currentSizes, size) => {
const defaultUrl = (0, _lodash.get)(image, ['sizes', size.slug, 'url']);
const mediaDetailsUrl = (0, _lodash.get)(image, ['media_details', 'sizes', size.slug, 'source_url']);
return { ...currentSizes,
[size.slug]: defaultUrl || mediaDetailsUrl
};
}, {});
return { ...currentResizedImages,
[parseInt(id, 10)]: sizes
};
}, {});
}
return {};
}, [isSelected, attributes.ids, imageSizes]);
function onFocusGalleryCaption() {
setSelectedImage();
}
function setAttributes(newAttrs) {
if (newAttrs.ids) {
throw new Error('The "ids" attribute should not be changed directly. It is managed automatically when "images" attribute changes');
}
if (newAttrs.images) {
newAttrs = { ...newAttrs,
// Unlike images[ n ].id which is a string, always ensure the
// ids array contains numbers as per its attribute type.
ids: (0, _lodash.map)(newAttrs.images, _ref => {
let {
id
} = _ref;
return parseInt(id, 10);
})
};
}
props.setAttributes(newAttrs);
}
function onSelectImage(index) {
return () => {
setSelectedImage(index);
};
}
function onDeselectImage() {
return () => {
setSelectedImage();
};
}
function onMove(oldIndex, newIndex) {
const newImages = [...images];
newImages.splice(newIndex, 1, images[oldIndex]);
newImages.splice(oldIndex, 1, images[newIndex]);
setSelectedImage(newIndex);
setAttributes({
images: newImages
});
}
function onMoveForward(oldIndex) {
return () => {
if (oldIndex === images.length - 1) {
return;
}
onMove(oldIndex, oldIndex + 1);
};
}
function onMoveBackward(oldIndex) {
return () => {
if (oldIndex === 0) {
return;
}
onMove(oldIndex, oldIndex - 1);
};
}
function onRemoveImage(index) {
return () => {
const newImages = (0, _lodash.filter)(images, (img, i) => index !== i);
setSelectedImage();
setAttributes({
images: newImages,
columns: attributes.columns ? Math.min(newImages.length, attributes.columns) : attributes.columns
});
};
}
function selectCaption(newImage) {
// The image id in both the images and attachmentCaptions arrays is a
// string, so ensure comparison works correctly by converting the
// newImage.id to a string.
const newImageId = newImage.id.toString();
const currentImage = (0, _lodash.find)(images, {
id: newImageId
});
const currentImageCaption = currentImage ? currentImage.caption : newImage.caption;
if (!attachmentCaptions) {
return currentImageCaption;
}
const attachment = (0, _lodash.find)(attachmentCaptions, {
id: newImageId
}); // If the attachment caption is updated.
if (attachment && attachment.caption !== newImage.caption) {
return newImage.caption;
}
return currentImageCaption;
}
function onSelectImages(newImages) {
setAttachmentCaptions(newImages.map(newImage => ({
// Store the attachmentCaption id as a string for consistency
// with the type of the id in the images attribute.
id: newImage.id.toString(),
caption: newImage.caption
})));
setAttributes({
images: newImages.map(newImage => ({ ...(0, _shared.pickRelevantMediaFiles)(newImage, sizeSlug),
caption: selectCaption(newImage, images, attachmentCaptions),
// The id value is stored in a data attribute, so when the
// block is parsed it's converted to a string. Converting
// to a string here ensures it's type is consistent.
id: newImage.id.toString()
})),
columns: attributes.columns ? Math.min(newImages.length, attributes.columns) : attributes.columns
});
}
function onUploadError(message) {
noticeOperations.removeAllNotices();
noticeOperations.createErrorNotice(message);
}
function setLinkTo(value) {
setAttributes({
linkTo: value
});
}
function setColumnsNumber(value) {
setAttributes({
columns: value
});
}
function toggleImageCrop() {
setAttributes({
imageCrop: !imageCrop
});
}
function getImageCropHelp(checked) {
return checked ? (0, _i18n.__)('Thumbnails are cropped to align.') : (0, _i18n.__)('Thumbnails are not cropped.');
}
function setImageAttributes(index, newAttributes) {
if (!images[index]) {
return;
}
setAttributes({
images: [...images.slice(0, index), { ...images[index],
...newAttributes
}, ...images.slice(index + 1)]
});
}
function getImagesSizeOptions() {
return (0, _lodash.map)((0, _lodash.filter)(imageSizes, _ref2 => {
let {
slug
} = _ref2;
return (0, _lodash.some)(resizedImages, sizes => sizes[slug]);
}), _ref3 => {
let {
name,
slug
} = _ref3;
return {
value: slug,
label: name
};
});
}
function updateImagesSize(newSizeSlug) {
const updatedImages = (0, _lodash.map)(images, image => {
if (!image.id) {
return image;
}
const url = (0, _lodash.get)(resizedImages, [parseInt(image.id, 10), newSizeSlug]);
return { ...image,
...(url && {
url
})
};
});
setAttributes({
images: updatedImages,
sizeSlug: newSizeSlug
});
}
(0, _element.useEffect)(() => {
if (_element.Platform.OS === 'web' && images && images.length > 0 && (0, _lodash.every)(images, _ref4 => {
let {
url
} = _ref4;
return (0, _blob.isBlobURL)(url);
})) {
const filesList = (0, _lodash.map)(images, _ref5 => {
let {
url
} = _ref5;
return (0, _blob.getBlobByURL)(url);
});
images.forEach(_ref6 => {
let {
url
} = _ref6;
return (0, _blob.revokeBlobURL)(url);
});
mediaUpload({
filesList,
onFileChange: onSelectImages,
allowedTypes: ['image']
});
}
}, []);
(0, _element.useEffect)(() => {
// Deselect images when deselecting the block.
if (!isSelected) {
setSelectedImage();
}
}, [isSelected]);
(0, _element.useEffect)(() => {
// linkTo attribute must be saved so blocks don't break when changing
// image_default_link_type in options.php.
if (!linkTo) {
var _window, _window$wp, _window$wp$media, _window$wp$media$view, _window$wp$media$view2, _window$wp$media$view3;
__unstableMarkNextChangeAsNotPersistent();
setAttributes({
linkTo: ((_window = window) === null || _window === void 0 ? void 0 : (_window$wp = _window.wp) === null || _window$wp === void 0 ? void 0 : (_window$wp$media = _window$wp.media) === null || _window$wp$media === void 0 ? void 0 : (_window$wp$media$view = _window$wp$media.view) === null || _window$wp$media$view === void 0 ? void 0 : (_window$wp$media$view2 = _window$wp$media$view.settings) === null || _window$wp$media$view2 === void 0 ? void 0 : (_window$wp$media$view3 = _window$wp$media$view2.defaultProps) === null || _window$wp$media$view3 === void 0 ? void 0 : _window$wp$media$view3.link) || _constants.LINK_DESTINATION_NONE
});
}
}, [linkTo]);
const hasImages = !!images.length;
const hasImageIds = hasImages && images.some(image => !!image.id);
const mediaPlaceholder = (0, _element.createElement)(_blockEditor.MediaPlaceholder, {
addToGallery: hasImageIds,
isAppender: hasImages,
disableMediaButtons: hasImages && !isSelected,
icon: !hasImages && _sharedIcon.sharedIcon,
labels: {
title: !hasImages && (0, _i18n.__)('Gallery'),
instructions: !hasImages && PLACEHOLDER_TEXT
},
onSelect: onSelectImages,
accept: "image/*",
allowedTypes: ALLOWED_MEDIA_TYPES,
multiple: true,
value: hasImageIds ? images : {},
onError: onUploadError,
notices: hasImages ? undefined : noticeUI,
onFocus: onFocus,
autoOpenMediaUpload: !hasImages && isSelected && wasBlockJustInserted
});
const blockProps = (0, _blockEditor.useBlockProps)();
if (!hasImages) {
return (0, _element.createElement)(_primitives.View, blockProps, mediaPlaceholder);
}
const imageSizeOptions = getImagesSizeOptions();
const shouldShowSizeOptions = hasImages && !(0, _lodash.isEmpty)(imageSizeOptions);
return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_components.PanelBody, {
title: (0, _i18n.__)('Settings')
}, images.length > 1 && (0, _element.createElement)(_components.RangeControl, (0, _extends2.default)({
label: (0, _i18n.__)('Columns'),
value: columns,
onChange: setColumnsNumber,
min: 1,
max: Math.min(MAX_COLUMNS, images.length)
}, MOBILE_CONTROL_PROPS_RANGE_CONTROL, {
required: true
})), (0, _element.createElement)(_components.ToggleControl, {
label: (0, _i18n.__)('Crop images'),
checked: !!imageCrop,
onChange: toggleImageCrop,
help: getImageCropHelp
}), (0, _element.createElement)(_components.SelectControl, {
label: (0, _i18n.__)('Link to'),
value: linkTo,
onChange: setLinkTo,
options: linkOptions,
hideCancelButton: true
}), shouldShowSizeOptions && (0, _element.createElement)(_components.SelectControl, {
label: (0, _i18n.__)('Image size'),
value: sizeSlug,
options: imageSizeOptions,
onChange: updateImagesSize,
hideCancelButton: true
}))), noticeUI, (0, _element.createElement)(_gallery.default, (0, _extends2.default)({}, props, {
selectedImage: selectedImage,
mediaPlaceholder: mediaPlaceholder,
onMoveBackward: onMoveBackward,
onMoveForward: onMoveForward,
onRemoveImage: onRemoveImage,
onSelectImage: onSelectImage,
onDeselectImage: onDeselectImage,
onSetImageAttributes: setImageAttributes,
blockProps: blockProps // This prop is used by gallery.native.js.
,
onFocusGalleryCaption: onFocusGalleryCaption
})));
}
var _default = (0, _compose.compose)([_components.withNotices, (0, _viewport.withViewportMatch)({
isNarrow: '< small'
})])(GalleryEdit);
exports.default = _default;
//# sourceMappingURL=edit.js.map
;