UNPKG

@wordpress/block-editor

Version:
160 lines (152 loc) 4.79 kB
/** * WordPress dependencies */ import { createContext, useContext } from '@wordpress/element'; /** * Internal dependencies */ import { orderBy } from '../../utils/sorting'; export const DEFAULT_BLOCK_LIST_CONTEXT = { scrollRef: null, blocksLayouts: { current: {} }, findBlockLayoutByClientId, getBlockLayoutsOrderedByYCoord, findBlockLayoutByPosition, updateBlocksLayouts }; const Context = createContext(DEFAULT_BLOCK_LIST_CONTEXT); const { Provider, Consumer } = Context; /** * Finds a block's layout data by position. * * @param {Object} data Blocks layouts object. * @param {Object} position Position to use for finding the block. * @param {number} position.x X coordinate. * @param {number} position.y Y coordinate. * * @return {Object|undefined} Found block layout data that matches the provided position. If none is found, `undefined` will be returned. */ function findBlockLayoutByPosition(data, position) { // Only enabled for root level blocks return Object.values(data).find(block => { return position.x >= block.x && position.x <= block.x + block.width && position.y >= block.y && position.y <= block.y + block.height; }); } /** * Finds a block's layout data by its client Id. * * @param {Object} data Blocks layouts object. * @param {string} clientId Block's clientId. * * @return {Object} Found block layout data. */ function findBlockLayoutByClientId(data, clientId) { return Object.entries(data).reduce((acc, entry) => { const item = entry[1]; if (acc) { return acc; } if (item?.clientId === clientId) { return item; } if (item?.innerBlocks && Object.keys(item.innerBlocks).length > 0) { return findBlockLayoutByClientId(item.innerBlocks, clientId); } return null; }, null); } /** * Deletes the layout data of a block by its client Id. * * @param {Object} data Blocks layouts object. * @param {string} clientId Block's clientsId. * * @return {Object} Updated data object. */ export function deleteBlockLayoutByClientId(data, clientId) { return Object.keys(data).reduce((acc, key) => { if (key !== clientId) { acc[key] = data[key]; } if (data[key]?.innerBlocks && Object.keys(data[key].innerBlocks).length > 0) { if (acc[key]) { acc[key].innerBlocks = deleteBlockLayoutByClientId(data[key].innerBlocks, clientId); } } return acc; }, {}); } /** * Orders the block's layout data by its Y coordinate. * * @param {Object} data Blocks layouts object. * * @return {Object} Blocks layouts object ordered by its Y coordinate. */ function getBlockLayoutsOrderedByYCoord(data) { // Only enabled for root level blocks. return orderBy(Object.values(data), 'y'); } /** * Updates or deletes a block's layout data in the blocksLayouts object, * in case of deletion, the layout data is not required. * * @param {Object} blocksLayouts Blocks layouts object. * @param {Object} blockData Block's layout data to add or remove to/from the blockLayouts object. * @param {string} blockData.clientId Block's clientId. * @param {?string} blockData.rootClientId Optional. Block's rootClientId. * @param {?boolean} blockData.shouldRemove Optional. Flag to remove it from the blocksLayout list. * @param {number} blockData.width Block's width. * @param {number} blockData.height Block's height. * @param {number} blockData.x Block's x coordinate (relative to the parent). * @param {number} blockData.y Block's y coordinate (relative to the parent). */ function updateBlocksLayouts(blocksLayouts, blockData) { const { clientId, rootClientId, shouldRemove, ...layoutProps } = blockData; if (clientId && shouldRemove) { blocksLayouts.current = deleteBlockLayoutByClientId(blocksLayouts.current, clientId); return; } if (clientId && !rootClientId) { blocksLayouts.current[clientId] = { clientId, rootClientId, ...layoutProps, innerBlocks: { ...blocksLayouts.current[clientId]?.innerBlocks } }; } else if (clientId && rootClientId) { const block = findBlockLayoutByClientId(blocksLayouts.current, rootClientId); if (block) { block.innerBlocks[clientId] = { clientId, rootClientId, ...layoutProps, innerBlocks: { ...block.innerBlocks[clientId]?.innerBlocks } }; } } } export { Provider as BlockListProvider, Consumer as BlockListConsumer }; /** * Hook that returns the block list context. * * @return {Object} Block list context */ export const useBlockListContext = () => { return useContext(Context); }; //# sourceMappingURL=block-list-context.native.js.map