@wordpress/block-editor
Version:
514 lines (472 loc) • 17.1 kB
JavaScript
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