@gechiui/block-editor
Version:
430 lines (352 loc) • 18.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.COLOR_SUPPORT_KEY = void 0;
exports.ColorEdit = ColorEdit;
exports.addEditProps = addEditProps;
exports.addSaveProps = addSaveProps;
exports.withColorPaletteStyles = void 0;
var _element = require("@gechiui/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classnames = _interopRequireDefault(require("classnames"));
var _lodash = require("lodash");
var _hooks = require("@gechiui/hooks");
var _blocks = require("@gechiui/blocks");
var _i18n = require("@gechiui/i18n");
var _compose = require("@gechiui/compose");
var _colors = require("../components/colors");
var _gradients = require("../components/gradients");
var _utils = require("./utils");
var _colorPanel = _interopRequireDefault(require("./color-panel"));
var _useSetting = _interopRequireDefault(require("../components/use-setting"));
/**
* External dependencies
*/
/**
* GeChiUI dependencies
*/
/**
* Internal dependencies
*/
const COLOR_SUPPORT_KEY = 'color';
exports.COLOR_SUPPORT_KEY = COLOR_SUPPORT_KEY;
const hasColorSupport = blockType => {
const colorSupport = (0, _blocks.getBlockSupport)(blockType, COLOR_SUPPORT_KEY);
return colorSupport && (colorSupport.link === true || colorSupport.gradient === true || colorSupport.background !== false || colorSupport.text !== false);
};
const shouldSkipSerialization = blockType => {
const colorSupport = (0, _blocks.getBlockSupport)(blockType, COLOR_SUPPORT_KEY);
return colorSupport === null || colorSupport === void 0 ? void 0 : colorSupport.__experimentalSkipSerialization;
};
const hasLinkColorSupport = blockType => {
if (_element.Platform.OS !== 'web') {
return false;
}
const colorSupport = (0, _blocks.getBlockSupport)(blockType, COLOR_SUPPORT_KEY);
return (0, _lodash.isObject)(colorSupport) && !!colorSupport.link;
};
const hasGradientSupport = blockType => {
const colorSupport = (0, _blocks.getBlockSupport)(blockType, COLOR_SUPPORT_KEY);
return (0, _lodash.isObject)(colorSupport) && !!colorSupport.gradients;
};
const hasBackgroundColorSupport = blockType => {
const colorSupport = (0, _blocks.getBlockSupport)(blockType, COLOR_SUPPORT_KEY);
return colorSupport && colorSupport.background !== false;
};
const hasTextColorSupport = blockType => {
const colorSupport = (0, _blocks.getBlockSupport)(blockType, COLOR_SUPPORT_KEY);
return colorSupport && colorSupport.text !== false;
};
/**
* Filters registered block settings, extending attributes to include
* `backgroundColor` and `textColor` attribute.
*
* @param {Object} settings Original block settings.
*
* @return {Object} Filtered block settings.
*/
function addAttributes(settings) {
if (!hasColorSupport(settings)) {
return settings;
} // allow blocks to specify their own attribute definition with default values if needed.
if (!settings.attributes.backgroundColor) {
Object.assign(settings.attributes, {
backgroundColor: {
type: 'string'
}
});
}
if (!settings.attributes.textColor) {
Object.assign(settings.attributes, {
textColor: {
type: 'string'
}
});
}
if (hasGradientSupport(settings) && !settings.attributes.gradient) {
Object.assign(settings.attributes, {
gradient: {
type: 'string'
}
});
}
return settings;
}
/**
* Override props assigned to save component to inject colors classnames.
*
* @param {Object} props Additional props applied to save element.
* @param {Object} blockType Block type.
* @param {Object} attributes Block attributes.
*
* @return {Object} Filtered props applied to save element.
*/
function addSaveProps(props, blockType, attributes) {
var _style$color, _style$color2, _style$color3, _style$color4, _style$elements, _style$elements$link;
if (!hasColorSupport(blockType) || shouldSkipSerialization(blockType)) {
return props;
}
const hasGradient = hasGradientSupport(blockType); // I'd have prefered to avoid the "style" attribute usage here
const {
backgroundColor,
textColor,
gradient,
style
} = attributes;
const backgroundClass = (0, _colors.getColorClassName)('background-color', backgroundColor);
const gradientClass = (0, _gradients.__experimentalGetGradientClass)(gradient);
const textClass = (0, _colors.getColorClassName)('color', textColor);
const newClassName = (0, _classnames.default)(props.className, textClass, gradientClass, {
// Don't apply the background class if there's a custom gradient
[backgroundClass]: (!hasGradient || !(style !== null && style !== void 0 && (_style$color = style.color) !== null && _style$color !== void 0 && _style$color.gradient)) && !!backgroundClass,
'has-text-color': textColor || (style === null || style === void 0 ? void 0 : (_style$color2 = style.color) === null || _style$color2 === void 0 ? void 0 : _style$color2.text),
'has-background': backgroundColor || (style === null || style === void 0 ? void 0 : (_style$color3 = style.color) === null || _style$color3 === void 0 ? void 0 : _style$color3.background) || hasGradient && (gradient || (style === null || style === void 0 ? void 0 : (_style$color4 = style.color) === null || _style$color4 === void 0 ? void 0 : _style$color4.gradient)),
'has-link-color': style === null || style === void 0 ? void 0 : (_style$elements = style.elements) === null || _style$elements === void 0 ? void 0 : (_style$elements$link = _style$elements.link) === null || _style$elements$link === void 0 ? void 0 : _style$elements$link.color
});
props.className = newClassName ? newClassName : undefined;
return props;
}
/**
* Filters registered block settings to extand the block edit wrapper
* to apply the desired styles and classnames properly.
*
* @param {Object} settings Original block settings.
*
* @return {Object} Filtered block settings.
*/
function addEditProps(settings) {
if (!hasColorSupport(settings) || shouldSkipSerialization(settings)) {
return settings;
}
const existingGetEditWrapperProps = settings.getEditWrapperProps;
settings.getEditWrapperProps = attributes => {
let props = {};
if (existingGetEditWrapperProps) {
props = existingGetEditWrapperProps(attributes);
}
return addSaveProps(props, settings, attributes);
};
return settings;
}
const getLinkColorFromAttributeValue = (colors, value) => {
const attributeParsed = /var:preset\|color\|(.+)/.exec(value);
if (attributeParsed && attributeParsed[1]) {
return (0, _colors.getColorObjectByAttributeValues)(colors, attributeParsed[1]).color;
}
return value;
};
function immutableSet(object, path, value) {
return (0, _lodash.setWith)(object ? (0, _lodash.clone)(object) : {}, path, value, _lodash.clone);
}
/**
* Inspector control panel containing the color related configuration
*
* @param {Object} props
*
* @return {GCElement} Color edit element.
*/
function ColorEdit(props) {
var _style$color6, _style$color7, _style$color8, _style$elements2, _style$elements2$link, _style$elements2$link2, _style$elements3, _style$elements3$link, _style$elements3$link2;
const {
name: blockName,
attributes
} = props; // Some color settings have a special handling for deprecated flags in `useSetting`,
// so we can't unwrap them by doing const { ... } = useSetting('color')
// until https://github.com/GeChiUI/gutenberg/issues/37094 is fixed.
const userPalette = (0, _useSetting.default)('color.palette.custom');
const themePalette = (0, _useSetting.default)('color.palette.theme');
const defaultPalette = (0, _useSetting.default)('color.palette.default');
const allSolids = (0, _element.useMemo)(() => [...(userPalette || []), ...(themePalette || []), ...(defaultPalette || [])], [userPalette, themePalette, defaultPalette]);
const userGradientPalette = (0, _useSetting.default)('color.gradients.custom');
const themeGradientPalette = (0, _useSetting.default)('color.gradients.theme');
const defaultGradientPalette = (0, _useSetting.default)('color.gradients.default');
const allGradients = (0, _element.useMemo)(() => [...(userGradientPalette || []), ...(themeGradientPalette || []), ...(defaultGradientPalette || [])], [userGradientPalette, themeGradientPalette, defaultGradientPalette]);
const areCustomSolidsEnabled = (0, _useSetting.default)('color.custom');
const areCustomGradientsEnabled = (0, _useSetting.default)('color.customGradient');
const isBackgroundEnabled = (0, _useSetting.default)('color.background');
const isLinkEnabled = (0, _useSetting.default)('color.link');
const isTextEnabled = (0, _useSetting.default)('color.text');
const solidsEnabled = areCustomSolidsEnabled || !themePalette || (themePalette === null || themePalette === void 0 ? void 0 : themePalette.length) > 0;
const gradientsEnabled = areCustomGradientsEnabled || !themeGradientPalette || (themeGradientPalette === null || themeGradientPalette === void 0 ? void 0 : themeGradientPalette.length) > 0; // Shouldn't be needed but right now the ColorGradientsPanel
// can trigger both onChangeColor and onChangeBackground
// synchronously causing our two callbacks to override changes
// from each other.
const localAttributes = (0, _element.useRef)(attributes);
(0, _element.useEffect)(() => {
localAttributes.current = attributes;
}, [attributes]);
if (!hasColorSupport(blockName)) {
return null;
}
const hasLinkColor = hasLinkColorSupport(blockName) && isLinkEnabled && solidsEnabled;
const hasTextColor = hasTextColorSupport(blockName) && isTextEnabled && solidsEnabled;
const hasBackgroundColor = hasBackgroundColorSupport(blockName) && isBackgroundEnabled && solidsEnabled;
const hasGradientColor = hasGradientSupport(blockName) && gradientsEnabled;
if (!hasLinkColor && !hasTextColor && !hasBackgroundColor && !hasGradientColor) {
return null;
}
const {
style,
textColor,
backgroundColor,
gradient
} = attributes;
let gradientValue;
if (hasGradientColor && gradient) {
gradientValue = (0, _gradients.getGradientValueBySlug)(allGradients, gradient);
} else if (hasGradientColor) {
var _style$color5;
gradientValue = style === null || style === void 0 ? void 0 : (_style$color5 = style.color) === null || _style$color5 === void 0 ? void 0 : _style$color5.gradient;
}
const onChangeColor = name => value => {
var _localAttributes$curr, _localAttributes$curr2;
const colorObject = (0, _colors.getColorObjectByColorValue)(allSolids, value);
const attributeName = name + 'Color';
const newStyle = { ...localAttributes.current.style,
color: { ...((_localAttributes$curr = localAttributes.current) === null || _localAttributes$curr === void 0 ? void 0 : (_localAttributes$curr2 = _localAttributes$curr.style) === null || _localAttributes$curr2 === void 0 ? void 0 : _localAttributes$curr2.color),
[name]: colorObject !== null && colorObject !== void 0 && colorObject.slug ? undefined : value
}
};
const newNamedColor = colorObject !== null && colorObject !== void 0 && colorObject.slug ? colorObject.slug : undefined;
const newAttributes = {
style: (0, _utils.cleanEmptyObject)(newStyle),
[attributeName]: newNamedColor
};
props.setAttributes(newAttributes);
localAttributes.current = { ...localAttributes.current,
...newAttributes
};
};
const onChangeGradient = value => {
const slug = (0, _gradients.getGradientSlugByValue)(allGradients, value);
let newAttributes;
if (slug) {
var _localAttributes$curr3, _localAttributes$curr4, _localAttributes$curr5;
const newStyle = { ...((_localAttributes$curr3 = localAttributes.current) === null || _localAttributes$curr3 === void 0 ? void 0 : _localAttributes$curr3.style),
color: { ...((_localAttributes$curr4 = localAttributes.current) === null || _localAttributes$curr4 === void 0 ? void 0 : (_localAttributes$curr5 = _localAttributes$curr4.style) === null || _localAttributes$curr5 === void 0 ? void 0 : _localAttributes$curr5.color),
gradient: undefined
}
};
newAttributes = {
style: (0, _utils.cleanEmptyObject)(newStyle),
gradient: slug
};
} else {
var _localAttributes$curr6, _localAttributes$curr7, _localAttributes$curr8;
const newStyle = { ...((_localAttributes$curr6 = localAttributes.current) === null || _localAttributes$curr6 === void 0 ? void 0 : _localAttributes$curr6.style),
color: { ...((_localAttributes$curr7 = localAttributes.current) === null || _localAttributes$curr7 === void 0 ? void 0 : (_localAttributes$curr8 = _localAttributes$curr7.style) === null || _localAttributes$curr8 === void 0 ? void 0 : _localAttributes$curr8.color),
gradient: value
}
};
newAttributes = {
style: (0, _utils.cleanEmptyObject)(newStyle),
gradient: undefined
};
}
props.setAttributes(newAttributes);
localAttributes.current = { ...localAttributes.current,
...newAttributes
};
};
const onChangeLinkColor = value => {
const colorObject = (0, _colors.getColorObjectByColorValue)(allSolids, value);
const newLinkColorValue = colorObject !== null && colorObject !== void 0 && colorObject.slug ? `var:preset|color|${colorObject.slug}` : value;
const newStyle = (0, _utils.cleanEmptyObject)(immutableSet(style, ['elements', 'link', 'color', 'text'], newLinkColorValue));
props.setAttributes({
style: newStyle
});
};
return (0, _element.createElement)(_colorPanel.default, {
enableContrastChecking: // Turn on contrast checker for web only since it's not supported on mobile yet.
_element.Platform.OS === 'web' && !gradient && !(style !== null && style !== void 0 && (_style$color6 = style.color) !== null && _style$color6 !== void 0 && _style$color6.gradient),
clientId: props.clientId,
settings: [...(hasTextColor ? [{
label: (0, _i18n.__)('文本'),
onColorChange: onChangeColor('text'),
colorValue: (0, _colors.getColorObjectByAttributeValues)(allSolids, textColor, style === null || style === void 0 ? void 0 : (_style$color7 = style.color) === null || _style$color7 === void 0 ? void 0 : _style$color7.text).color
}] : []), ...(hasBackgroundColor || hasGradientColor ? [{
label: (0, _i18n.__)('背景'),
onColorChange: hasBackgroundColor ? onChangeColor('background') : undefined,
colorValue: (0, _colors.getColorObjectByAttributeValues)(allSolids, backgroundColor, style === null || style === void 0 ? void 0 : (_style$color8 = style.color) === null || _style$color8 === void 0 ? void 0 : _style$color8.background).color,
gradientValue,
onGradientChange: hasGradientColor ? onChangeGradient : undefined
}] : []), ...(hasLinkColor ? [{
label: (0, _i18n.__)('链接'),
onColorChange: onChangeLinkColor,
colorValue: getLinkColorFromAttributeValue(allSolids, style === null || style === void 0 ? void 0 : (_style$elements2 = style.elements) === null || _style$elements2 === void 0 ? void 0 : (_style$elements2$link = _style$elements2.link) === null || _style$elements2$link === void 0 ? void 0 : (_style$elements2$link2 = _style$elements2$link.color) === null || _style$elements2$link2 === void 0 ? void 0 : _style$elements2$link2.text),
clearable: !!(style !== null && style !== void 0 && (_style$elements3 = style.elements) !== null && _style$elements3 !== void 0 && (_style$elements3$link = _style$elements3.link) !== null && _style$elements3$link !== void 0 && (_style$elements3$link2 = _style$elements3$link.color) !== null && _style$elements3$link2 !== void 0 && _style$elements3$link2.text)
}] : [])]
});
}
/**
* This adds inline styles for color palette colors.
* Ideally, this is not needed and themes should load their palettes on the editor.
*
* @param {Function} BlockListBlock Original component.
*
* @return {Function} Wrapped component.
*/
const withColorPaletteStyles = (0, _compose.createHigherOrderComponent)(BlockListBlock => props => {
var _props$wrapperProps;
const {
name,
attributes
} = props;
const {
backgroundColor,
textColor
} = attributes;
const userPalette = (0, _useSetting.default)('color.palette.custom') || [];
const themePalette = (0, _useSetting.default)('color.palette.theme') || [];
const defaultPalette = (0, _useSetting.default)('color.palette.default') || [];
const colors = (0, _element.useMemo)(() => [...(userPalette || []), ...(themePalette || []), ...(defaultPalette || [])], [userPalette, themePalette, defaultPalette]);
if (!hasColorSupport(name) || shouldSkipSerialization(name)) {
return (0, _element.createElement)(BlockListBlock, props);
}
const extraStyles = {};
if (textColor) {
var _getColorObjectByAttr;
extraStyles.color = (_getColorObjectByAttr = (0, _colors.getColorObjectByAttributeValues)(colors, textColor)) === null || _getColorObjectByAttr === void 0 ? void 0 : _getColorObjectByAttr.color;
}
if (backgroundColor) {
var _getColorObjectByAttr2;
extraStyles.backgroundColor = (_getColorObjectByAttr2 = (0, _colors.getColorObjectByAttributeValues)(colors, backgroundColor)) === null || _getColorObjectByAttr2 === void 0 ? void 0 : _getColorObjectByAttr2.color;
}
let wrapperProps = props.wrapperProps;
wrapperProps = { ...props.wrapperProps,
style: { ...extraStyles,
...((_props$wrapperProps = props.wrapperProps) === null || _props$wrapperProps === void 0 ? void 0 : _props$wrapperProps.style)
}
};
return (0, _element.createElement)(BlockListBlock, (0, _extends2.default)({}, props, {
wrapperProps: wrapperProps
}));
});
exports.withColorPaletteStyles = withColorPaletteStyles;
(0, _hooks.addFilter)('blocks.registerBlockType', 'core/color/addAttribute', addAttributes);
(0, _hooks.addFilter)('blocks.getSaveContent.extraProps', 'core/color/addSaveProps', addSaveProps);
(0, _hooks.addFilter)('blocks.registerBlockType', 'core/color/addEditProps', addEditProps);
(0, _hooks.addFilter)('editor.BlockListBlock', 'core/color/with-color-palette-styles', withColorPaletteStyles);
//# sourceMappingURL=color.js.map