UNPKG

@wordpress/block-library

Version:
356 lines (355 loc) 12.2 kB
/** * WordPress dependencies */ import { useMemo } from '@wordpress/element'; import { ExternalLink, FocalPointPicker, RangeControl, TextareaControl, ToggleControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalUnitControl as UnitControl, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; import { InspectorControls, useSettings, store as blockEditorStore, __experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown, __experimentalUseGradient, __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ import { COVER_MIN_HEIGHT, mediaPosition } from '../shared'; import { unlock } from '../../lock-unlock'; import { useToolsPanelDropdownMenuProps } from '../../utils/hooks'; import { DEFAULT_MEDIA_SIZE_SLUG } from '../constants'; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; const { cleanEmptyObject, ResolutionTool, HTMLElementControl } = unlock(blockEditorPrivateApis); function CoverHeightInput({ onChange, onUnitChange, unit = 'px', value = '' }) { const instanceId = useInstanceId(UnitControl); const inputId = `block-cover-height-input-${instanceId}`; const isPx = unit === 'px'; const [availableUnits] = useSettings('spacing.units'); const units = useCustomUnits({ availableUnits: availableUnits || ['px', 'em', 'rem', 'vw', 'vh'], defaultValues: { px: 430, '%': 20, em: 20, rem: 20, vw: 20, vh: 50 } }); const handleOnChange = unprocessedValue => { const inputValue = unprocessedValue !== '' ? parseFloat(unprocessedValue) : undefined; if (isNaN(inputValue) && inputValue !== undefined) { return; } onChange(inputValue); }; const computedValue = useMemo(() => { const [parsedQuantity] = parseQuantityAndUnitFromRawValue(value); return [parsedQuantity, unit].join(''); }, [unit, value]); const min = isPx ? COVER_MIN_HEIGHT : 0; return /*#__PURE__*/_jsx(UnitControl, { __next40pxDefaultSize: true, label: __('Minimum height'), id: inputId, isResetValueOnUnitChange: true, min: min, onChange: handleOnChange, onUnitChange: onUnitChange, units: units, value: computedValue }); } export default function CoverInspectorControls({ attributes, setAttributes, clientId, setOverlayColor, coverRef, currentSettings, updateDimRatio, featuredImage }) { const { useFeaturedImage, id, dimRatio, focalPoint, hasParallax, isRepeated, minHeight, minHeightUnit, alt, tagName } = attributes; const { isVideoBackground, isImageBackground, mediaElement, url, overlayColor } = currentSettings; const sizeSlug = attributes.sizeSlug || DEFAULT_MEDIA_SIZE_SLUG; const { gradientValue, setGradient } = __experimentalUseGradient(); const { getSettings } = useSelect(blockEditorStore); const imageSizes = getSettings()?.imageSizes; const image = useSelect(select => id && isImageBackground ? select(coreStore).getMedia(id, { context: 'view' }) : null, [id, isImageBackground]); const currentBackgroundImage = useFeaturedImage ? featuredImage : image; function updateImage(newSizeSlug) { const newUrl = currentBackgroundImage?.media_details?.sizes?.[newSizeSlug]?.source_url; if (!newUrl) { return null; } setAttributes({ url: newUrl, sizeSlug: newSizeSlug }); } const imageSizeOptions = imageSizes?.filter(({ slug }) => currentBackgroundImage?.media_details?.sizes?.[slug]?.source_url)?.map(({ name, slug }) => ({ value: slug, label: name })); const toggleParallax = () => { setAttributes({ hasParallax: !hasParallax, ...(!hasParallax ? { focalPoint: undefined } : {}) }); }; const toggleIsRepeated = () => { setAttributes({ isRepeated: !isRepeated }); }; const showFocalPointPicker = isVideoBackground || isImageBackground && (!hasParallax || isRepeated); const imperativeFocalPointPreview = value => { const [styleOfRef, property] = mediaElement.current ? [mediaElement.current.style, 'objectPosition'] : [coverRef.current.style, 'backgroundPosition']; styleOfRef[property] = mediaPosition(value); }; const colorGradientSettings = useMultipleOriginColorsAndGradients(); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(InspectorControls, { children: !!url && /*#__PURE__*/_jsxs(ToolsPanel, { label: __('Settings'), resetAll: () => { setAttributes({ hasParallax: false, focalPoint: undefined, isRepeated: false, alt: '', sizeSlug: undefined }); }, dropdownMenuProps: dropdownMenuProps, children: [isImageBackground && /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(ToolsPanelItem, { label: __('Fixed background'), isShownByDefault: true, hasValue: () => hasParallax, onDeselect: () => setAttributes({ hasParallax: false, focalPoint: undefined }), children: /*#__PURE__*/_jsx(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Fixed background'), checked: hasParallax, onChange: toggleParallax }) }), /*#__PURE__*/_jsx(ToolsPanelItem, { label: __('Repeated background'), isShownByDefault: true, hasValue: () => isRepeated, onDeselect: () => setAttributes({ isRepeated: false }), children: /*#__PURE__*/_jsx(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Repeated background'), checked: isRepeated, onChange: toggleIsRepeated }) })] }), showFocalPointPicker && /*#__PURE__*/_jsx(ToolsPanelItem, { label: __('Focal point'), isShownByDefault: true, hasValue: () => !!focalPoint, onDeselect: () => setAttributes({ focalPoint: undefined }), children: /*#__PURE__*/_jsx(FocalPointPicker, { __nextHasNoMarginBottom: true, label: __('Focal point'), url: url, value: focalPoint, onDragStart: imperativeFocalPointPreview, onDrag: imperativeFocalPointPreview, onChange: newFocalPoint => setAttributes({ focalPoint: newFocalPoint }) }) }), !useFeaturedImage && url && !isVideoBackground && /*#__PURE__*/_jsx(ToolsPanelItem, { label: __('Alternative text'), isShownByDefault: true, hasValue: () => !!alt, onDeselect: () => setAttributes({ alt: '' }), children: /*#__PURE__*/_jsx(TextareaControl, { __nextHasNoMarginBottom: true, label: __('Alternative text'), value: alt, onChange: newAlt => setAttributes({ alt: newAlt }), help: /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(ExternalLink, { href: // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. __('https://www.w3.org/WAI/tutorials/images/decision-tree/'), children: __('Describe the purpose of the image.') }), /*#__PURE__*/_jsx("br", {}), __('Leave empty if decorative.')] }) }) }), !!imageSizeOptions?.length && /*#__PURE__*/_jsx(ResolutionTool, { value: sizeSlug, onChange: updateImage, options: imageSizeOptions, defaultValue: DEFAULT_MEDIA_SIZE_SLUG })] }) }), colorGradientSettings.hasColorsOrGradients && /*#__PURE__*/_jsxs(InspectorControls, { group: "color", children: [/*#__PURE__*/_jsx(ColorGradientSettingsDropdown, { __experimentalIsRenderedInSidebar: true, settings: [{ colorValue: overlayColor.color, gradientValue, label: __('Overlay'), onColorChange: setOverlayColor, onGradientChange: setGradient, isShownByDefault: true, resetAllFilter: () => ({ overlayColor: undefined, customOverlayColor: undefined, gradient: undefined, customGradient: undefined }), clearable: true }], panelId: clientId, ...colorGradientSettings }), /*#__PURE__*/_jsx(ToolsPanelItem, { hasValue: () => { // If there's a media background the dimRatio will be // defaulted to 50 whereas it will be 100 for colors. return dimRatio === undefined ? false : dimRatio !== (url ? 50 : 100); }, label: __('Overlay opacity'), onDeselect: () => updateDimRatio(url ? 50 : 100), resetAllFilter: () => ({ dimRatio: url ? 50 : 100 }), isShownByDefault: true, panelId: clientId, children: /*#__PURE__*/_jsx(RangeControl, { __nextHasNoMarginBottom: true, label: __('Overlay opacity'), value: dimRatio, onChange: newDimRatio => updateDimRatio(newDimRatio), min: 0, max: 100, step: 10, required: true, __next40pxDefaultSize: true }) })] }), /*#__PURE__*/_jsx(InspectorControls, { group: "dimensions", children: /*#__PURE__*/_jsx(ToolsPanelItem, { className: "single-column", hasValue: () => !!minHeight, label: __('Minimum height'), onDeselect: () => setAttributes({ minHeight: undefined, minHeightUnit: undefined }), resetAllFilter: () => ({ minHeight: undefined, minHeightUnit: undefined }), isShownByDefault: true, panelId: clientId, children: /*#__PURE__*/_jsx(CoverHeightInput, { value: attributes?.style?.dimensions?.aspectRatio ? '' : minHeight, unit: minHeightUnit, onChange: newMinHeight => setAttributes({ minHeight: newMinHeight, style: cleanEmptyObject({ ...attributes?.style, dimensions: { ...attributes?.style?.dimensions, aspectRatio: undefined // Reset aspect ratio when minHeight is set. } }) }), onUnitChange: nextUnit => setAttributes({ minHeightUnit: nextUnit }) }) }) }), /*#__PURE__*/_jsx(InspectorControls, { group: "advanced", children: /*#__PURE__*/_jsx(HTMLElementControl, { tagName: tagName, onChange: value => setAttributes({ tagName: value }), clientId: clientId, options: [{ label: __('Default (<div>)'), value: 'div' }, { label: '<header>', value: 'header' }, { label: '<main>', value: 'main' }, { label: '<section>', value: 'section' }, { label: '<article>', value: 'article' }, { label: '<aside>', value: 'aside' }, { label: '<footer>', value: 'footer' }] }) })] }); } //# sourceMappingURL=inspector-controls.js.map