Skip to content

Commit 398bec4

Browse files
Mamadukasethrubenstein
authored andcommitted
Don't use global 'select' in the Behaviors controls component (WordPress#51028)
1 parent 97aa69a commit 398bec4

File tree

1 file changed

+77
-61
lines changed

1 file changed

+77
-61
lines changed

packages/block-editor/src/hooks/behaviors.js

Lines changed: 77 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { addFilter } from '@wordpress/hooks';
55
import { SelectControl } from '@wordpress/components';
66
import { __ } from '@wordpress/i18n';
77
import { createHigherOrderComponent } from '@wordpress/compose';
8-
import { select } from '@wordpress/data';
8+
import { useSelect } from '@wordpress/data';
99

1010
/**
1111
* Internal dependencies
@@ -18,6 +18,66 @@ import { store as blockEditorStore } from '../store';
1818
*/
1919
import merge from 'deepmerge';
2020

21+
function BehaviorsControl( { blockName, blockBehaviors, onChange } ) {
22+
const { settings, themeBehaviors } = useSelect(
23+
( select ) => {
24+
const { getBehaviors, getSettings } = select( blockEditorStore );
25+
26+
return {
27+
settings:
28+
getSettings()?.__experimentalFeatures?.blocks?.[ blockName ]
29+
?.behaviors,
30+
themeBehaviors: getBehaviors()?.blocks?.[ blockName ],
31+
};
32+
},
33+
[ blockName ]
34+
);
35+
36+
if (
37+
! settings ||
38+
// If every behavior is disabled, do not show the behaviors inspector control.
39+
Object.entries( settings ).every( ( [ , value ] ) => ! value )
40+
) {
41+
return null;
42+
}
43+
44+
// Block behaviors take precedence over theme behaviors.
45+
const behaviors = merge( themeBehaviors, blockBehaviors || {} );
46+
47+
const noBehaviorsOption = {
48+
value: '',
49+
label: __( 'No behaviors' ),
50+
};
51+
52+
const behaviorsOptions = Object.entries( settings )
53+
.filter( ( [ , behaviorValue ] ) => behaviorValue ) // Filter out behaviors that are disabled.
54+
.map( ( [ behaviorName ] ) => ( {
55+
value: behaviorName,
56+
label:
57+
// Capitalize the first letter of the behavior name.
58+
behaviorName[ 0 ].toUpperCase() +
59+
behaviorName.slice( 1 ).toLowerCase(),
60+
} ) );
61+
62+
const options = [ noBehaviorsOption, ...behaviorsOptions ];
63+
64+
return (
65+
<InspectorControls group="advanced">
66+
<SelectControl
67+
__nextHasNoMarginBottom
68+
label={ __( 'Behaviors' ) }
69+
// At the moment we are only supporting one behavior (Lightbox)
70+
value={ behaviors?.lightbox ? 'lightbox' : '' }
71+
options={ options }
72+
onChange={ onChange }
73+
hideCancelButton={ true }
74+
help={ __( 'Add behaviors.' ) }
75+
size="__unstable-large"
76+
/>
77+
</InspectorControls>
78+
);
79+
}
80+
2181
/**
2282
* Override the default edit UI to include a new block inspector control for
2383
* assigning behaviors to blocks if behaviors are enabled in the theme.json.
@@ -30,72 +90,28 @@ import merge from 'deepmerge';
3090
*/
3191
export const withBehaviors = createHigherOrderComponent( ( BlockEdit ) => {
3292
return ( props ) => {
93+
const blockEdit = <BlockEdit key="edit" { ...props } />;
3394
// Only add behaviors to the core/image block.
3495
if ( props.name !== 'core/image' ) {
35-
return <BlockEdit { ...props } />;
96+
return blockEdit;
3697
}
3798

38-
const settings =
39-
select( blockEditorStore ).getSettings()?.__experimentalFeatures
40-
?.blocks?.[ props.name ]?.behaviors;
41-
if (
42-
! settings ||
43-
// If every behavior is disabled, do not show the behaviors inspector control.
44-
Object.entries( settings ).every( ( [ , value ] ) => ! value )
45-
) {
46-
return <BlockEdit { ...props } />;
47-
}
48-
49-
const { behaviors: blockBehaviors } = props.attributes;
50-
51-
// Get the theme behaviors for the block from the theme.json.
52-
const themeBehaviors =
53-
select( blockEditorStore ).getBehaviors()?.blocks?.[ props.name ];
54-
55-
// Block behaviors take precedence over theme behaviors.
56-
const behaviors = merge( themeBehaviors, blockBehaviors || {} );
57-
58-
const noBehaviorsOption = {
59-
value: '',
60-
label: __( 'No behaviors' ),
61-
};
62-
63-
const behaviorsOptions = Object.entries( settings )
64-
.filter( ( [ , behaviorValue ] ) => behaviorValue ) // Filter out behaviors that are disabled.
65-
.map( ( [ behaviorName ] ) => ( {
66-
value: behaviorName,
67-
label:
68-
// Capitalize the first letter of the behavior name.
69-
behaviorName[ 0 ].toUpperCase() +
70-
behaviorName.slice( 1 ).toLowerCase(),
71-
} ) );
72-
73-
const options = [ noBehaviorsOption, ...behaviorsOptions ];
74-
7599
return (
76100
<>
77-
<BlockEdit { ...props } />
78-
<InspectorControls group="advanced">
79-
<SelectControl
80-
__nextHasNoMarginBottom
81-
label={ __( 'Behaviors' ) }
82-
// At the moment we are only supporting one behavior (Lightbox)
83-
value={ behaviors?.lightbox ? 'lightbox' : '' }
84-
options={ options }
85-
onChange={ ( nextValue ) => {
86-
// If the user selects something, it means that they want to
87-
// change the default value (true) so we save it in the attributes.
88-
props.setAttributes( {
89-
behaviors: {
90-
lightbox: nextValue === 'lightbox',
91-
},
92-
} );
93-
} }
94-
hideCancelButton={ true }
95-
help={ __( 'Add behaviors.' ) }
96-
size="__unstable-large"
97-
/>
98-
</InspectorControls>
101+
{ blockEdit }
102+
<BehaviorsControl
103+
blockName={ props.name }
104+
blockBehaviors={ props.attributes.behaviors }
105+
onChange={ ( nextValue ) => {
106+
// If the user selects something, it means that they want to
107+
// change the default value (true) so we save it in the attributes.
108+
props.setAttributes( {
109+
behaviors: {
110+
lightbox: nextValue === 'lightbox',
111+
},
112+
} );
113+
} }
114+
/>
99115
</>
100116
);
101117
};

0 commit comments

Comments
 (0)