@wordpress/block-editor
Version:
231 lines (200 loc) • 7.71 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getValuesFromColors = getValuesFromColors;
var _element = require("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classnames = _interopRequireDefault(require("classnames"));
var _tinycolor = _interopRequireDefault(require("tinycolor2"));
var _blocks = require("@wordpress/blocks");
var _components = require("@wordpress/components");
var _compose = require("@wordpress/compose");
var _hooks = require("@wordpress/hooks");
var _components2 = require("../components");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* Convert a list of colors to an object of R, G, and B values.
*
* @param {string[]} colors Array of RBG color strings.
*
* @return {Object} R, G, and B values.
*/
function getValuesFromColors(colors = []) {
const values = {
r: [],
g: [],
b: []
};
colors.forEach(color => {
// Access values directly to skip extra rounding that tinycolor.toRgb() does.
const tcolor = (0, _tinycolor.default)(color);
values.r.push(tcolor._r / 255);
values.g.push(tcolor._g / 255);
values.b.push(tcolor._b / 255);
});
return values;
}
/**
* Values for the SVG `feComponentTransfer`.
*
* @typedef Values {Object}
* @property {number[]} r Red values.
* @property {number[]} g Green values.
* @property {number[]} b Blue values.
*/
/**
* SVG and stylesheet needed for rendering the duotone filter.
*
* @param {Object} props Duotone props.
* @param {string} props.selector Selector to apply the filter to.
* @param {string} props.id Unique id for this duotone filter.
* @param {Values} props.values R, G, and B values to filter with.
* @return {WPElement} Duotone element.
*/
function DuotoneFilter({
selector,
id,
values
}) {
const stylesheet = `
${selector} {
filter: url( #${id} );
}
`;
return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_components.SVG, {
xmlnsXlink: "http://www.w3.org/1999/xlink",
viewBox: "0 0 0 0",
width: "0",
height: "0",
focusable: "false",
role: "none",
style: {
visibility: 'hidden',
position: 'absolute',
left: '-9999px',
overflow: 'hidden'
}
}, (0, _element.createElement)("defs", null, (0, _element.createElement)("filter", {
id: id
}, (0, _element.createElement)("feColorMatrix", {
type: "matrix" // Use perceptual brightness to convert to grayscale.
// prettier-ignore
,
values: ".299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 0 0 0 1 0"
}), (0, _element.createElement)("feComponentTransfer", {
// Use sRGB instead of linearRGB to be consistent with how CSS gradients work.
colorInterpolationFilters: "sRGB"
}, (0, _element.createElement)("feFuncR", {
type: "table",
tableValues: values.r.join(' ')
}), (0, _element.createElement)("feFuncG", {
type: "table",
tableValues: values.g.join(' ')
}), (0, _element.createElement)("feFuncB", {
type: "table",
tableValues: values.b.join(' ')
}))))), (0, _element.createElement)("style", {
dangerouslySetInnerHTML: {
__html: stylesheet
}
}));
}
function DuotonePanel({
attributes,
setAttributes
}) {
var _style$color;
const style = attributes === null || attributes === void 0 ? void 0 : attributes.style;
const duotone = style === null || style === void 0 ? void 0 : (_style$color = style.color) === null || _style$color === void 0 ? void 0 : _style$color.duotone;
const duotonePalette = (0, _components2.__experimentalUseEditorFeature)('color.duotone');
const colorPalette = (0, _components2.__experimentalUseEditorFeature)('color.palette');
return (0, _element.createElement)(_components2.BlockControls, {
group: "block"
}, (0, _element.createElement)(_components2.__experimentalDuotoneControl, {
duotonePalette: duotonePalette,
colorPalette: colorPalette,
value: duotone,
onChange: newDuotone => {
const newStyle = { ...style,
color: { ...(style === null || style === void 0 ? void 0 : style.color),
duotone: newDuotone
}
};
setAttributes({
style: newStyle
});
}
}));
}
/**
* Filters registered block settings, extending attributes to include
* the `duotone` attribute.
*
* @param {Object} settings Original block settings
* @return {Object} Filtered block settings
*/
function addDuotoneAttributes(settings) {
if (!(0, _blocks.hasBlockSupport)(settings, 'color.__experimentalDuotone')) {
return settings;
} // Allow blocks to specify their own attribute definition with default
// values if needed.
if (!settings.attributes.style) {
Object.assign(settings.attributes, {
style: {
type: 'object'
}
});
}
return settings;
}
/**
* Override the default edit UI to include toolbar controls for duotone if the
* block supports duotone.
*
* @param {Function} BlockEdit Original component
* @return {Function} Wrapped component
*/
const withDuotoneControls = (0, _compose.createHigherOrderComponent)(BlockEdit => props => {
const hasDuotoneSupport = (0, _blocks.hasBlockSupport)(props.name, 'color.__experimentalDuotone');
return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(BlockEdit, props), hasDuotoneSupport && (0, _element.createElement)(DuotonePanel, props));
}, 'withDuotoneControls');
/**
* Override the default block element to include duotone styles.
*
* @param {Function} BlockListBlock Original component
* @return {Function} Wrapped component
*/
const withDuotoneStyles = (0, _compose.createHigherOrderComponent)(BlockListBlock => props => {
var _props$attributes, _props$attributes$sty, _props$attributes$sty2;
const duotoneSupport = (0, _blocks.getBlockSupport)(props.name, 'color.__experimentalDuotone');
const values = props === null || props === void 0 ? void 0 : (_props$attributes = props.attributes) === null || _props$attributes === void 0 ? void 0 : (_props$attributes$sty = _props$attributes.style) === null || _props$attributes$sty === void 0 ? void 0 : (_props$attributes$sty2 = _props$attributes$sty.color) === null || _props$attributes$sty2 === void 0 ? void 0 : _props$attributes$sty2.duotone;
if (!duotoneSupport || !values) {
return (0, _element.createElement)(BlockListBlock, props);
}
const id = `wp-duotone-filter-${(0, _compose.useInstanceId)(BlockListBlock)}`;
const selectors = duotoneSupport.split(',');
const selectorsScoped = selectors.map(selector => `.${id} ${selector.trim()}`);
const selectorsGroup = selectorsScoped.join(', ');
const className = (0, _classnames.default)(props === null || props === void 0 ? void 0 : props.classname, id);
return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(DuotoneFilter, {
selector: selectorsGroup,
id: id,
values: getValuesFromColors(values)
}), (0, _element.createElement)(BlockListBlock, (0, _extends2.default)({}, props, {
className: className
})));
}, 'withDuotoneStyles');
(0, _hooks.addFilter)('blocks.registerBlockType', 'core/editor/duotone/add-attributes', addDuotoneAttributes);
(0, _hooks.addFilter)('editor.BlockEdit', 'core/editor/duotone/with-editor-controls', withDuotoneControls);
(0, _hooks.addFilter)('editor.BlockListBlock', 'core/editor/duotone/with-styles', withDuotoneStyles);
//# sourceMappingURL=duotone.js.map