UNPKG

@gechiui/block-editor

Version:
246 lines (203 loc) 8.28 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.addAssignedAlign = addAssignedAlign; exports.addAttribute = addAttribute; exports.getValidAlignments = getValidAlignments; exports.withToolbarControls = exports.withDataAlign = 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 _compose = require("@gechiui/compose"); var _hooks = require("@gechiui/hooks"); var _blocks = require("@gechiui/blocks"); var _components = require("../components"); var _useAvailableAlignments = _interopRequireDefault(require("../components/block-alignment-control/use-available-alignments")); /** * External dependencies */ /** * GeChiUI dependencies */ /** * Internal dependencies */ /** * An array which includes all possible valid alignments, * used to validate if an alignment is valid or not. * * @constant * @type {string[]} */ const ALL_ALIGNMENTS = ['left', 'center', 'right', 'wide', 'full']; /** * An array which includes all wide alignments. * In order for this alignments to be valid they need to be supported by the block, * and by the theme. * * @constant * @type {string[]} */ const WIDE_ALIGNMENTS = ['wide', 'full']; /** * Returns the valid alignments. * Takes into consideration the aligns supported by a block, if the block supports wide controls or not and if theme supports wide controls or not. * Exported just for testing purposes, not exported outside the module. * * @param {?boolean|string[]} blockAlign Aligns supported by the block. * @param {?boolean} hasWideBlockSupport True if block supports wide alignments. And False otherwise. * @param {?boolean} hasWideEnabled True if theme supports wide alignments. And False otherwise. * * @return {string[]} Valid alignments. */ function getValidAlignments(blockAlign) { let hasWideBlockSupport = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; let hasWideEnabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; let validAlignments; if (Array.isArray(blockAlign)) { validAlignments = ALL_ALIGNMENTS.filter(value => blockAlign.includes(value)); } else if (blockAlign === true) { // `true` includes all alignments... validAlignments = [...ALL_ALIGNMENTS]; } else { validAlignments = []; } if (!hasWideEnabled || blockAlign === true && !hasWideBlockSupport) { return (0, _lodash.without)(validAlignments, ...WIDE_ALIGNMENTS); } return validAlignments; } /** * Filters registered block settings, extending attributes to include `align`. * * @param {Object} settings Original block settings. * * @return {Object} Filtered block settings. */ function addAttribute(settings) { // allow blocks to specify their own attribute definition with default values if needed. if ((0, _lodash.has)(settings.attributes, ['align', 'type'])) { return settings; } if ((0, _blocks.hasBlockSupport)(settings, 'align')) { // Gracefully handle if settings.attributes is undefined. settings.attributes = { ...settings.attributes, align: { type: 'string', // Allow for '' since it is used by updateAlignment function // in withToolbarControls for special cases with defined default values. enum: [...ALL_ALIGNMENTS, ''] } }; } return settings; } /** * Override the default edit UI to include new toolbar controls for block * alignment, if block defines support. * * @param {Function} BlockEdit Original component. * * @return {Function} Wrapped component. */ const withToolbarControls = (0, _compose.createHigherOrderComponent)(BlockEdit => props => { const { name: blockName } = props; // Compute the block valid alignments by taking into account, // if the theme supports wide alignments or not and the layout's // availble alignments. We do that for conditionally rendering // Slot. const blockAllowedAlignments = getValidAlignments((0, _blocks.getBlockSupport)(blockName, 'align'), (0, _blocks.hasBlockSupport)(blockName, 'alignWide', true)); const validAlignments = (0, _useAvailableAlignments.default)(blockAllowedAlignments).map(_ref => { let { name } = _ref; return name; }); const updateAlignment = nextAlign => { if (!nextAlign) { var _blockType$attributes, _blockType$attributes2; const blockType = (0, _blocks.getBlockType)(props.name); const blockDefaultAlign = blockType === null || blockType === void 0 ? void 0 : (_blockType$attributes = blockType.attributes) === null || _blockType$attributes === void 0 ? void 0 : (_blockType$attributes2 = _blockType$attributes.align) === null || _blockType$attributes2 === void 0 ? void 0 : _blockType$attributes2.default; if (blockDefaultAlign) { nextAlign = ''; } } props.setAttributes({ align: nextAlign }); }; return (0, _element.createElement)(_element.Fragment, null, !!validAlignments.length && (0, _element.createElement)(_components.BlockControls, { group: "block", __experimentalShareWithChildBlocks: true }, (0, _element.createElement)(_components.BlockAlignmentControl, { value: props.attributes.align, onChange: updateAlignment, controls: validAlignments })), (0, _element.createElement)(BlockEdit, props)); }, 'withToolbarControls'); /** * Override the default block element to add alignment wrapper props. * * @param {Function} BlockListBlock Original component. * * @return {Function} Wrapped component. */ exports.withToolbarControls = withToolbarControls; const withDataAlign = (0, _compose.createHigherOrderComponent)(BlockListBlock => props => { const { name, attributes } = props; const { align } = attributes; const blockAllowedAlignments = getValidAlignments((0, _blocks.getBlockSupport)(name, 'align'), (0, _blocks.hasBlockSupport)(name, 'alignWide', true)); const validAlignments = (0, _useAvailableAlignments.default)(blockAllowedAlignments); // If an alignment is not assigned, there's no need to go through the // effort to validate or assign its value. if (align === undefined) { return (0, _element.createElement)(BlockListBlock, props); } let wrapperProps = props.wrapperProps; if (validAlignments.some(alignment => alignment.name === align)) { wrapperProps = { ...wrapperProps, 'data-align': align }; } return (0, _element.createElement)(BlockListBlock, (0, _extends2.default)({}, props, { wrapperProps: wrapperProps })); }); /** * Override props assigned to save component to inject alignment class name if * block supports it. * * @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. */ exports.withDataAlign = withDataAlign; function addAssignedAlign(props, blockType, attributes) { const { align } = attributes; const blockAlign = (0, _blocks.getBlockSupport)(blockType, 'align'); const hasWideBlockSupport = (0, _blocks.hasBlockSupport)(blockType, 'alignWide', true); // Compute valid alignments without taking into account if // the theme supports wide alignments or not. // This way changing themes does not impact the block save. const isAlignValid = getValidAlignments(blockAlign, hasWideBlockSupport).includes(align); if (isAlignValid) { props.className = (0, _classnames.default)(`align${align}`, props.className); } return props; } (0, _hooks.addFilter)('blocks.registerBlockType', 'core/align/addAttribute', addAttribute); (0, _hooks.addFilter)('editor.BlockListBlock', 'core/editor/align/with-data-align', withDataAlign); (0, _hooks.addFilter)('editor.BlockEdit', 'core/editor/align/with-toolbar-controls', withToolbarControls); (0, _hooks.addFilter)('blocks.getSaveContent.extraProps', 'core/align/addAssignedAlign', addAssignedAlign); //# sourceMappingURL=align.js.map