UNPKG

@wordpress/block-editor

Version:
217 lines (206 loc) 7.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridLayoutSync = useGridLayoutSync; var _data = require("@wordpress/data"); var _element = require("@wordpress/element"); var _compose = require("@wordpress/compose"); var _store = require("../../store"); var _utils = require("./utils"); var _object = require("../../utils/object"); /** * WordPress dependencies */ /** * Internal dependencies */ function useGridLayoutSync({ clientId: gridClientId }) { const { gridLayout, blockOrder, selectedBlockLayout } = (0, _data.useSelect)(select => { var _getBlockAttributes$l; const { getBlockAttributes, getBlockOrder } = select(_store.store); const selectedBlock = select(_store.store).getSelectedBlock(); return { gridLayout: (_getBlockAttributes$l = getBlockAttributes(gridClientId).layout) !== null && _getBlockAttributes$l !== void 0 ? _getBlockAttributes$l : {}, blockOrder: getBlockOrder(gridClientId), selectedBlockLayout: selectedBlock?.attributes.style?.layout }; }, [gridClientId]); const { getBlockAttributes, getBlockRootClientId } = (0, _data.useSelect)(_store.store); const { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } = (0, _data.useDispatch)(_store.store); const selectedBlockRect = (0, _element.useMemo)(() => selectedBlockLayout ? new _utils.GridRect(selectedBlockLayout) : null, [selectedBlockLayout]); const previouslySelectedBlockRect = (0, _compose.usePrevious)(selectedBlockRect); const previousIsManualPlacement = (0, _compose.usePrevious)(gridLayout.isManualPlacement); const previousBlockOrder = (0, _compose.usePrevious)(blockOrder); (0, _element.useEffect)(() => { const updates = {}; if (gridLayout.isManualPlacement) { const occupiedRects = []; // Respect the position of blocks that already have a columnStart and rowStart value. for (const clientId of blockOrder) { var _getBlockAttributes$s; const { columnStart, rowStart, columnSpan = 1, rowSpan = 1 } = (_getBlockAttributes$s = getBlockAttributes(clientId).style?.layout) !== null && _getBlockAttributes$s !== void 0 ? _getBlockAttributes$s : {}; if (!columnStart || !rowStart) { continue; } occupiedRects.push(new _utils.GridRect({ columnStart, rowStart, columnSpan, rowSpan })); } // When in manual mode, ensure that every block has a columnStart and rowStart value. for (const clientId of blockOrder) { var _attributes$style$lay; const attributes = getBlockAttributes(clientId); const { columnStart, rowStart, columnSpan = 1, rowSpan = 1 } = (_attributes$style$lay = attributes.style?.layout) !== null && _attributes$style$lay !== void 0 ? _attributes$style$lay : {}; if (columnStart && rowStart) { continue; } const [newColumnStart, newRowStart] = placeBlock(occupiedRects, gridLayout.columnCount, columnSpan, rowSpan, previouslySelectedBlockRect?.columnEnd, previouslySelectedBlockRect?.rowEnd); occupiedRects.push(new _utils.GridRect({ columnStart: newColumnStart, rowStart: newRowStart, columnSpan, rowSpan })); updates[clientId] = { style: { ...attributes.style, layout: { ...attributes.style?.layout, columnStart: newColumnStart, rowStart: newRowStart } } }; } // Ensure there's enough rows to fit all blocks. const bottomMostRow = Math.max(...occupiedRects.map(r => r.rowEnd)); if (!gridLayout.rowCount || gridLayout.rowCount < bottomMostRow) { updates[gridClientId] = { layout: { ...gridLayout, rowCount: bottomMostRow } }; } // Unset grid layout attributes for blocks removed from the grid. for (const clientId of previousBlockOrder !== null && previousBlockOrder !== void 0 ? previousBlockOrder : []) { if (!blockOrder.includes(clientId)) { var _attributes$style$lay2; const rootClientId = getBlockRootClientId(clientId); // Block was removed from the editor, so nothing to do. if (rootClientId === null) { continue; } // Check if the block is being moved to another grid. // If so, do nothing and let the new grid parent handle // the attributes. const rootAttributes = getBlockAttributes(rootClientId); if (rootAttributes?.layout?.type === 'grid') { continue; } const attributes = getBlockAttributes(clientId); const { columnStart, rowStart, columnSpan, rowSpan, ...layout } = (_attributes$style$lay2 = attributes.style?.layout) !== null && _attributes$style$lay2 !== void 0 ? _attributes$style$lay2 : {}; if (columnStart || rowStart || columnSpan || rowSpan) { const hasEmptyLayoutAttribute = Object.keys(layout).length === 0; updates[clientId] = (0, _object.setImmutably)(attributes, ['style', 'layout'], hasEmptyLayoutAttribute ? undefined : layout); } } } } else { // Remove all of the columnStart and rowStart values // when switching from manual to auto mode, if (previousIsManualPlacement === true) { for (const clientId of blockOrder) { var _attributes$style$lay3; const attributes = getBlockAttributes(clientId); const { columnStart, rowStart, ...layout } = (_attributes$style$lay3 = attributes.style?.layout) !== null && _attributes$style$lay3 !== void 0 ? _attributes$style$lay3 : {}; // Only update attributes if columnStart or rowStart are set. if (columnStart || rowStart) { const hasEmptyLayoutAttribute = Object.keys(layout).length === 0; updates[clientId] = (0, _object.setImmutably)(attributes, ['style', 'layout'], hasEmptyLayoutAttribute ? undefined : layout); } } } // Remove row styles in auto mode if (gridLayout.rowCount) { updates[gridClientId] = { layout: { ...gridLayout, rowCount: undefined } }; } } if (Object.keys(updates).length) { __unstableMarkNextChangeAsNotPersistent(); updateBlockAttributes(Object.keys(updates), updates, /* uniqueByBlock: */true); } }, [ // Actual deps to sync: gridClientId, gridLayout, previousBlockOrder, blockOrder, previouslySelectedBlockRect, previousIsManualPlacement, // These won't change, but the linter thinks they might: __unstableMarkNextChangeAsNotPersistent, getBlockAttributes, getBlockRootClientId, updateBlockAttributes]); } /** * @param {GridRect[]} occupiedRects * @param {number} gridColumnCount * @param {number} blockColumnSpan * @param {number} blockRowSpan * @param {number?} startColumn * @param {number?} startRow */ function placeBlock(occupiedRects, gridColumnCount, blockColumnSpan, blockRowSpan, startColumn = 1, startRow = 1) { for (let row = startRow;; row++) { for (let column = row === startRow ? startColumn : 1; column <= gridColumnCount; column++) { const candidateRect = new _utils.GridRect({ columnStart: column, rowStart: row, columnSpan: blockColumnSpan, rowSpan: blockRowSpan }); if (!occupiedRects.some(r => r.intersectsRect(candidateRect))) { return [column, row]; } } } } //# sourceMappingURL=use-grid-layout-sync.js.map