UNPKG

@wordpress/block-editor

Version:
514 lines (472 loc) 17.1 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import { createElement } from "@wordpress/element"; /** * External dependencies */ import classnames from 'classnames'; /** * WordPress dependencies */ import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalHStack as HStack, __experimentalZStack as ZStack, __experimentalDropdownContentWrapper as DropdownContentWrapper, TabPanel, ColorIndicator, Flex, FlexItem, Dropdown, Button } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ import ColorGradientControl from '../colors-gradients/control'; import { useColorsPerOrigin, useGradientsPerOrigin } from './hooks'; import { getValueFromVariable } from './utils'; import { setImmutably } from '../../utils/object'; export function useHasColorPanel(settings) { const hasTextPanel = useHasTextPanel(settings); const hasBackgroundPanel = useHasBackgroundPanel(settings); const hasLinkPanel = useHasLinkPanel(settings); const hasHeadingPanel = useHasHeadingPanel(settings); const hasButtonPanel = useHasHeadingPanel(settings); const hasCaptionPanel = useHasCaptionPanel(settings); return hasTextPanel || hasBackgroundPanel || hasLinkPanel || hasHeadingPanel || hasButtonPanel || hasCaptionPanel; } export function useHasTextPanel(settings) { const colors = useColorsPerOrigin(settings); return settings?.color?.text && (colors?.length > 0 || settings?.color?.custom); } export function useHasLinkPanel(settings) { const colors = useColorsPerOrigin(settings); return settings?.color?.link && (colors?.length > 0 || settings?.color?.custom); } export function useHasCaptionPanel(settings) { const colors = useColorsPerOrigin(settings); return settings?.color?.caption && (colors?.length > 0 || settings?.color?.custom); } export function useHasHeadingPanel(settings) { const colors = useColorsPerOrigin(settings); const gradients = useGradientsPerOrigin(settings); return settings?.color?.heading && (colors?.length > 0 || settings?.color?.custom || gradients?.length > 0 || settings?.color?.customGradient); } export function useHasButtonPanel(settings) { const colors = useColorsPerOrigin(settings); const gradients = useGradientsPerOrigin(settings); return settings?.color?.button && (colors?.length > 0 || settings?.color?.custom || gradients?.length > 0 || settings?.color?.customGradient); } export function useHasBackgroundPanel(settings) { const colors = useColorsPerOrigin(settings); const gradients = useGradientsPerOrigin(settings); return settings?.color?.background && (colors?.length > 0 || settings?.color?.custom || gradients?.length > 0 || settings?.color?.customGradient); } function ColorToolsPanel({ resetAllFilter, onChange, value, panelId, children }) { const resetAll = () => { const updatedValue = resetAllFilter(value); onChange(updatedValue); }; return createElement(ToolsPanel, { label: __('Color'), resetAll: resetAll, panelId: panelId, hasInnerWrapper: true, className: "color-block-support-panel", __experimentalFirstVisibleItemClass: "first", __experimentalLastVisibleItemClass: "last" }, createElement("div", { className: "color-block-support-panel__inner-wrapper" }, children)); } const DEFAULT_CONTROLS = { text: true, background: true, link: true, heading: true, button: true, caption: true }; const popoverProps = { placement: 'left-start', offset: 36, shift: true }; const LabeledColorIndicators = ({ indicators, label }) => createElement(HStack, { justify: "flex-start" }, createElement(ZStack, { isLayered: false, offset: -8 }, indicators.map((indicator, index) => createElement(Flex, { key: index, expanded: false }, createElement(ColorIndicator, { colorValue: indicator })))), createElement(FlexItem, { className: "block-editor-panel-color-gradient-settings__color-name", title: label }, label)); function ColorPanelTab({ isGradient, inheritedValue, userValue, setValue, colorGradientControlSettings }) { return createElement(ColorGradientControl, _extends({}, colorGradientControlSettings, { showTitle: false, enableAlpha: true, __experimentalIsRenderedInSidebar: true, colorValue: isGradient ? undefined : inheritedValue, gradientValue: isGradient ? inheritedValue : undefined, onColorChange: isGradient ? undefined : setValue, onGradientChange: isGradient ? setValue : undefined, clearable: inheritedValue === userValue, headingLevel: 3 })); } function ColorPanelDropdown({ label, hasValue, resetValue, isShownByDefault, indicators, tabs, colorGradientControlSettings, panelId }) { const tabConfigs = tabs.map(({ key, label: tabLabel }) => { return { name: key, title: tabLabel }; }); return createElement(ToolsPanelItem, { className: "block-editor-tools-panel-color-gradient-settings__item", hasValue: hasValue, label: label, onDeselect: resetValue, isShownByDefault: isShownByDefault, panelId: panelId }, createElement(Dropdown, { popoverProps: popoverProps, className: "block-editor-tools-panel-color-gradient-settings__dropdown", renderToggle: ({ onToggle, isOpen }) => { const toggleProps = { onClick: onToggle, className: classnames('block-editor-panel-color-gradient-settings__dropdown', { 'is-open': isOpen }), 'aria-expanded': isOpen, 'aria-label': sprintf( /* translators: %s is the type of color property, e.g., "background" */ __('Color %s styles'), label) }; return createElement(Button, toggleProps, createElement(LabeledColorIndicators, { indicators: indicators, label: label })); }, renderContent: () => createElement(DropdownContentWrapper, { paddingSize: "none" }, createElement("div", { className: "block-editor-panel-color-gradient-settings__dropdown-content" }, tabs.length === 1 && createElement(ColorPanelTab, _extends({}, tabs[0], { colorGradientControlSettings: colorGradientControlSettings })), tabs.length > 1 && createElement(TabPanel, { tabs: tabConfigs }, tab => { const selectedTab = tabs.find(t => t.key === tab.name); if (!selectedTab) { return null; } return createElement(ColorPanelTab, _extends({}, selectedTab, { colorGradientControlSettings: colorGradientControlSettings })); }))) })); } export default function ColorPanel({ as: Wrapper = ColorToolsPanel, value, onChange, inheritedValue = value, settings, panelId, defaultControls = DEFAULT_CONTROLS, children }) { const colors = useColorsPerOrigin(settings); const gradients = useGradientsPerOrigin(settings); const areCustomSolidsEnabled = settings?.color?.custom; const areCustomGradientsEnabled = settings?.color?.customGradient; const hasSolidColors = colors.length > 0 || areCustomSolidsEnabled; const hasGradientColors = gradients.length > 0 || areCustomGradientsEnabled; const decodeValue = rawValue => getValueFromVariable({ settings }, '', rawValue); const encodeColorValue = colorValue => { const allColors = colors.flatMap(({ colors: originColors }) => originColors); const colorObject = allColors.find(({ color }) => color === colorValue); return colorObject ? 'var:preset|color|' + colorObject.slug : colorValue; }; const encodeGradientValue = gradientValue => { const allGradients = gradients.flatMap(({ gradients: originGradients }) => originGradients); const gradientObject = allGradients.find(({ gradient }) => gradient === gradientValue); return gradientObject ? 'var:preset|gradient|' + gradientObject.slug : gradientValue; }; // Text Color const showTextPanel = useHasTextPanel(settings); const textColor = decodeValue(inheritedValue?.color?.text); const userTextColor = decodeValue(value?.color?.text); const hasTextColor = () => !!userTextColor; const setTextColor = newColor => { onChange(setImmutably(value, ['color', 'text'], encodeColorValue(newColor))); }; const resetTextColor = () => setTextColor(undefined); // BackgroundColor const showBackgroundPanel = useHasBackgroundPanel(settings); const backgroundColor = decodeValue(inheritedValue?.color?.background); const userBackgroundColor = decodeValue(value?.color?.background); const gradient = decodeValue(inheritedValue?.color?.gradient); const userGradient = decodeValue(value?.color?.gradient); const hasBackground = () => !!userBackgroundColor || !!userGradient; const setBackgroundColor = newColor => { const newValue = setImmutably(value, ['color', 'background'], encodeColorValue(newColor)); newValue.color.gradient = undefined; onChange(newValue); }; const setGradient = newGradient => { const newValue = setImmutably(value, ['color', 'gradient'], encodeGradientValue(newGradient)); newValue.color.background = undefined; onChange(newValue); }; const resetBackground = () => { const newValue = setImmutably(value, ['color', 'background'], undefined); newValue.color.gradient = undefined; onChange(newValue); }; // Links const showLinkPanel = useHasLinkPanel(settings); const linkColor = decodeValue(inheritedValue?.elements?.link?.color?.text); const userLinkColor = decodeValue(value?.elements?.link?.color?.text); const setLinkColor = newColor => { onChange(setImmutably(value, ['elements', 'link', 'color', 'text'], encodeColorValue(newColor))); }; const hoverLinkColor = decodeValue(inheritedValue?.elements?.link?.[':hover']?.color?.text); const userHoverLinkColor = decodeValue(value?.elements?.link?.[':hover']?.color?.text); const setHoverLinkColor = newColor => { onChange(setImmutably(value, ['elements', 'link', ':hover', 'color', 'text'], encodeColorValue(newColor))); }; const hasLink = () => !!userLinkColor || !!userHoverLinkColor; const resetLink = () => { let newValue = setImmutably(value, ['elements', 'link', ':hover', 'color', 'text'], undefined); newValue = setImmutably(newValue, ['elements', 'link', 'color', 'text'], undefined); onChange(newValue); }; // Elements const elements = [{ name: 'caption', label: __('Captions'), showPanel: useHasCaptionPanel(settings) }, { name: 'button', label: __('Button'), showPanel: useHasButtonPanel(settings) }, { name: 'heading', label: __('Heading'), showPanel: useHasHeadingPanel(settings) }, { name: 'h1', label: __('H1'), showPanel: useHasHeadingPanel(settings) }, { name: 'h2', label: __('H2'), showPanel: useHasHeadingPanel(settings) }, { name: 'h3', label: __('H3'), showPanel: useHasHeadingPanel(settings) }, { name: 'h4', label: __('H4'), showPanel: useHasHeadingPanel(settings) }, { name: 'h5', label: __('H5'), showPanel: useHasHeadingPanel(settings) }, { name: 'h6', label: __('H6'), showPanel: useHasHeadingPanel(settings) }]; const resetAllFilter = useCallback(previousValue => { return { ...previousValue, color: undefined, elements: { ...previousValue?.elements, link: { ...previousValue?.elements?.link, color: undefined, ':hover': { color: undefined } }, ...elements.reduce((acc, element) => { return { ...acc, [element.name]: { ...previousValue?.elements?.[element.name], color: undefined } }; }, {}) } }; }, []); const items = [showTextPanel && { key: 'text', label: __('Text'), hasValue: hasTextColor, resetValue: resetTextColor, isShownByDefault: defaultControls.text, indicators: [textColor], tabs: [{ key: 'text', label: __('Text'), inheritedValue: textColor, setValue: setTextColor, userValue: userTextColor }] }, showBackgroundPanel && { key: 'background', label: __('Background'), hasValue: hasBackground, resetValue: resetBackground, isShownByDefault: defaultControls.background, indicators: [gradient !== null && gradient !== void 0 ? gradient : backgroundColor], tabs: [{ key: 'background', label: __('Solid'), inheritedValue: backgroundColor, setValue: setBackgroundColor, userValue: userBackgroundColor }, { key: 'gradient', label: __('Gradient'), inheritedValue: gradient, setValue: setGradient, userValue: userGradient, isGradient: true }] }, showLinkPanel && { key: 'link', label: __('Link'), hasValue: hasLink, resetValue: resetLink, isShownByDefault: defaultControls.link, indicators: [linkColor, hoverLinkColor], tabs: [{ key: 'link', label: __('Default'), inheritedValue: linkColor, setValue: setLinkColor, userValue: userLinkColor }, { key: 'hover', label: __('Hover'), inheritedValue: hoverLinkColor, setValue: setHoverLinkColor, userValue: userHoverLinkColor }] }].filter(Boolean); elements.forEach(({ name, label, showPanel }) => { if (!showPanel) return; const elementBackgroundColor = decodeValue(inheritedValue?.elements?.[name]?.color?.background); const elementGradient = decodeValue(inheritedValue?.elements?.[name]?.color?.gradient); const elementTextColor = decodeValue(inheritedValue?.elements?.[name]?.color?.text); const elementBackgroundUserColor = decodeValue(value?.elements?.[name]?.color?.background); const elementGradientUserColor = decodeValue(value?.elements?.[name]?.color?.gradient); const elementTextUserColor = decodeValue(value?.elements?.[name]?.color?.text); const hasElement = () => !!(elementTextUserColor || elementBackgroundUserColor || elementGradientUserColor); const resetElement = () => { const newValue = setImmutably(value, ['elements', name, 'color', 'background'], undefined); newValue.elements[name].color.gradient = undefined; newValue.elements[name].color.text = undefined; onChange(newValue); }; const setElementTextColor = newTextColor => { onChange(setImmutably(value, ['elements', name, 'color', 'text'], encodeColorValue(newTextColor))); }; const setElementBackgroundColor = newBackgroundColor => { const newValue = setImmutably(value, ['elements', name, 'color', 'background'], encodeColorValue(newBackgroundColor)); newValue.elements[name].color.gradient = undefined; onChange(newValue); }; const setElementGradient = newGradient => { const newValue = setImmutably(value, ['elements', name, 'color', 'gradient'], encodeGradientValue(newGradient)); newValue.elements[name].color.background = undefined; onChange(newValue); }; const supportsTextColor = true; // Background color is not supported for `caption` // as there isn't yet a way to set padding for the element. const supportsBackground = name !== 'caption'; items.push({ key: name, label, hasValue: hasElement, resetValue: resetElement, isShownByDefault: defaultControls[name], indicators: supportsTextColor && supportsBackground ? [elementTextColor, elementGradient !== null && elementGradient !== void 0 ? elementGradient : elementBackgroundColor] : [supportsTextColor ? elementTextColor : elementGradient !== null && elementGradient !== void 0 ? elementGradient : elementBackgroundColor], tabs: [hasSolidColors && supportsTextColor && { key: 'text', label: __('Text'), inheritedValue: elementTextColor, setValue: setElementTextColor, userValue: elementTextUserColor }, hasSolidColors && supportsBackground && { key: 'background', label: __('Background'), inheritedValue: elementBackgroundColor, setValue: setElementBackgroundColor, userValue: elementBackgroundUserColor }, hasGradientColors && supportsBackground && { key: 'gradient', label: __('Gradient'), inheritedValue: elementGradient, setValue: setElementGradient, userValue: elementGradientUserColor, isGradient: true }].filter(Boolean) }); }); return createElement(Wrapper, { resetAllFilter: resetAllFilter, value: value, onChange: onChange, panelId: panelId }, items.map(item => createElement(ColorPanelDropdown, _extends({ key: item.key }, item, { colorGradientControlSettings: { colors, disableCustomColors: !areCustomSolidsEnabled, gradients, disableCustomGradients: !areCustomGradientsEnabled }, panelId: panelId }))), children); } //# sourceMappingURL=color-panel.js.map