-
Notifications
You must be signed in to change notification settings - Fork 4.7k
register template part variations server side. #31761
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
Changes from all commits
64bbb36
8d2fbae
2360ad3
b99b59d
ba6c893
4c10d79
ee9aa69
cd2dd76
1f1264d
ff7852f
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,51 @@ | ||
| /** | ||
| * WordPress dependencies | ||
| */ | ||
| import { __ } from '@wordpress/i18n'; | ||
| import { header as headerIcon, footer as footerIcon } from '@wordpress/icons'; | ||
| import { store as coreDataStore } from '@wordpress/core-data'; | ||
| import { select } from '@wordpress/data'; | ||
|
|
||
| const fallbackVariations = [ | ||
| { | ||
| name: 'header', | ||
| icon: headerIcon, | ||
| title: __( 'Header' ), | ||
| description: __( | ||
| 'The Header template defines a page area that typically contains a title, logo, and main navigation.' | ||
| ), | ||
| attributes: { area: 'header' }, | ||
| scope: [ 'inserter' ], | ||
| }, | ||
| { | ||
| name: 'footer', | ||
| icon: footerIcon, | ||
| title: __( 'Footer' ), | ||
| description: __( | ||
| 'The Footer template defines a page area that typically contains site credits, social links, or any other combination of blocks.' | ||
| ), | ||
| attributes: { area: 'footer' }, | ||
| scope: [ 'inserter' ], | ||
| }, | ||
| ]; | ||
|
|
||
| fallbackVariations.forEach( ( variation ) => { | ||
| if ( variation.isActive ) return; | ||
| variation.isActive = ( blockAttributes, variationAttributes ) => { | ||
| const { area, theme, slug } = blockAttributes; | ||
| // We first check the `area` block attribute which is set during insertion. | ||
| // This property is removed on the creation of a template part. | ||
| if ( area ) return area === variationAttributes.area; | ||
| // Find a matching variation from the created template part | ||
| // by checking the entity's `area` property. | ||
| if ( ! slug ) return false; | ||
| const entity = select( coreDataStore ).getEntityRecord( | ||
| 'postType', | ||
| 'wp_template_part', | ||
| `${ theme }//${ slug }` | ||
| ); | ||
| return entity?.area === variationAttributes.area; | ||
| }; | ||
| } ); | ||
|
|
||
| export default fallbackVariations; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,41 +2,43 @@ | |
| * WordPress dependencies | ||
| */ | ||
| import { store as coreDataStore } from '@wordpress/core-data'; | ||
| import { store as editorStore } from '@wordpress/editor'; | ||
| import { store as blocksStore } from '@wordpress/blocks'; | ||
| import { dispatch, select, subscribe } from '@wordpress/data'; | ||
| import { select } from '@wordpress/data'; | ||
| import { | ||
| header as headerIcon, | ||
| footer as footerIcon, | ||
| sidebar as sidebarIcon, | ||
| layout as layoutIcon, | ||
| } from '@wordpress/icons'; | ||
|
|
||
| const unsubscribe = subscribe( () => { | ||
| const definedVariations = select( | ||
| editorStore | ||
| ).__experimentalGetDefaultTemplatePartAreas(); | ||
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import fallbackVariations from './fallback-variations'; | ||
|
|
||
| if ( ! definedVariations?.length ) { | ||
| return; | ||
| function getTemplatePartIcon( iconName ) { | ||
| if ( 'header' === iconName ) { | ||
| return headerIcon; | ||
| } else if ( 'footer' === iconName ) { | ||
| return footerIcon; | ||
| } else if ( 'sidebar' === iconName ) { | ||
| return sidebarIcon; | ||
| } | ||
| unsubscribe(); | ||
| return layoutIcon; | ||
| } | ||
|
|
||
| const variations = definedVariations | ||
| .filter( ( { area } ) => 'uncategorized' !== area ) | ||
| .map( ( { area, label, description, icon } ) => { | ||
| return { | ||
| name: area, | ||
| title: label, | ||
| description, | ||
| icon, | ||
| attributes: { area }, | ||
| scope: [ 'inserter' ], | ||
| }; | ||
| } ); | ||
| export function enhanceTemplatePartVariations( settings, name ) { | ||
| if ( name !== 'core/template-part' ) { | ||
| return settings; | ||
| } | ||
|
|
||
| // WordPress versions pre-5.8 do not support server side variation registration. | ||
| // So we must register the fallback variations until those versions are no longer supported. | ||
| if ( ! ( settings.variations && settings.variations.length ) ) { | ||
| return { ...settings, variations: fallbackVariations }; | ||
| } | ||
|
|
||
| /** | ||
| * Add `isActive` function to all `Template Part` variations, if not defined. | ||
| * `isActive` function is used to find a variation match from a created | ||
| * Block by providing its attributes. | ||
| */ | ||
| variations.forEach( ( variation ) => { | ||
| if ( variation.isActive ) return; | ||
| variation.isActive = ( blockAttributes, variationAttributes ) => { | ||
| if ( settings.variations ) { | ||
| const isActive = ( blockAttributes, variationAttributes ) => { | ||
| const { area, theme, slug } = blockAttributes; | ||
| // We first check the `area` block attribute which is set during insertion. | ||
| // This property is removed on the creation of a template part. | ||
|
|
@@ -51,10 +53,21 @@ const unsubscribe = subscribe( () => { | |
| ); | ||
| return entity?.area === variationAttributes.area; | ||
| }; | ||
| } ); | ||
|
|
||
| dispatch( blocksStore ).addBlockVariations( | ||
| 'core/template-part', | ||
| variations | ||
| ); | ||
| } ); | ||
| const variations = settings.variations.map( ( variation ) => { | ||
| return { | ||
| ...variation, | ||
| ...( ! variation.isActive && { isActive } ), | ||
| ...( typeof variation.icon === 'string' && { | ||
|
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. Should we check Also related to that, should we just create a mapper object that would contain the
Contributor
Author
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 all makes sense.
I was wondering if maybe there was a way someone could have registered it with an actual icon instead of an icon name, and to just double check if it was a simple string at this point before trying to overwrite it.
Contributor
Author
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, I'l go ahead and limit this to just importing the icons we expect for template parts at this time (header, footer, sidebar, and layout). It would be neat if in the future we could enable registering custom icons with a template part area. Its no requirement at this point, but if instead of defining
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. I was planning on exploring allowing icons to be set with svg strings, but the tricky part is finding a solution that will also work with react native
Contributor
Author
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. @gwwar that would be neat! Im not too familiar with native's limitations there. |
||
| icon: getTemplatePartIcon( variation.icon ), | ||
| } ), | ||
| }; | ||
| } ); | ||
|
|
||
| return { | ||
| ...settings, | ||
| variations, | ||
| }; | ||
| } | ||
| return settings; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.