@wordpress/block-library
Version:
Block library for the WordPress editor.
249 lines (218 loc) • 7.98 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _classnames = _interopRequireDefault(require("classnames"));
var _lodash = require("lodash");
var _i18n = require("@wordpress/i18n");
var _components = require("@wordpress/components");
var _blockEditor = require("@wordpress/block-editor");
var _data = require("@wordpress/data");
var _blocks = require("@wordpress/blocks");
var _utils = require("./utils");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* Allowed blocks constant is passed to InnerBlocks precisely as specified here.
* The contents of the array should never change.
* The array should contain the name of each block that is allowed.
* In columns block, the only block we allow is 'core/column'.
*
* @constant
* @type {string[]}
*/
const ALLOWED_BLOCKS = ['core/column'];
function ColumnsEditContainer(_ref) {
let {
attributes,
setAttributes,
updateAlignment,
updateColumns,
clientId
} = _ref;
const {
isStackedOnMobile,
verticalAlignment
} = attributes;
const {
count
} = (0, _data.useSelect)(select => {
return {
count: select(_blockEditor.store).getBlockCount(clientId)
};
}, [clientId]);
const classes = (0, _classnames.default)({
[`are-vertically-aligned-${verticalAlignment}`]: verticalAlignment,
[`is-not-stacked-on-mobile`]: !isStackedOnMobile
});
const blockProps = (0, _blockEditor.useBlockProps)({
className: classes
});
const innerBlocksProps = (0, _blockEditor.useInnerBlocksProps)(blockProps, {
allowedBlocks: ALLOWED_BLOCKS,
orientation: 'horizontal',
renderAppender: false
});
return (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_blockEditor.BlockControls, null, (0, _element.createElement)(_blockEditor.BlockVerticalAlignmentToolbar, {
onChange: updateAlignment,
value: verticalAlignment
})), (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_components.PanelBody, null, (0, _element.createElement)(_components.RangeControl, {
label: (0, _i18n.__)('Columns'),
value: count,
onChange: value => updateColumns(count, value),
min: 1,
max: Math.max(6, count)
}), count > 6 && (0, _element.createElement)(_components.Notice, {
status: "warning",
isDismissible: false
}, (0, _i18n.__)('This column count exceeds the recommended amount and may cause visual breakage.')), (0, _element.createElement)(_components.ToggleControl, {
label: (0, _i18n.__)('Stack on mobile'),
checked: isStackedOnMobile,
onChange: () => setAttributes({
isStackedOnMobile: !isStackedOnMobile
})
}))), (0, _element.createElement)("div", innerBlocksProps));
}
const ColumnsEditContainerWrapper = (0, _data.withDispatch)((dispatch, ownProps, registry) => ({
/**
* Update all child Column blocks with a new vertical alignment setting
* based on whatever alignment is passed in. This allows change to parent
* to overide anything set on a individual column basis.
*
* @param {string} verticalAlignment the vertical alignment setting
*/
updateAlignment(verticalAlignment) {
const {
clientId,
setAttributes
} = ownProps;
const {
updateBlockAttributes
} = dispatch(_blockEditor.store);
const {
getBlockOrder
} = registry.select(_blockEditor.store); // Update own alignment.
setAttributes({
verticalAlignment
}); // Update all child Column Blocks to match.
const innerBlockClientIds = getBlockOrder(clientId);
innerBlockClientIds.forEach(innerBlockClientId => {
updateBlockAttributes(innerBlockClientId, {
verticalAlignment
});
});
},
/**
* Updates the column count, including necessary revisions to child Column
* blocks to grant required or redistribute available space.
*
* @param {number} previousColumns Previous column count.
* @param {number} newColumns New column count.
*/
updateColumns(previousColumns, newColumns) {
const {
clientId
} = ownProps;
const {
replaceInnerBlocks
} = dispatch(_blockEditor.store);
const {
getBlocks
} = registry.select(_blockEditor.store);
let innerBlocks = getBlocks(clientId);
const hasExplicitWidths = (0, _utils.hasExplicitPercentColumnWidths)(innerBlocks); // Redistribute available width for existing inner blocks.
const isAddingColumn = newColumns > previousColumns;
if (isAddingColumn && hasExplicitWidths) {
// If adding a new column, assign width to the new column equal to
// as if it were `1 / columns` of the total available space.
const newColumnWidth = (0, _utils.toWidthPrecision)(100 / newColumns); // Redistribute in consideration of pending block insertion as
// constraining the available working width.
const widths = (0, _utils.getRedistributedColumnWidths)(innerBlocks, 100 - newColumnWidth);
innerBlocks = [...(0, _utils.getMappedColumnWidths)(innerBlocks, widths), ...Array.from({
length: newColumns - previousColumns
}).map(() => {
return (0, _blocks.createBlock)('core/column', {
width: `${newColumnWidth}%`
});
})];
} else if (isAddingColumn) {
innerBlocks = [...innerBlocks, ...Array.from({
length: newColumns - previousColumns
}).map(() => {
return (0, _blocks.createBlock)('core/column');
})];
} else {
// The removed column will be the last of the inner blocks.
innerBlocks = innerBlocks.slice(0, -(previousColumns - newColumns));
if (hasExplicitWidths) {
// Redistribute as if block is already removed.
const widths = (0, _utils.getRedistributedColumnWidths)(innerBlocks, 100);
innerBlocks = (0, _utils.getMappedColumnWidths)(innerBlocks, widths);
}
}
replaceInnerBlocks(clientId, innerBlocks);
}
}))(ColumnsEditContainer);
function Placeholder(_ref2) {
let {
clientId,
name,
setAttributes
} = _ref2;
const {
blockType,
defaultVariation,
variations
} = (0, _data.useSelect)(select => {
const {
getBlockVariations,
getBlockType,
getDefaultBlockVariation
} = select(_blocks.store);
return {
blockType: getBlockType(name),
defaultVariation: getDefaultBlockVariation(name, 'block'),
variations: getBlockVariations(name, 'block')
};
}, [name]);
const {
replaceInnerBlocks
} = (0, _data.useDispatch)(_blockEditor.store);
const blockProps = (0, _blockEditor.useBlockProps)();
return (0, _element.createElement)("div", blockProps, (0, _element.createElement)(_blockEditor.__experimentalBlockVariationPicker, {
icon: (0, _lodash.get)(blockType, ['icon', 'src']),
label: (0, _lodash.get)(blockType, ['title']),
variations: variations,
onSelect: function () {
let nextVariation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultVariation;
if (nextVariation.attributes) {
setAttributes(nextVariation.attributes);
}
if (nextVariation.innerBlocks) {
replaceInnerBlocks(clientId, (0, _blocks.createBlocksFromInnerBlocksTemplate)(nextVariation.innerBlocks), true);
}
},
allowSkip: true
}));
}
const ColumnsEdit = props => {
const {
clientId
} = props;
const hasInnerBlocks = (0, _data.useSelect)(select => select(_blockEditor.store).getBlocks(clientId).length > 0, [clientId]);
const Component = hasInnerBlocks ? ColumnsEditContainerWrapper : Placeholder;
return (0, _element.createElement)(Component, props);
};
var _default = ColumnsEdit;
exports.default = _default;
//# sourceMappingURL=edit.js.map