@wordpress/block-editor
Version:
249 lines (205 loc) • 8.18 kB
JavaScript
;
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("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classnames = _interopRequireDefault(require("classnames"));
var _compose = require("@wordpress/compose");
var _hooks = require("@wordpress/hooks");
var _blocks = require("@wordpress/blocks");
var _components = require("../components");
var _useAvailableAlignments = _interopRequireDefault(require("../components/block-alignment-control/use-available-alignments"));
var _blockEditingMode = require("../components/block-editing-mode");
/**
* External dependencies
*/
/**
* WordPress 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, hasWideBlockSupport = true, hasWideEnabled = 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 validAlignments.filter(alignment => !WIDE_ALIGNMENTS.includes(alignment));
}
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) {
var _settings$attributes$;
// Allow blocks to specify their own attribute definition with default values if needed.
if ('type' in ((_settings$attributes$ = settings.attributes?.align) !== null && _settings$attributes$ !== void 0 ? _settings$attributes$ : {})) {
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 blockEdit = (0, _element.createElement)(BlockEdit, (0, _extends2.default)({
key: "edit"
}, 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(({
name
}) => name);
const blockEditingMode = (0, _blockEditingMode.useBlockEditingMode)();
if (!validAlignments.length || blockEditingMode !== 'default') {
return blockEdit;
}
const updateAlignment = nextAlign => {
if (!nextAlign) {
const blockType = (0, _blocks.getBlockType)(props.name);
const blockDefaultAlign = blockType?.attributes?.align?.default;
if (blockDefaultAlign) {
nextAlign = '';
}
}
props.setAttributes({
align: nextAlign
});
};
return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_components.BlockControls, {
group: "block",
__experimentalShareWithChildBlocks: true
}, (0, _element.createElement)(_components.BlockAlignmentControl, {
value: props.attributes.align,
onChange: updateAlignment,
controls: validAlignments
})), blockEdit);
}, '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
}));
}, 'withDataAlign');
/**
* 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