UNPKG

@wordpress/block-editor

Version:
183 lines (175 loc) 6.13 kB
/** * External dependencies */ import clsx from 'clsx'; /** * WordPress dependencies */ import { addFilter } from '@wordpress/hooks'; import { getBlockSupport, getBlockType, hasBlockSupport } from '@wordpress/blocks'; /** * Internal dependencies */ import { BlockControls, BlockAlignmentControl } from '../components'; import useAvailableAlignments from '../components/block-alignment-control/use-available-alignments'; import { useBlockEditingMode } from '../components/block-editing-mode'; /** * An array which includes all possible valid alignments, * used to validate if an alignment is valid or not. * * @constant * @type {string[]} */ import { jsx as _jsx } from "react/jsx-runtime"; 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. */ export 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. */ export 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 (hasBlockSupport(settings, 'align')) { // Gracefully handle if settings.attributes is undefined. settings.attributes = { ...settings.attributes, align: { type: 'string', // Allow for '' since it is used by the `updateAlignment` function // in toolbar controls for special cases with defined default values. enum: [...ALL_ALIGNMENTS, ''] } }; } return settings; } function BlockEditAlignmentToolbarControlsPure({ name: blockName, align, setAttributes }) { // Compute the block valid alignments by taking into account, // if the theme supports wide alignments or not and the layout's // available alignments. We do that for conditionally rendering // Slot. const blockAllowedAlignments = getValidAlignments(getBlockSupport(blockName, 'align'), hasBlockSupport(blockName, 'alignWide', true)); const validAlignments = useAvailableAlignments(blockAllowedAlignments).map(({ name }) => name); const blockEditingMode = useBlockEditingMode(); if (!validAlignments.length || blockEditingMode !== 'default') { return null; } const updateAlignment = nextAlign => { if (!nextAlign) { const blockType = getBlockType(blockName); const blockDefaultAlign = blockType?.attributes?.align?.default; if (blockDefaultAlign) { nextAlign = ''; } } setAttributes({ align: nextAlign }); }; return /*#__PURE__*/_jsx(BlockControls, { group: "block", __experimentalShareWithChildBlocks: true, children: /*#__PURE__*/_jsx(BlockAlignmentControl, { value: align, onChange: updateAlignment, controls: validAlignments }) }); } export default { shareWithChildBlocks: true, edit: BlockEditAlignmentToolbarControlsPure, useBlockProps, addSaveProps: addAssignedAlign, attributeKeys: ['align'], hasSupport(name) { return hasBlockSupport(name, 'align', false); } }; function useBlockProps({ name, align }) { const blockAllowedAlignments = getValidAlignments(getBlockSupport(name, 'align'), hasBlockSupport(name, 'alignWide', true)); const validAlignments = useAvailableAlignments(blockAllowedAlignments); if (validAlignments.some(alignment => alignment.name === align)) { return { 'data-align': align }; } return {}; } /** * 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. */ export function addAssignedAlign(props, blockType, attributes) { const { align } = attributes; const blockAlign = getBlockSupport(blockType, 'align'); const hasWideBlockSupport = 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 = clsx(`align${align}`, props.className); } return props; } addFilter('blocks.registerBlockType', 'core/editor/align/addAttribute', addAttribute); //# sourceMappingURL=align.js.map