Skip to content

Commit

Permalink
Add getBlockStyles selector so avoid over-selecting in GridPopover
Browse files Browse the repository at this point in the history
  • Loading branch information
noisysocks committed Aug 12, 2024
1 parent 98cb5de commit 7b52f34
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 5 deletions.
17 changes: 12 additions & 5 deletions packages/block-editor/src/components/grid/grid-visualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { range, GridRect, getGridInfo } from './utils';
import { store as blockEditorStore } from '../../store';
import { useGetNumberOfBlocksBeforeCell } from './use-get-number-of-blocks-before-cell';
import ButtonBlockAppender from '../button-block-appender';
import { unlock } from '../../lock-unlock';

export function GridVisualizer( { clientId, contentRef, parentLayout } ) {
const isDistractionFree = useSelect(
Expand Down Expand Up @@ -100,20 +101,26 @@ const GridPopover = forwardRef( ( { gridClientId, gridInfo }, ref ) => {
const [ isDroppingAllowed, setIsDroppingAllowed ] = useState( false );
const [ highlightedRect, setHighlightedRect ] = useState( null );

const gridItems = useSelect(
( select ) => select( blockEditorStore ).getBlocks( gridClientId ),
const gridItemStyles = useSelect(
( select ) => {
const { getBlockOrder, getBlockStyles } = unlock(
select( blockEditorStore )
);
const blockOrder = getBlockOrder( gridClientId );
return getBlockStyles( blockOrder );
},
[ gridClientId ]
);

const occupiedRects = useMemo( () => {
const rects = [];
for ( const block of gridItems ) {
for ( const style of Object.values( gridItemStyles ) ) {
const {
columnStart,
rowStart,
columnSpan = 1,
rowSpan = 1,
} = block.attributes.style?.layout || {};
} = style?.layout ?? {};
if ( ! columnStart || ! rowStart ) {
continue;
}
Expand All @@ -127,7 +134,7 @@ const GridPopover = forwardRef( ( { gridClientId, gridInfo }, ref ) => {
);
}
return rects;
}, [ gridItems ] );
}, [ gridItemStyles ] );

useEffect( () => {
function onGlobalDrag() {
Expand Down
21 changes: 21 additions & 0 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,3 +511,24 @@ export function getTemporarilyEditingAsBlocks( state ) {
export function getTemporarilyEditingFocusModeToRevert( state ) {
return state.temporarilyEditingFocusModeRevert;
}

/**
* Returns the style attributes of multiple blocks.
*
* @param {Object} state Global application state.
* @param {string[]} clientIds An array of block client IDs.
*
* @return {Object} An object where keys are client IDs and values are the corresponding block styles or undefined.
*/
export const getBlockStyles = createSelector(
( state, clientIds ) =>
clientIds.reduce( ( styles, clientId ) => {
styles[ clientId ] = state.blocks.attributes.get( clientId )?.style;
return styles;
}, {} ),
( state, clientIds ) => [
...clientIds.map(
( clientId ) => state.blocks.attributes.get( clientId )?.style
),
]
);
89 changes: 89 additions & 0 deletions packages/block-editor/src/store/test/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getEnabledBlockParents,
getExpandedBlock,
isDragging,
getBlockStyles,
} from '../private-selectors';
import { getBlockEditingMode } from '../selectors';

Expand Down Expand Up @@ -509,4 +510,92 @@ describe( 'private selectors', () => {
);
} );
} );

describe( 'getBlockStyles', () => {
it( 'should return an empty object when no client IDs are provided', () => {
const state = {
blocks: {
attributes: new Map(),
},
};
const result = getBlockStyles( state, [] );
expect( result ).toEqual( {} );
} );

it( 'should return styles for a single block', () => {
const state = {
blocks: {
attributes: new Map( [
[ 'block-1', { style: { color: 'red' } } ],
] ),
},
};
const result = getBlockStyles( state, [ 'block-1' ] );
expect( result ).toEqual( {
'block-1': { color: 'red' },
} );
} );

it( 'should return styles for multiple blocks', () => {
const state = {
blocks: {
attributes: new Map( [
[ 'block-1', { style: { color: 'red' } } ],
[ 'block-2', { style: { fontSize: '16px' } } ],
[ 'block-3', { style: { margin: '10px' } } ],
] ),
},
};
const result = getBlockStyles( state, [
'block-1',
'block-2',
'block-3',
] );
expect( result ).toEqual( {
'block-1': { color: 'red' },
'block-2': { fontSize: '16px' },
'block-3': { margin: '10px' },
} );
} );

it( 'should return undefined for blocks without styles', () => {
const state = {
blocks: {
attributes: new Map( [
[ 'block-1', { style: { color: 'red' } } ],
[ 'block-2', {} ],
[ 'block-3', { style: { margin: '10px' } } ],
] ),
},
};
const result = getBlockStyles( state, [
'block-1',
'block-2',
'block-3',
] );
expect( result ).toEqual( {
'block-1': { color: 'red' },
'block-2': undefined,
'block-3': { margin: '10px' },
} );
} );

it( 'should return undefined for non-existent blocks', () => {
const state = {
blocks: {
attributes: new Map( [
[ 'block-1', { style: { color: 'red' } } ],
] ),
},
};
const result = getBlockStyles( state, [
'block-1',
'non-existent-block',
] );
expect( result ).toEqual( {
'block-1': { color: 'red' },
'non-existent-block': undefined,
} );
} );
} );
} );

0 comments on commit 7b52f34

Please sign in to comment.