@wordpress/block-library
Version:
Block library for the WordPress editor.
286 lines (276 loc) • 9.76 kB
JavaScript
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
;