UNPKG

@wordpress/block-library

Version:
498 lines (436 loc) 18.8 kB
"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 _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _reactNative = require("react-native"); var _reactNativeVideo = _interopRequireDefault(require("react-native-video")); var _dedupe = _interopRequireDefault(require("classnames/dedupe")); var _reactNativeBridge = require("@wordpress/react-native-bridge"); var _i18n = require("@wordpress/i18n"); var _components = require("@wordpress/components"); var _blockEditor = require("@wordpress/block-editor"); var _compose = require("@wordpress/compose"); var _data = require("@wordpress/data"); var _icons = require("@wordpress/icons"); var _url = require("@wordpress/url"); var _editPost = require("@wordpress/edit-post"); var _style = _interopRequireDefault(require("./style.scss")); var _shared = require("./shared"); var _controls = _interopRequireDefault(require("./controls")); var _useCoverIsDark = _interopRequireDefault(require("./use-cover-is-dark")); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Constants */ const INNER_BLOCKS_TEMPLATE = [['core/paragraph', { align: 'center', placeholder: (0, _i18n.__)('Write title…') }]]; const Cover = _ref => { var _style$color, _styles$overlay; let { attributes, getStylesFromColorScheme, isParentSelected, onFocus, setAttributes, openGeneralSidebar, closeSettingsBottomSheet, isSelected, selectBlock, blockWidth, hasInnerBlocks } = _ref; const { backgroundType, dimRatio, focalPoint, minHeight, url, id, style, customOverlayColor, minHeightUnit = 'px', allowedBlocks, templateLock, customGradient, gradient, overlayColor, isDark } = attributes; const [isScreenReaderEnabled, setIsScreenReaderEnabled] = (0, _element.useState)(false); (0, _element.useEffect)(() => { let isCurrent = true; // Sync with local media store. (0, _reactNativeBridge.mediaUploadSync)(); const a11yInfoChangeSubscription = _reactNative.AccessibilityInfo.addEventListener('screenReaderChanged', setIsScreenReaderEnabled); _reactNative.AccessibilityInfo.isScreenReaderEnabled().then(() => { if (isCurrent) { setIsScreenReaderEnabled(); } }); return () => { isCurrent = false; a11yInfoChangeSubscription.remove(); }; }, []); const convertedMinHeight = (0, _components.useConvertUnitToMobile)(minHeight || _shared.COVER_DEFAULT_HEIGHT, minHeightUnit); const isImage = backgroundType === _blockEditor.MEDIA_TYPE_IMAGE; const THEME_COLORS_COUNT = 4; const colorsDefault = (0, _components.useMobileGlobalStylesColors)(); const coverDefaultPalette = (0, _element.useMemo)(() => { return { colors: colorsDefault.slice(0, THEME_COLORS_COUNT) }; }, [colorsDefault]); const gradients = (0, _components.useMobileGlobalStylesColors)('gradients'); const gradientValue = customGradient || (0, _blockEditor.getGradientValueBySlug)(gradients, gradient); const overlayColorValue = (0, _blockEditor.getColorObjectByAttributeValues)(colorsDefault, overlayColor); const hasBackground = !!(url || style && style.color && style.color.background || attributes.overlayColor || overlayColorValue.color || customOverlayColor || gradientValue); const hasOnlyColorBackground = !url && (hasBackground || hasInnerBlocks); const [isCustomColorPickerShowing, setCustomColorPickerShowing] = (0, _element.useState)(false); const openMediaOptionsRef = (0, _element.useRef)(); // Initialize uploading flag to false, awaiting sync. const [isUploadInProgress, setIsUploadInProgress] = (0, _element.useState)(false); // Initialize upload failure flag to true if url is local. const [didUploadFail, setDidUploadFail] = (0, _element.useState)(id && (0, _url.getProtocol)(url) === 'file:'); // Don't show failure if upload is in progress. const shouldShowFailure = didUploadFail && !isUploadInProgress; const onSelectMedia = media => { setDidUploadFail(false); const onSelect = (0, _shared.attributesFromMedia)(setAttributes, dimRatio); onSelect(media); }; const onMediaPressed = () => { if (isUploadInProgress) { (0, _reactNativeBridge.requestImageUploadCancelDialog)(id); } else if (shouldShowFailure) { (0, _reactNativeBridge.requestImageFailedRetryDialog)(id); } else if (isImage && url) { (0, _reactNativeBridge.requestImageFullscreenPreview)(url); } }; const [isVideoLoading, setIsVideoLoading] = (0, _element.useState)(true); const onVideoLoadStart = () => { setIsVideoLoading(true); }; const onVideoLoad = () => { setIsVideoLoading(false); }; const onClearMedia = (0, _element.useCallback)(() => { setAttributes({ focalPoint: undefined, hasParallax: undefined, id: undefined, url: undefined }); closeSettingsBottomSheet(); }, [closeSettingsBottomSheet]); function setColor(color) { var _colorValue$slug, _ref2; const colorValue = (0, _blockEditor.getColorObjectByColorValue)(colorsDefault, color); setAttributes({ // Clear all related attributes (only one should be set). overlayColor: (_colorValue$slug = colorValue === null || colorValue === void 0 ? void 0 : colorValue.slug) !== null && _colorValue$slug !== void 0 ? _colorValue$slug : undefined, customOverlayColor: (_ref2 = !(colorValue !== null && colorValue !== void 0 && colorValue.slug) && color) !== null && _ref2 !== void 0 ? _ref2 : undefined, gradient: undefined, customGradient: undefined }); } function openColorPicker() { selectBlock(); setCustomColorPickerShowing(true); openGeneralSidebar(); } const { __unstableMarkNextChangeAsNotPersistent } = (0, _data.useDispatch)(_blockEditor.store); const isCoverDark = (0, _useCoverIsDark.default)(isDark, url, dimRatio, overlayColorValue === null || overlayColorValue === void 0 ? void 0 : overlayColorValue.color); (0, _element.useEffect)(() => { var _attributes$className; // This side-effect should not create an undo level. __unstableMarkNextChangeAsNotPersistent(); // Used to set a default color for its InnerBlocks // since there's no system to inherit styles yet // the RichText component will check if there are // parent styles for the current block. If there are, // it will use that color instead. setAttributes({ isDark: isCoverDark, childrenStyles: isCoverDark ? _style.default.defaultColor : _style.default.defaultColorLightMode }); // Ensure that "is-light" is removed from "className" attribute if cover background is dark. if (isCoverDark && (_attributes$className = attributes.className) !== null && _attributes$className !== void 0 && _attributes$className.includes('is-light')) { const className = (0, _dedupe.default)(attributes.className, { 'is-light': false }); setAttributes({ className: className !== '' ? className : undefined }); } }, [isCoverDark]); const backgroundColor = getStylesFromColorScheme(_style.default.backgroundSolid, _style.default.backgroundSolidDark); const overlayStyles = [_style.default.overlay, url && { opacity: dimRatio / 100 }, !gradientValue && { backgroundColor: customOverlayColor || (overlayColorValue === null || overlayColorValue === void 0 ? void 0 : overlayColorValue.color) || (style === null || style === void 0 ? void 0 : (_style$color = style.color) === null || _style$color === void 0 ? void 0 : _style$color.background) || ((_styles$overlay = _style.default.overlay) === null || _styles$overlay === void 0 ? void 0 : _styles$overlay.color) }, // While we don't support theme colors we add a default bg color. !overlayColorValue.color && !url ? backgroundColor : {}, isImage && isParentSelected && !isUploadInProgress && !didUploadFail && _style.default.overlaySelected]; const placeholderIconStyle = getStylesFromColorScheme(_style.default.icon, _style.default.iconDark); const placeholderIcon = (0, _element.createElement)(_components.Icon, (0, _extends2.default)({ icon: _icons.cover }, placeholderIconStyle)); const toolbarControls = open => (0, _element.createElement)(_blockEditor.BlockControls, { group: "other" }, (0, _element.createElement)(_components.ToolbarButton, { title: (0, _i18n.__)('Edit cover media'), icon: _icons.replace, onClick: open })); const accessibilityHint = _reactNative.Platform.OS === 'ios' ? (0, _i18n.__)('Double tap to open Action Sheet to add image or video') : (0, _i18n.__)('Double tap to open Bottom Sheet to add image or video'); const addMediaButton = () => (0, _element.createElement)(_reactNative.TouchableWithoutFeedback, { accessibilityHint: accessibilityHint, accessibilityLabel: (0, _i18n.__)('Add image or video'), accessibilityRole: "button", onPress: openMediaOptionsRef.current }, (0, _element.createElement)(_reactNative.View, { style: _style.default.selectImageContainer }, (0, _element.createElement)(_reactNative.View, { style: _style.default.selectImage }, (0, _element.createElement)(_components.Icon, (0, _extends2.default)({ size: 16, icon: _icons.image }, _style.default.selectImageIcon))))); const onBottomSheetClosed = (0, _element.useCallback)(() => { _reactNative.InteractionManager.runAfterInteractions(() => { setCustomColorPickerShowing(false); }); }, []); const colorPickerControls = (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_components.BottomSheetConsumer, null, _ref3 => { let { shouldEnableBottomSheetScroll, shouldEnableBottomSheetMaxHeight, onHandleClosingBottomSheet, onHandleHardwareButtonPress, isBottomSheetContentScrolling } = _ref3; return (0, _element.createElement)(_components.ColorPicker, { shouldEnableBottomSheetScroll: shouldEnableBottomSheetScroll, shouldEnableBottomSheetMaxHeight: shouldEnableBottomSheetMaxHeight, setColor: setColor, onNavigationBack: closeSettingsBottomSheet, onHandleClosingBottomSheet: onHandleClosingBottomSheet, onHandleHardwareButtonPress: onHandleHardwareButtonPress, onBottomSheetClosed: onBottomSheetClosed, isBottomSheetContentScrolling: isBottomSheetContentScrolling, bottomLabelText: (0, _i18n.__)('Select a color') }); })); const renderContent = getMediaOptions => (0, _element.createElement)(_element.Fragment, null, renderBackground(getMediaOptions), isParentSelected && hasOnlyColorBackground && addMediaButton()); const renderBackground = getMediaOptions => { var _styles$image; return (0, _element.createElement)(_reactNative.TouchableWithoutFeedback, { accessible: !isParentSelected, onPress: onMediaPressed, disabled: !isParentSelected }, (0, _element.createElement)(_reactNative.View, { style: [_style.default.background, backgroundColor] }, getMediaOptions(), isParentSelected && backgroundType === _shared.VIDEO_BACKGROUND_TYPE && toolbarControls(openMediaOptionsRef.current), (0, _element.createElement)(_blockEditor.MediaUploadProgress, { mediaId: id, onUpdateMediaProgress: () => { setIsUploadInProgress(true); }, onFinishMediaUploadWithSuccess: _ref4 => { let { mediaServerId, mediaUrl } = _ref4; setIsUploadInProgress(false); setDidUploadFail(false); setAttributes({ id: mediaServerId, url: mediaUrl, backgroundType }); }, onFinishMediaUploadWithFailure: () => { setIsUploadInProgress(false); setDidUploadFail(true); }, onMediaUploadStateReset: () => { setIsUploadInProgress(false); setDidUploadFail(false); setAttributes({ id: undefined, url: undefined }); } }), _shared.IMAGE_BACKGROUND_TYPE === backgroundType && (0, _element.createElement)(_reactNative.View, { style: _style.default.imageContainer }, (0, _element.createElement)(_components.Image, { editButton: false, focalPoint: focalPoint || _components.IMAGE_DEFAULT_FOCAL_POINT, isSelected: isParentSelected, isUploadFailed: didUploadFail, isUploadInProgress: isUploadInProgress, onSelectMediaUploadOption: onSelectMedia, openMediaOptions: openMediaOptionsRef.current, url: url, width: (_styles$image = _style.default.image) === null || _styles$image === void 0 ? void 0 : _styles$image.width })), _shared.VIDEO_BACKGROUND_TYPE === backgroundType && (0, _element.createElement)(_reactNativeVideo.default, { muted: true, disableFocus: true, repeat: true, resizeMode: 'cover', source: { uri: url }, onLoad: onVideoLoad, onLoadStart: onVideoLoadStart, style: [_style.default.background, // Hide Video component since it has black background while loading the source. { opacity: isVideoLoading ? 0 : 1 }] }))); }; if (!hasBackground && !hasInnerBlocks || isCustomColorPickerShowing) { var _styles$mediaPlacehol; return (0, _element.createElement)(_reactNative.View, null, isCustomColorPickerShowing && colorPickerControls, (0, _element.createElement)(_blockEditor.MediaPlaceholder, { height: (_styles$mediaPlacehol = _style.default.mediaPlaceholderEmptyStateContainer) === null || _styles$mediaPlacehol === void 0 ? void 0 : _styles$mediaPlacehol.height, backgroundColor: customOverlayColor, hideContent: customOverlayColor !== '' && customOverlayColor !== undefined, icon: placeholderIcon, labels: { title: (0, _i18n.__)('Cover') }, onSelect: onSelectMedia, allowedTypes: _shared.ALLOWED_MEDIA_TYPES, onFocus: onFocus }, (0, _element.createElement)(_reactNative.View, { style: _style.default.colorPaletteWrapper, pointerEvents: isScreenReaderEnabled ? 'none' : 'auto' }, (0, _element.createElement)(_components.BottomSheetConsumer, null, _ref5 => { let { shouldEnableBottomSheetScroll } = _ref5; return (0, _element.createElement)(_components.ColorPalette, { customColorIndicatorStyles: _style.default.paletteColorIndicator, customIndicatorWrapperStyles: _style.default.paletteCustomIndicatorWrapper, setColor: setColor, onCustomPress: openColorPicker, defaultSettings: coverDefaultPalette, shouldShowCustomLabel: false, shouldShowCustomVerticalSeparator: false, shouldEnableBottomSheetScroll: shouldEnableBottomSheetScroll }); })))); } return (0, _element.createElement)(_reactNative.View, { style: _style.default.backgroundContainer }, isSelected && (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_controls.default, { attributes: attributes, didUploadFail: didUploadFail, hasOnlyColorBackground: hasOnlyColorBackground, isUploadInProgress: isUploadInProgress, onClearMedia: onClearMedia, onSelectMedia: onSelectMedia, setAttributes: setAttributes })), (0, _element.createElement)(_reactNative.View, { pointerEvents: "box-none", style: [_style.default.content, { minHeight: convertedMinHeight }] }, (0, _element.createElement)(_blockEditor.InnerBlocks, { allowedBlocks: allowedBlocks, template: INNER_BLOCKS_TEMPLATE, templateLock: templateLock, templateInsertUpdatesSelection: true, blockWidth: blockWidth })), (0, _element.createElement)(_reactNative.View, { pointerEvents: "none", style: _style.default.overlayContainer }, (0, _element.createElement)(_reactNative.View, { style: overlayStyles }, gradientValue && (0, _element.createElement)(_components.Gradient, { gradientValue: gradientValue, style: _style.default.background }))), (0, _element.createElement)(_blockEditor.MediaUpload, { allowedTypes: _shared.ALLOWED_MEDIA_TYPES, isReplacingMedia: !hasOnlyColorBackground, onSelect: onSelectMedia, render: _ref6 => { let { open, getMediaOptions } = _ref6; openMediaOptionsRef.current = open; return renderContent(getMediaOptions); } }), isImage && url && openMediaOptionsRef.current && isParentSelected && !isUploadInProgress && !didUploadFail && (0, _element.createElement)(_reactNative.View, { style: _style.default.imageEditButton }, (0, _element.createElement)(_components.ImageEditingButton, { onSelectMediaUploadOption: onSelectMedia, openMediaOptions: openMediaOptionsRef.current, pickerOptions: [{ destructiveButton: true, id: 'clearMedia', label: (0, _i18n.__)('Clear Media'), onPress: onClearMedia, separated: true, value: 'clearMedia' }], url: url })), shouldShowFailure && (0, _element.createElement)(_reactNative.View, { pointerEvents: "none", style: _style.default.uploadFailedContainer }, (0, _element.createElement)(_reactNative.View, { style: _style.default.uploadFailed }, (0, _element.createElement)(_components.Icon, (0, _extends2.default)({ icon: _icons.warning }, _style.default.uploadFailedIcon))))); }; var _default = (0, _compose.compose)([(0, _data.withSelect)((select, _ref7) => { var _getBlock; let { clientId } = _ref7; const { getSelectedBlockClientId, getBlock } = select(_blockEditor.store); const selectedBlockClientId = getSelectedBlockClientId(); const { getSettings } = select(_blockEditor.store); const hasInnerBlocks = ((_getBlock = getBlock(clientId)) === null || _getBlock === void 0 ? void 0 : _getBlock.innerBlocks.length) > 0; return { settings: getSettings(), isParentSelected: selectedBlockClientId === clientId, hasInnerBlocks }; }), (0, _data.withDispatch)((dispatch, _ref8) => { let { clientId } = _ref8; const { openGeneralSidebar } = dispatch(_editPost.store); const { selectBlock } = dispatch(_blockEditor.store); return { openGeneralSidebar: () => openGeneralSidebar('edit-post/block'), closeSettingsBottomSheet() { dispatch(_editPost.store).closeGeneralSidebar(); }, selectBlock: () => selectBlock(clientId) }; }), _compose.withPreferredColorScheme])(Cover); exports.default = _default; //# sourceMappingURL=edit.native.js.map