-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Behaviors UI #49972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Behaviors UI #49972
Changes from 55 commits
bd53de2
bd43bf6
e1dd737
8b84a22
d5dbc1c
037d669
8f62d34
62b6217
edfd7d1
8ee4065
594224b
fd6fe36
da4a5ad
2958fd1
0a68bea
fd08928
4e03e0d
92b6e6c
ffa881e
99c964b
7f7db2c
5e5ff9a
ad20b64
d16266b
0982d9f
0ef7b5e
e75fd87
f6414f9
31c0623
ee3701f
a0ac748
1dd6df1
a737200
3fd9270
5a9748c
9a6b1f2
1c7f6d5
470f74f
bba7c2d
2cb348c
c65bc57
1c655f7
697c04f
d4fd9d9
a57d634
234a8b6
4bef633
7aa7231
1d923ab
aee908a
33cb62d
55e37a3
d4d657b
8d6b0d0
76b2a75
70e51cd
69ebe6c
c32be86
b8dc7dd
4800d91
9124b58
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| <?php | ||
| /** | ||
| * Behaviors. | ||
| * | ||
| * Updates the block editor settings with the theme's behaviors. | ||
| * | ||
| * @package gutenberg | ||
| */ | ||
|
|
||
| add_filter( | ||
| 'block_editor_settings_all', | ||
| function( $settings ) { | ||
| $theme_data = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_data(); | ||
| if ( array_key_exists( 'behaviors', $theme_data ) ) { | ||
| $settings['behaviors'] = $theme_data['behaviors']; | ||
| } | ||
| return $settings; | ||
| }, | ||
| PHP_INT_MAX | ||
michalczaplinski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ); | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| /** | ||
| * WordPress dependencies | ||
| */ | ||
| import { addFilter } from '@wordpress/hooks'; | ||
| import { SelectControl } from '@wordpress/components'; | ||
| import { __ } from '@wordpress/i18n'; | ||
| import { createHigherOrderComponent } from '@wordpress/compose'; | ||
| import { select } from '@wordpress/data'; | ||
|
|
||
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import { InspectorControls } from '../components'; | ||
| import { store as blockEditorStore } from '../store'; | ||
|
|
||
| /** | ||
| * External dependencies | ||
| */ | ||
| import merge from 'deepmerge'; | ||
|
|
||
| /** | ||
| * Override the default edit UI to include a new block inspector control for | ||
| * assigning behaviors to blocks if behaviors are enabled in the theme.json. | ||
| * | ||
| * Currently, only the `core/image` block is supported. | ||
| * | ||
| * @param {WPComponent} BlockEdit Original component. | ||
| * | ||
| * @return {WPComponent} Wrapped component. | ||
| */ | ||
| export const withBehaviors = createHigherOrderComponent( ( BlockEdit ) => { | ||
| return ( props ) => { | ||
| // Only add behaviors to the core/image block. | ||
| if ( props.name !== 'core/image' ) { | ||
| return <BlockEdit { ...props } />; | ||
| } | ||
|
|
||
| const settings = | ||
| select( blockEditorStore ).getSettings()?.__experimentalFeatures | ||
| ?.blocks?.[ props.name ]?.behaviors; | ||
|
|
||
| if ( | ||
| ! settings || | ||
| // If every behavior is disabled, do not show the behaviors inspector control. | ||
| Object.entries( settings ).every( ( [ , value ] ) => ! value ) | ||
| ) { | ||
| return <BlockEdit { ...props } />; | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a subtile issue that may or may not result in a bug. The fact that we conditionally render The remount often create focus loss and issues like that. While this might not always be a problem, it is a problem in general if the condition "can" change when the component is mounted (I'm not sure it's the case here)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That conditional is reading a theme.json value. I don't think that condition can change without a page reload 🤔
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, probably fine for now, just something to know as sometimes we used to switch over attribute values (easy to add a check there). Also, maybe at some point in the future, that setting could be editable in the global styles UI in the site editor.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That is the next step after merging this PR, so we should then take a look at this issue. |
||
|
|
||
| const { behaviors: blockBehaviors } = props.attributes; | ||
|
|
||
| // Get the theme behaviors for the block from the theme.json. | ||
| const themeBehaviors = | ||
| select( blockEditorStore ).getBehaviors()?.blocks?.[ props.name ]; | ||
|
|
||
| // Block behaviors take precedence over theme behaviors. | ||
| const behaviors = merge( themeBehaviors, blockBehaviors || {} ); | ||
|
|
||
| return ( | ||
| <> | ||
| <BlockEdit { ...props } /> | ||
| <InspectorControls group="advanced"> | ||
| <SelectControl | ||
| __nextHasNoMarginBottom | ||
| label={ __( 'Behaviors' ) } | ||
| // At the moment we are only supporting one behavior (Lightbox) | ||
| value={ behaviors?.lightbox ? 'lightbox' : '' } | ||
| options={ Object.entries( settings ) | ||
| .filter( ( [ , behaviorValue ] ) => behaviorValue ) // Filter out behaviors that are disabled. | ||
| .map( ( [ behaviorName ] ) => ( { | ||
| value: behaviorName, | ||
| label: | ||
| // Capitalize the first letter of the behavior name. | ||
| behaviorName[ 0 ].toUpperCase() + | ||
| behaviorName.slice( 1 ).toLowerCase(), | ||
| } ) ) | ||
| .concat( { | ||
| value: '', | ||
| label: __( 'No behaviors' ), | ||
| } ) } | ||
| onChange={ ( nextValue ) => { | ||
| // If the user selects something, it means that they want to | ||
| // change the default value (true) so we save it in the attributes. | ||
| props.setAttributes( { | ||
| behaviors: { | ||
| lightbox: nextValue === 'lightbox', | ||
| }, | ||
| } ); | ||
| } } | ||
| hideCancelButton={ true } | ||
| help={ __( 'Add behaviors' ) } | ||
| size="__unstable-large" | ||
| /> | ||
| </InspectorControls> | ||
| </> | ||
| ); | ||
| }; | ||
| }, 'withBehaviors' ); | ||
|
|
||
| addFilter( | ||
| 'editor.BlockEdit', | ||
| 'core/behaviors/with-inspector-control', | ||
| withBehaviors | ||
| ); | ||
Uh oh!
There was an error while loading. Please reload this page.