@gechiui/block-editor
Version:
215 lines (192 loc) • 8.4 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement } from "@gechiui/element";
/**
* External dependencies
*/
import { isString, kebabCase, reduce, upperFirst } from 'lodash';
/**
* GeChiUI dependencies
*/
import { useMemo, Component } from '@gechiui/element';
import { compose, createHigherOrderComponent } from '@gechiui/compose';
/**
* Internal dependencies
*/
import { getColorClassName, getColorObjectByColorValue, getColorObjectByAttributeValues, getMostReadableColor } from './utils';
import useSetting from '../use-setting';
/**
* Higher order component factory for injecting the `colorsArray` argument as
* the colors prop in the `withCustomColors` HOC.
*
* @param {Array} colorsArray An array of color objects.
*
* @return {Function} The higher order component.
*/
const withCustomColorPalette = colorsArray => createHigherOrderComponent(WrappedComponent => props => createElement(WrappedComponent, _extends({}, props, {
colors: colorsArray
})), 'withCustomColorPalette');
/**
* Higher order component factory for injecting the editor colors as the
* `colors` prop in the `withColors` HOC.
*
* @return {Function} The higher order component.
*/
const withEditorColorPalette = () => createHigherOrderComponent(WrappedComponent => 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 = useSetting('color.palette.custom');
const themePalette = useSetting('color.palette.theme');
const defaultPalette = useSetting('color.palette.default');
const allColors = useMemo(() => [...(userPalette || []), ...(themePalette || []), ...(defaultPalette || [])], [userPalette, themePalette, defaultPalette]);
return createElement(WrappedComponent, _extends({}, props, {
colors: allColors
}));
}, 'withEditorColorPalette');
/**
* Helper function used with `createHigherOrderComponent` to create
* higher order components for managing color logic.
*
* @param {Array} colorTypes An array of color types (e.g. 'backgroundColor, borderColor).
* @param {Function} withColorPalette A HOC for injecting the 'colors' prop into the WrappedComponent.
*
* @return {GCComponent} The component that can be used as a HOC.
*/
function createColorHOC(colorTypes, withColorPalette) {
const colorMap = reduce(colorTypes, (colorObject, colorType) => {
return { ...colorObject,
...(isString(colorType) ? {
[colorType]: kebabCase(colorType)
} : colorType)
};
}, {});
return compose([withColorPalette, WrappedComponent => {
return class extends Component {
constructor(props) {
super(props);
this.setters = this.createSetters();
this.colorUtils = {
getMostReadableColor: this.getMostReadableColor.bind(this)
};
this.state = {};
}
getMostReadableColor(colorValue) {
const {
colors
} = this.props;
return getMostReadableColor(colors, colorValue);
}
createSetters() {
return reduce(colorMap, (settersAccumulator, colorContext, colorAttributeName) => {
const upperFirstColorAttributeName = upperFirst(colorAttributeName);
const customColorAttributeName = `custom${upperFirstColorAttributeName}`;
settersAccumulator[`set${upperFirstColorAttributeName}`] = this.createSetColor(colorAttributeName, customColorAttributeName);
return settersAccumulator;
}, {});
}
createSetColor(colorAttributeName, customColorAttributeName) {
return colorValue => {
const colorObject = getColorObjectByColorValue(this.props.colors, colorValue);
this.props.setAttributes({
[colorAttributeName]: colorObject && colorObject.slug ? colorObject.slug : undefined,
[customColorAttributeName]: colorObject && colorObject.slug ? undefined : colorValue
});
};
}
static getDerivedStateFromProps(_ref, previousState) {
let {
attributes,
colors
} = _ref;
return reduce(colorMap, (newState, colorContext, colorAttributeName) => {
const colorObject = getColorObjectByAttributeValues(colors, attributes[colorAttributeName], attributes[`custom${upperFirst(colorAttributeName)}`]);
const previousColorObject = previousState[colorAttributeName];
const previousColor = previousColorObject === null || previousColorObject === void 0 ? void 0 : previousColorObject.color;
/**
* The "and previousColorObject" condition checks that a previous color object was already computed.
* At the start previousColorObject and colorValue are both equal to undefined
* bus as previousColorObject does not exist we should compute the object.
*/
if (previousColor === colorObject.color && previousColorObject) {
newState[colorAttributeName] = previousColorObject;
} else {
newState[colorAttributeName] = { ...colorObject,
class: getColorClassName(colorContext, colorObject.slug)
};
}
return newState;
}, {});
}
render() {
return createElement(WrappedComponent, _extends({}, this.props, {
colors: undefined
}, this.state, this.setters, {
colorUtils: this.colorUtils
}));
}
};
}]);
}
/**
* A higher-order component factory for creating a 'withCustomColors' HOC, which handles color logic
* for class generation color value, retrieval and color attribute setting.
*
* Use this higher-order component to work with a custom set of colors.
*
* @example
*
* ```jsx
* const CUSTOM_COLORS = [ { name: 'Red', slug: 'red', color: '#ff0000' }, { name: 'Blue', slug: 'blue', color: '#0000ff' } ];
* const withCustomColors = createCustomColorsHOC( CUSTOM_COLORS );
* // ...
* export default compose(
* withCustomColors( 'backgroundColor', 'borderColor' ),
* MyColorfulComponent,
* );
* ```
*
* @param {Array} colorsArray The array of color objects (name, slug, color, etc... ).
*
* @return {Function} Higher-order component.
*/
export function createCustomColorsHOC(colorsArray) {
return function () {
const withColorPalette = withCustomColorPalette(colorsArray);
for (var _len = arguments.length, colorTypes = new Array(_len), _key = 0; _key < _len; _key++) {
colorTypes[_key] = arguments[_key];
}
return createHigherOrderComponent(createColorHOC(colorTypes, withColorPalette), 'withCustomColors');
};
}
/**
* A higher-order component, which handles color logic for class generation color value, retrieval and color attribute setting.
*
* For use with the default editor/theme color palette.
*
* @example
*
* ```jsx
* export default compose(
* withColors( 'backgroundColor', { textColor: 'color' } ),
* MyColorfulComponent,
* );
* ```
*
* @param {...(Object|string)} colorTypes The arguments can be strings or objects. If the argument is an object,
* it should contain the color attribute name as key and the color context as value.
* If the argument is a string the value should be the color attribute name,
* the color context is computed by applying a kebab case transform to the value.
* Color context represents the context/place where the color is going to be used.
* The class name of the color is generated using 'has' followed by the color name
* and ending with the color context all in kebab case e.g: has-green-background-color.
*
* @return {Function} Higher-order component.
*/
export default function withColors() {
const withColorPalette = withEditorColorPalette();
for (var _len2 = arguments.length, colorTypes = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
colorTypes[_key2] = arguments[_key2];
}
return createHigherOrderComponent(createColorHOC(colorTypes, withColorPalette), 'withColors');
}
//# sourceMappingURL=with-colors.js.map