UNPKG

@wordpress/block-editor

Version:
231 lines (200 loc) 7.71 kB
"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