UNPKG

@wordpress/block-library

Version:
415 lines (414 loc) 13.7 kB
// packages/block-library/src/cover/edit/inspector-controls.js 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"; 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 PosterImage from "../../utils/poster-image"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var { 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) : void 0; if (isNaN(inputValue) && inputValue !== void 0) { 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, onChange: handleOnChange, onUnitChange, units, value: computedValue } ); } function CoverInspectorControls({ attributes, setAttributes, clientId, setOverlayColor, coverRef, currentSettings, updateDimRatio, featuredImage }) { const { useFeaturedImage, id, dimRatio, focalPoint, hasParallax, isRepeated, minHeight, minHeightUnit, alt, tagName, poster } = 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).getEntityRecord( "postType", "attachment", 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: void 0 } : {} }); }; 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 || useFeaturedImage) && /* @__PURE__ */ jsxs( ToolsPanel, { label: __("Settings"), resetAll: () => { setAttributes({ hasParallax: false, focalPoint: void 0, isRepeated: false, alt: "", poster: void 0 }); updateImage(DEFAULT_MEDIA_SIZE_SLUG); }, dropdownMenuProps, children: [ isImageBackground && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( ToolsPanelItem, { label: __("Fixed background"), isShownByDefault: true, hasValue: () => !!hasParallax, onDeselect: () => setAttributes({ hasParallax: false, focalPoint: void 0 }), 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: void 0 }), children: /* @__PURE__ */ jsx( FocalPointPicker, { __nextHasNoMarginBottom: true, label: __("Focal point"), url, value: focalPoint, onDragStart: imperativeFocalPointPreview, onDrag: imperativeFocalPointPreview, onChange: (newFocalPoint) => setAttributes({ focalPoint: newFocalPoint }) } ) } ), isVideoBackground && /* @__PURE__ */ jsx( PosterImage, { poster, onChange: (posterImage) => setAttributes({ poster: posterImage?.url }) } ), !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: void 0, customOverlayColor: void 0, gradient: void 0, customGradient: void 0 }), clearable: true } ], panelId: clientId, ...colorGradientSettings } ), /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: () => { return dimRatio === void 0 ? 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: void 0, minHeightUnit: void 0 }), resetAllFilter: () => ({ minHeight: void 0, minHeightUnit: void 0 }), 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: void 0 // Reset aspect ratio when minHeight is set. } }) }), onUnitChange: (nextUnit) => setAttributes({ minHeightUnit: nextUnit }) } ) } ) }), /* @__PURE__ */ jsx(InspectorControls, { group: "advanced", children: /* @__PURE__ */ jsx( HTMLElementControl, { tagName, onChange: (value) => setAttributes({ tagName: value }), 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" } ] } ) }) ] }); } export { CoverInspectorControls as default }; //# sourceMappingURL=inspector-controls.js.map