UNPKG

@wordpress/block-library

Version:
286 lines (276 loc) 9.76 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _clsx = _interopRequireDefault(require("clsx")); 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"); var _hooks = require("../utils/hooks"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const DEFAULT_BLOCK = { name: 'core/column' }; function ColumnInspectorControls({ clientId, setAttributes, isStackedOnMobile }) { const { count, canInsertColumnBlock, minCount } = (0, _data.useSelect)(select => { const { canInsertBlockType, canRemoveBlock, getBlockOrder } = select(_blockEditor.store); const blockOrder = getBlockOrder(clientId); // Get the indexes of columns for which removal is prevented. // The highest index will be used to determine the minimum column count. const preventRemovalBlockIndexes = blockOrder.reduce((acc, blockId, index) => { if (!canRemoveBlock(blockId)) { acc.push(index); } return acc; }, []); return { count: blockOrder.length, canInsertColumnBlock: canInsertBlockType('core/column', clientId), minCount: Math.max(...preventRemovalBlockIndexes) + 1 }; }, [clientId]); const { getBlocks } = (0, _data.useSelect)(_blockEditor.store); const { replaceInnerBlocks } = (0, _data.useDispatch)(_blockEditor.store); /** * 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. */ function updateColumns(previousColumns, newColumns) { 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); const newlyAddedColumns = newColumns - previousColumns; // Redistribute in consideration of pending block insertion as // constraining the available working width. const widths = (0, _utils.getRedistributedColumnWidths)(innerBlocks, 100 - newColumnWidth * newlyAddedColumns); innerBlocks = [...(0, _utils.getMappedColumnWidths)(innerBlocks, widths), ...Array.from({ length: newlyAddedColumns }).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 if (newColumns < previousColumns) { // 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); } const dropdownMenuProps = (0, _hooks.useToolsPanelDropdownMenuProps)(); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalToolsPanel, { label: (0, _i18n.__)('Settings'), resetAll: () => { setAttributes({ isStackedOnMobile: true }); }, dropdownMenuProps: dropdownMenuProps, children: [canInsertColumnBlock && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalVStack, { spacing: 4, style: { gridColumn: '1 / -1' }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.RangeControl, { __nextHasNoMarginBottom: true, __next40pxDefaultSize: true, label: (0, _i18n.__)('Columns'), value: count, onChange: value => updateColumns(count, Math.max(minCount, value)), min: Math.max(1, minCount), max: Math.max(6, count) }), count > 6 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Notice, { status: "warning", isDismissible: false, children: (0, _i18n.__)('This column count exceeds the recommended amount and may cause visual breakage.') })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Stack on mobile'), isShownByDefault: true, hasValue: () => isStackedOnMobile !== true, onDeselect: () => setAttributes({ isStackedOnMobile: true }), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToggleControl, { __nextHasNoMarginBottom: true, label: (0, _i18n.__)('Stack on mobile'), checked: isStackedOnMobile, onChange: () => setAttributes({ isStackedOnMobile: !isStackedOnMobile }) }) })] }); } function ColumnsEditContainer({ attributes, setAttributes, clientId }) { const { isStackedOnMobile, verticalAlignment, templateLock } = attributes; const registry = (0, _data.useRegistry)(); const { getBlockOrder } = (0, _data.useSelect)(_blockEditor.store); const { updateBlockAttributes } = (0, _data.useDispatch)(_blockEditor.store); const classes = (0, _clsx.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, { defaultBlock: DEFAULT_BLOCK, directInsert: true, orientation: 'horizontal', renderAppender: false, templateLock }); /** * Update all child Column blocks with a new vertical alignment setting * based on whatever alignment is passed in. This allows change to parent * to override anything set on a individual column basis. * * @param {string} newVerticalAlignment The vertical alignment setting. */ function updateAlignment(newVerticalAlignment) { const innerBlockClientIds = getBlockOrder(clientId); // Update own and child Column block vertical alignments. // This is a single action; the batching prevents creating multiple history records. registry.batch(() => { setAttributes({ verticalAlignment: newVerticalAlignment }); updateBlockAttributes(innerBlockClientIds, { verticalAlignment: newVerticalAlignment }); }); } return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.BlockControls, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.BlockVerticalAlignmentToolbar, { onChange: updateAlignment, value: verticalAlignment }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.InspectorControls, { children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ColumnInspectorControls, { clientId: clientId, setAttributes: setAttributes, isStackedOnMobile: isStackedOnMobile }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { ...innerBlocksProps })] }); } function Placeholder({ clientId, name, setAttributes }) { 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 /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { ...blockProps, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.__experimentalBlockVariationPicker, { icon: blockType?.icon?.src, label: blockType?.title, variations: variations, instructions: (0, _i18n.__)('Divide into columns. Select a layout:'), onSelect: (nextVariation = 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 ? ColumnsEditContainer : Placeholder; return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, { ...props }); }; var _default = exports.default = ColumnsEdit; //# sourceMappingURL=edit.js.map