UNPKG

@gechiui/block-editor

Version:
430 lines (352 loc) 18.4 kB
"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