From ae6afbc0547dd834401e6f16608c91e3e83c47a5 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:21 +0200 Subject: [PATCH 01/81] Initial experiment --- .../src/components/block-switcher/index.js | 43 ++++++++++++++++++- .../src/components/block-switcher/style.scss | 4 ++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index f28d0e49333817..8726f522bc28f5 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -3,12 +3,15 @@ */ import { __, _n, sprintf, _x } from '@wordpress/i18n'; import { - DropdownMenu, ToolbarButton, ToolbarGroup, ToolbarItem, __experimentalText as Text, MenuGroup, + MenuItem, + Dropdown, + DropdownMenu, + FormTokenField, } from '@wordpress/components'; import { switchToBlockType, @@ -29,6 +32,7 @@ import { useBlockVariationTransforms } from './block-variation-transformations'; import BlockStylesMenu from './block-styles-menu'; import PatternTransformationsMenu from './pattern-transformations-menu'; import useBlockDisplayTitle from '../block-title/use-block-display-title'; +import { unlock } from '../../lock-unlock'; function BlockSwitcherDropdownMenuContents( { onClose, @@ -114,6 +118,17 @@ function BlockSwitcherDropdownMenuContents( { hasBlockStyles || hasBlockOrBlockVariationTransforms || hasPatternTransformation; + + const { sources } = useSelect( ( select ) => { + const _sources = unlock( + select( blocksStore ) + ).getAllBlockBindingsSources(); + + return { + sources: _sources, + }; + }, [] ); + if ( ! hasContents ) { return (

@@ -170,12 +185,36 @@ function BlockSwitcherDropdownMenuContents( { onSwitch={ onClose } /> ) } - { isUsingBindings && ( + { isUsingBindings ? ( { connectedBlockDescription } + ) : ( + + ( + + { __( 'Connect Block' ) } + + ) } + renderContent={ () => ( + {} } + suggestions={ Object.keys( sources ) } + value={ [] } + className="block-editor-block-switcher__binding-connector" + /> + ) } + /> + ) } ); diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index afcb576bd8db49..a3381e3d73bea7 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -199,3 +199,7 @@ display: block; padding: $grid-unit; } + +.block-editor-block-switcher__binding-connector { + min-width: 100%; +} From 5efa047eb6259b675277178f34cd966bc5735a9d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:21 +0200 Subject: [PATCH 02/81] First experiment of raw custom field for P --- .../block-editor/src/hooks/block-bindings.js | 120 +++++++++++++++++- 1 file changed, 113 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index c61f586575a530..2783004b3d9977 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -9,8 +9,15 @@ import { __experimentalHStack as HStack, __experimentalItemGroup as ItemGroup, __experimentalItem as Item, + Modal, + FormTokenField, + MenuGroup, + MenuItem, + MenuItemsChoice, } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { plus } from '@wordpress/icons'; +import { useState } from '@wordpress/element'; /** * Internal dependencies @@ -18,6 +25,7 @@ import { useSelect } from '@wordpress/data'; import { canBindAttribute } from '../hooks/use-bindings-attributes'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; +import { store as blockEditorStore } from '../store'; export const BlockBindingsPanel = ( { name, metadata } ) => { const { bindings } = metadata || {}; @@ -31,9 +39,8 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { }; }, [] ); - if ( ! bindings ) { - return null; - } + const [ connectionModal, setConnectionModal ] = useState( false ); + const [ metaValues, setMetaValues ] = useState( [] ); // Don't show not allowed attributes. // Don't show the bindings connected to pattern overrides in the inspectors panel. @@ -47,10 +54,64 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { delete filteredBindings[ key ]; } } ); + const data = useSelect( ( select ) => { + // Access the core/editor store + const { getEditedPostAttribute } = select( 'core/editor' ); - if ( Object.keys( filteredBindings ).length === 0 ) { - return null; - } + // Fetch the meta data for the current post + const metaData = getEditedPostAttribute( 'meta' ); + // Return the meta data if you need to use it in your component + return metaData; + }, [] ); + + const { updateBlockAttributes } = useDispatch( 'core/block-editor' ); + + // Inside your component + const fetchMetas = ( value ) => { + // If array contains "core/post-meta" and is array with at least one value. + if ( + Array.isArray( value ) && + value.length > 0 && + value.includes( 'core/post-meta' ) + ) { + setMetaValues( Object.keys( data ) ); + } + }; + + const { _id } = useSelect( ( select ) => { + const { getSelectedBlockClientId } = select( blockEditorStore ); + + const selectedBlockClientId = getSelectedBlockClientId(); + return { + _id: selectedBlockClientId, + }; + }, [] ); + + const onCloseNewConnection = ( value ) => { + // Alert the selected value + setConnectionModal( false ); + setMetaValues( [] ); + + // Use useDispatch to get the updateBlockAttributes function + + // Assuming the block expects a flat structure for its metadata attribute + const newMetadata = { + metadata: { + // Adjust this according to the actual structure expected by your block + bindings: { + content: { + source: 'core/post-meta', + args: { key: value }, + }, + }, + }, + }; + + // Update the block's attributes with the new metadata + updateBlockAttributes( _id, { + ...newMetadata, + } ); + }; return ( @@ -62,6 +123,51 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { help={ __( 'Attributes connected to various sources.' ) } > + setConnectionModal( true ) } + > + { __( 'Add new connection' ) } + + { connectionModal && ( + + setConnectionModal( false ) + } + className="components-modal__block-bindings-modal" + > + { + // Add {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"page_text_custom_field"}}}}} + fetchMetas( value ); + } } + suggestions={ Object.keys( sources ) } + value={ [] } + className="block-editor-block-switcher__binding-connector" + /> + + ) } + { metaValues && metaValues.length > 0 && ( + + + { + return { + label: key, + value: key, + }; + } ) } + onSelect={ ( key ) => { + onCloseNewConnection( key ); + } } + /> + + + ) } { Object.keys( filteredBindings ).map( ( key ) => { return ( From 0a1b636709688464b4aba2bef08e7a2aeefd359f Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:21 +0200 Subject: [PATCH 03/81] use selectors --- .../block-editor/src/hooks/block-bindings.js | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 2783004b3d9977..e71d6feb542185 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -69,11 +69,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { // Inside your component const fetchMetas = ( value ) => { // If array contains "core/post-meta" and is array with at least one value. - if ( - Array.isArray( value ) && - value.length > 0 && - value.includes( 'core/post-meta' ) - ) { + if ( value === 'core/post-meta' ) { setMetaValues( Object.keys( data ) ); } }; @@ -139,16 +135,21 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } className="components-modal__block-bindings-modal" > - { - // Add {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"page_text_custom_field"}}}}} - fetchMetas( value ); - } } - suggestions={ Object.keys( sources ) } - value={ [] } - className="block-editor-block-switcher__binding-connector" - /> + + { + return { + label: key, + value: key, + }; + } + ) } + onSelect={ ( key ) => { + fetchMetas( key ); + } } + /> + ) } { metaValues && metaValues.length > 0 && ( From 1f9900ef48f2395e99c8228a79111c22e681d43d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:21 +0200 Subject: [PATCH 04/81] Use lists --- packages/block-editor/src/hooks/block-bindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index e71d6feb542185..e611b2c2fd3c4a 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -129,7 +129,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { { connectionModal && ( setConnectionModal( false ) } From 8128c0fde73f7511dd9d43032c76cb45366cb9b9 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:21 +0200 Subject: [PATCH 05/81] Remove --- .../block-editor/src/hooks/block-bindings.js | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index e611b2c2fd3c4a..83c787771284ed 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -10,13 +10,13 @@ import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, Modal, - FormTokenField, MenuGroup, MenuItem, MenuItemsChoice, + Icon, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { plus } from '@wordpress/icons'; +import { plus, reset } from '@wordpress/icons'; import { useState } from '@wordpress/element'; /** @@ -109,6 +109,14 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } ); }; + const removeConnection = ( key ) => { + const newMetadata = { ...metadata }; + delete newMetadata.bindings[ key ]; + updateBlockAttributes( _id, { + ...newMetadata, + } ); + }; + return ( { - + { ) } - { Object.keys( filteredBindings ).map( ( key ) => { - return ( - - - { key } - - { sources[ - filteredBindings[ key ].source - ] - ? sources[ - filteredBindings[ key ] - .source - ].label - : filteredBindings[ key ] - .source } - - - - ); - } ) } - + + { Object.keys( filteredBindings ).map( ( key ) => { + const source = sources[ + filteredBindings[ key ].source + ] + ? sources[ filteredBindings[ key ].source ] + .label + : filteredBindings[ key ].source; + return ( + + removeConnection( key ) + } + icon={ reset } + > + { key } - { source } + + ); + } ) } + + From 4eac7dcd3296b8633469fa49ca53fe8728e356d3 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:21 +0200 Subject: [PATCH 06/81] Fix removing --- .../block-editor/src/hooks/block-bindings.js | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 83c787771284ed..a8f43927b3c9fb 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -88,32 +88,36 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { setConnectionModal( false ); setMetaValues( [] ); - // Use useDispatch to get the updateBlockAttributes function - // Assuming the block expects a flat structure for its metadata attribute const newMetadata = { - metadata: { - // Adjust this according to the actual structure expected by your block - bindings: { - content: { - source: 'core/post-meta', - args: { key: value }, - }, + ...metadata, + // Adjust this according to the actual structure expected by your block + bindings: { + ...bindings, + content: { + source: 'core/post-meta', + args: { key: value }, }, }, }; // Update the block's attributes with the new metadata updateBlockAttributes( _id, { - ...newMetadata, + metadata: newMetadata, } ); }; const removeConnection = ( key ) => { const newMetadata = { ...metadata }; delete newMetadata.bindings[ key ]; + if ( Object.keys( newMetadata.bindings ).length === 0 ) { + delete newMetadata.bindings; + } updateBlockAttributes( _id, { - ...newMetadata, + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, } ); }; From db906bd4c93b60cb854c7b9cf2b787c32f62a136 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 07/81] Add new ui --- .../block-editor/src/hooks/block-bindings.js | 127 ++++++++---------- .../src/hooks/use-bindings-attributes.js | 4 + 2 files changed, 60 insertions(+), 71 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index a8f43927b3c9fb..0fc3573de0a466 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -6,41 +6,43 @@ import { store as blocksStore } from '@wordpress/blocks'; import { BaseControl, PanelBody, - __experimentalHStack as HStack, - __experimentalItemGroup as ItemGroup, - __experimentalItem as Item, - Modal, MenuGroup, MenuItem, - MenuItemsChoice, - Icon, + privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { plus, reset } from '@wordpress/icons'; -import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import { canBindAttribute } from '../hooks/use-bindings-attributes'; +import { + canBindAttribute, + getBindableAttributes, +} from '../hooks/use-bindings-attributes'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import { store as blockEditorStore } from '../store'; +const { + DropdownMenuV2: DropdownMenu, + DropdownMenuItemV2: DropdownMenuItem, + DropdownMenuItemLabelV2: DropdownMenuItemLabel, + DropdownMenuItemHelpTextV2: DropDownMenuItemHelpText, +} = unlock( componentsPrivateApis ); + export const BlockBindingsPanel = ( { name, metadata } ) => { const { bindings } = metadata || {}; const { sources } = useSelect( ( select ) => { const _sources = unlock( select( blocksStore ) ).getAllBlockBindingsSources(); - return { sources: _sources, }; }, [] ); - const [ connectionModal, setConnectionModal ] = useState( false ); - const [ metaValues, setMetaValues ] = useState( [] ); + const bindableAttributes = getBindableAttributes( name ); // Don't show not allowed attributes. // Don't show the bindings connected to pattern overrides in the inspectors panel. @@ -66,14 +68,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { const { updateBlockAttributes } = useDispatch( 'core/block-editor' ); - // Inside your component - const fetchMetas = ( value ) => { - // If array contains "core/post-meta" and is array with at least one value. - if ( value === 'core/post-meta' ) { - setMetaValues( Object.keys( data ) ); - } - }; - const { _id } = useSelect( ( select ) => { const { getSelectedBlockClientId } = select( blockEditorStore ); @@ -84,10 +78,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { }, [] ); const onCloseNewConnection = ( value ) => { - // Alert the selected value - setConnectionModal( false ); - setMetaValues( [] ); - // Assuming the block expects a flat structure for its metadata attribute const newMetadata = { ...metadata, @@ -131,56 +121,51 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { help={ __( 'Attributes connected to various sources.' ) } > - setConnectionModal( true ) } + { /* TODO: Hide this input if all metadata attributes are bind */ } + + { __( 'Add new connection' ) } + + } + placement="left" + gutter={ 20 } > - { __( 'Add new connection' ) } - - { connectionModal && ( - - setConnectionModal( false ) - } - className="components-modal__block-bindings-modal" - > - - { - return { - label: key, - value: key, - }; + { bindableAttributes.map( ( attribute ) => ( + + + { attribute } + + + } + placement="left" + gutter={ 10 } + > + { Object.keys( data ).map( ( key ) => ( + + onCloseNewConnection( key ) } - ) } - onSelect={ ( key ) => { - fetchMetas( key ); - } } - /> - - - ) } - { metaValues && metaValues.length > 0 && ( - - - { - return { - label: key, - value: key, - }; - } ) } - onSelect={ ( key ) => { - onCloseNewConnection( key ); - } } - /> - - - ) } + > + + { data[ key ] } + + + { key } + + + ) ) } + + ) ) } + { Object.keys( filteredBindings ).map( ( key ) => { const source = sources[ diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 54b5425bfc44a5..4cac29a8bc5e91 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -91,6 +91,10 @@ export function canBindAttribute( blockName, attributeName ) { ); } +export function getBindableAttributes( blockName ) { + return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; +} + export const withBlockBindingSupport = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { const registry = useRegistry(); From e3578824ff9d572daadcfb24f2c703a997fe4cff Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 08/81] Update attributes --- packages/block-editor/src/hooks/block-bindings.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 0fc3573de0a466..0a02f6c5a690a1 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -77,14 +77,14 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { }; }, [] ); - const onCloseNewConnection = ( value ) => { + const onCloseNewConnection = ( value, attribute ) => { // Assuming the block expects a flat structure for its metadata attribute const newMetadata = { ...metadata, // Adjust this according to the actual structure expected by your block bindings: { ...bindings, - content: { + [ attribute ]: { source: 'core/post-meta', args: { key: value }, }, @@ -151,9 +151,12 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { { Object.keys( data ).map( ( key ) => ( - onCloseNewConnection( key ) - } + onClick={ () => { + onCloseNewConnection( + key, + attribute + ); + } } > { data[ key ] } From 1a18fb61fca8b3b28584f95245b69b4f3bf77505 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 09/81] Check binded number --- .../block-editor/src/hooks/block-bindings.js | 86 ++++++++++--------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 0a02f6c5a690a1..e3c25d732b0b57 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -111,6 +111,9 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } ); }; + const allAttributesBinded = + Object.keys( filteredBindings ).length === bindableAttributes.length; + return ( { > { /* TODO: Hide this input if all metadata attributes are bind */ } - - { __( 'Add new connection' ) } - - } - placement="left" - gutter={ 20 } - > - { bindableAttributes.map( ( attribute ) => ( + { bindableAttributes.length > 0 && + ! allAttributesBinded && ( - - { attribute } - - + + { __( 'Add new connection' ) } + } placement="left" - gutter={ 10 } + gutter={ 20 } > - { Object.keys( data ).map( ( key ) => ( - { - onCloseNewConnection( - key, - attribute - ); - } } + { bindableAttributes.map( ( attribute ) => ( + + + { attribute } + + + } + placement="left" + gutter={ 10 } > - - { data[ key ] } - - - { key } - - + { Object.keys( data ).map( + ( key ) => ( + { + onCloseNewConnection( + key, + attribute + ); + } } + > + + { data[ key ] } + + + { key } + + + ) + ) } + ) ) } - ) ) } - + ) } { Object.keys( filteredBindings ).map( ( key ) => { const source = sources[ From 39b2efa920593f217d7c32327c0d90f56d6d8fa4 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 10/81] Check binded number --- packages/block-editor/src/hooks/block-bindings.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index e3c25d732b0b57..7bc927cb8fe554 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -124,7 +124,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { help={ __( 'Attributes connected to various sources.' ) } > - { /* TODO: Hide this input if all metadata attributes are bind */ } { bindableAttributes.length > 0 && ! allAttributesBinded && ( Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 11/81] Move bindings panel to editor --- packages/block-editor/src/hooks/index.js | 2 - packages/block-editor/src/style.scss | 1 - .../src/hooks/block-bindings.js | 70 ++++++++++++------- .../src/hooks/block-bindings.scss | 0 packages/editor/src/hooks/index.js | 1 + .../src/hooks/use-bindings-attributes.js | 46 ++++++++++++ packages/editor/src/style.scss | 1 + 7 files changed, 94 insertions(+), 27 deletions(-) rename packages/{block-editor => editor}/src/hooks/block-bindings.js (75%) rename packages/{block-editor => editor}/src/hooks/block-bindings.scss (100%) create mode 100644 packages/editor/src/hooks/use-bindings-attributes.js diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index b58ede2e9d389d..1b863c4bf338ec 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -30,14 +30,12 @@ import childLayout from './layout-child'; import contentLockUI from './content-lock-ui'; import './metadata'; import blockHooks from './block-hooks'; -import blockBindingsPanel from './block-bindings'; import './block-renaming'; import './use-bindings-attributes'; import './grid-visualizer'; createBlockEditFilter( [ - blockBindingsPanel, align, textAlign, anchor, diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index e7e4b75d0a30f0..c2165216addfc3 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -46,7 +46,6 @@ @import "./components/tool-selector/style.scss"; @import "./components/url-input/style.scss"; @import "./components/url-popover/style.scss"; -@import "./hooks/block-bindings.scss"; @import "./hooks/block-hooks.scss"; @import "./hooks/border.scss"; @import "./hooks/color.scss"; diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js similarity index 75% rename from packages/block-editor/src/hooks/block-bindings.js rename to packages/editor/src/hooks/block-bindings.js index 7bc927cb8fe554..f29e5c6840e132 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -12,6 +12,7 @@ import { } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { plus, reset } from '@wordpress/icons'; +import { InspectorControls } from '@wordpress/block-editor'; /** * Internal dependencies @@ -19,10 +20,11 @@ import { plus, reset } from '@wordpress/icons'; import { canBindAttribute, getBindableAttributes, -} from '../hooks/use-bindings-attributes'; +} from './use-bindings-attributes'; import { unlock } from '../lock-unlock'; -import InspectorControls from '../components/inspector-controls'; import { store as blockEditorStore } from '../store'; +import { addFilter } from '@wordpress/hooks'; +import { createHigherOrderComponent } from '@wordpress/compose'; const { DropdownMenuV2: DropdownMenu, @@ -31,7 +33,7 @@ const { DropdownMenuItemHelpTextV2: DropDownMenuItemHelpText, } = unlock( componentsPrivateApis ); -export const BlockBindingsPanel = ( { name, metadata } ) => { +const BlockBindingsPanel = ( { name, metadata } ) => { const { bindings } = metadata || {}; const { sources } = useSelect( ( select ) => { const _sources = unlock( @@ -56,17 +58,12 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { delete filteredBindings[ key ]; } } ); - const data = useSelect( ( select ) => { - // Access the core/editor store - const { getEditedPostAttribute } = select( 'core/editor' ); - - // Fetch the meta data for the current post - const metaData = getEditedPostAttribute( 'meta' ); - // Return the meta data if you need to use it in your component - return metaData; + const postMeta = useSelect( ( select ) => { + // eslint-disable-next-line @wordpress/data-no-store-string-literals + return select( 'core/editor' ).getEditedPostAttribute( 'meta' ); }, [] ); - const { updateBlockAttributes } = useDispatch( 'core/block-editor' ); + const { updateBlockAttributes } = useDispatch( blockEditorStore ); const { _id } = useSelect( ( select ) => { const { getSelectedBlockClientId } = select( blockEditorStore ); @@ -112,7 +109,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { }; const allAttributesBinded = - Object.keys( filteredBindings ).length === bindableAttributes.length; + Object.keys( filteredBindings ).length === bindableAttributes?.length; return ( @@ -152,8 +149,12 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { placement="left" gutter={ 10 } > - { Object.keys( data ).map( - ( key ) => ( + { Object.keys( postMeta ) + .filter( + ( value ) => + value !== 'footnotes' + ) + .map( ( key ) => ( { @@ -164,14 +165,13 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } } > - { data[ key ] } + { postMeta[ key ] } { key } - ) - ) } + ) ) } ) ) } @@ -204,10 +204,32 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { ); }; -export default { - edit: BlockBindingsPanel, - attributeKeys: [ 'metadata' ], - hasSupport() { - return true; +/** + * Override the default edit UI to include a new block inspector control for + * assigning a partial syncing controls to supported blocks in the pattern editor. + * Currently, only the `core/paragraph` block is supported. + * + * @param {Component} BlockEdit Original component. + * + * @return {Component} Wrapped component. + */ +const withBlockBindings = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const bindableAttributes = getBindableAttributes( props?.name ); + return ( + <> + + { bindableAttributes.length > 0 && ( + + ) } + + ); }, -}; + 'withBlockBindings' +); + +addFilter( + 'editor.BlockEdit', + 'core/editor/with-block-bindings', + withBlockBindings +); diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss similarity index 100% rename from packages/block-editor/src/hooks/block-bindings.scss rename to packages/editor/src/hooks/block-bindings.scss diff --git a/packages/editor/src/hooks/index.js b/packages/editor/src/hooks/index.js index 6001d53f65c103..8332a1b26ae71c 100644 --- a/packages/editor/src/hooks/index.js +++ b/packages/editor/src/hooks/index.js @@ -5,3 +5,4 @@ import './custom-sources-backwards-compatibility'; import './default-autocompleters'; import './media-upload'; import './pattern-overrides'; +import './block-bindings'; diff --git a/packages/editor/src/hooks/use-bindings-attributes.js b/packages/editor/src/hooks/use-bindings-attributes.js new file mode 100644 index 00000000000000..69d69ea401ffe0 --- /dev/null +++ b/packages/editor/src/hooks/use-bindings-attributes.js @@ -0,0 +1,46 @@ +/** @typedef {import('@wordpress/compose').WPHigherOrderComponent} WPHigherOrderComponent */ +/** @typedef {import('@wordpress/blocks').WPBlockSettings} WPBlockSettings */ + +/** + * Given a binding of block attributes, returns a higher order component that + * overrides its `attributes` and `setAttributes` props to sync any changes needed. + * + * @return {WPHigherOrderComponent} Higher-order component. + */ + +const BLOCK_BINDINGS_ALLOWED_BLOCKS = { + 'core/paragraph': [ 'content' ], + 'core/heading': [ 'content' ], + 'core/image': [ 'id', 'url', 'title', 'alt' ], + 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], +}; + +/** + * Based on the given block name, + * check if it is possible to bind the block. + * + * @param {string} blockName - The block name. + * @return {boolean} Whether it is possible to bind the block to sources. + */ +export function canBindBlock( blockName ) { + return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; +} + +/** + * Based on the given block name and attribute name, + * check if it is possible to bind the block attribute. + * + * @param {string} blockName - The block name. + * @param {string} attributeName - The attribute name. + * @return {boolean} Whether it is possible to bind the block attribute. + */ +export function canBindAttribute( blockName, attributeName ) { + return ( + canBindBlock( blockName ) && + BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) + ); +} + +export function getBindableAttributes( blockName ) { + return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ] || []; +} diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index d1af3095230f34..e1e7089cef53cf 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -56,3 +56,4 @@ @import "./components/table-of-contents/style.scss"; @import "./components/text-editor/style.scss"; @import "./components/visual-editor/style.scss"; +@import "./hooks/block-bindings.scss"; From 88759d351857744a52b7bd612cecac5cd80c8a12 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 12/81] Move code --- packages/editor/src/hooks/block-bindings.js | 26 ++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index f29e5c6840e132..ef70b2e5102ce3 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -1,3 +1,13 @@ +/** + * Internal dependencies + */ +import { + canBindAttribute, + getBindableAttributes, +} from './use-bindings-attributes'; +import { unlock } from '../lock-unlock'; +import { store as editorStore } from '../store'; + /** * WordPress dependencies */ @@ -12,17 +22,10 @@ import { } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { plus, reset } from '@wordpress/icons'; -import { InspectorControls } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ import { - canBindAttribute, - getBindableAttributes, -} from './use-bindings-attributes'; -import { unlock } from '../lock-unlock'; -import { store as blockEditorStore } from '../store'; + InspectorControls, + store as blockEditorStore, +} from '@wordpress/block-editor'; import { addFilter } from '@wordpress/hooks'; import { createHigherOrderComponent } from '@wordpress/compose'; @@ -60,7 +63,7 @@ const BlockBindingsPanel = ( { name, metadata } ) => { } ); const postMeta = useSelect( ( select ) => { // eslint-disable-next-line @wordpress/data-no-store-string-literals - return select( 'core/editor' ).getEditedPostAttribute( 'meta' ); + return select( editorStore ).getEditedPostAttribute( 'meta' ); }, [] ); const { updateBlockAttributes } = useDispatch( blockEditorStore ); @@ -214,6 +217,7 @@ const BlockBindingsPanel = ( { name, metadata } ) => { * @return {Component} Wrapped component. */ const withBlockBindings = createHigherOrderComponent( + // Prevent this from running on every write block. ( BlockEdit ) => ( props ) => { const bindableAttributes = getBindableAttributes( props?.name ); return ( From aa626fe2741bd3462cff6bdac76ff934764f2789 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 13/81] Move to utils --- packages/editor/src/bindings/utils.ts | 56 +++++++++++++ packages/editor/src/hooks/block-bindings.js | 91 ++++++++------------- 2 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 packages/editor/src/bindings/utils.ts diff --git a/packages/editor/src/bindings/utils.ts b/packages/editor/src/bindings/utils.ts new file mode 100644 index 00000000000000..bacd6687542179 --- /dev/null +++ b/packages/editor/src/bindings/utils.ts @@ -0,0 +1,56 @@ +type MetaData = { + bindings?: Record< string, string >; +}; +type UpdateBlockAttributes = ( + id: string, + attributes: Record< string, any > +) => void; + +export const addConnection = ( + value: string, + attribute: string, + metadata: MetaData, + _id: string, + updateBlockAttributes: UpdateBlockAttributes +) => { + // Assuming the block expects a flat structure for its metadata attribute + const newMetadata = { + ...metadata, + // Adjust this according to the actual structure expected by your block + bindings: { + ...metadata?.bindings, + [ attribute ]: { + source: 'core/post-meta', + args: { key: value }, + }, + }, + }; + + // Update the block's attributes with the new metadata + updateBlockAttributes( _id, { + metadata: newMetadata, + } ); +}; + +export const removeConnection = ( + key: string, + metadata: MetaData, + _id: string, + updateBlockAttributes: ( + id: string, + attributes: Record< string, any > + ) => void +) => { + const newMetadata = { ...metadata }; + if ( ! newMetadata.bindings ) { + return; + } + delete newMetadata.bindings[ key ]; + if ( Object.keys( newMetadata.bindings ).length === 0 ) { + delete newMetadata.bindings; + } + updateBlockAttributes( _id, { + metadata: + Object.keys( newMetadata ).length === 0 ? undefined : newMetadata, + } ); +}; diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index ef70b2e5102ce3..cf47608b4bd35d 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -7,6 +7,7 @@ import { } from './use-bindings-attributes'; import { unlock } from '../lock-unlock'; import { store as editorStore } from '../store'; +import { removeConnection, addConnection } from '../bindings/utils'; /** * WordPress dependencies @@ -36,7 +37,7 @@ const { DropdownMenuItemHelpTextV2: DropDownMenuItemHelpText, } = unlock( componentsPrivateApis ); -const BlockBindingsPanel = ( { name, metadata } ) => { +const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { bindings } = metadata || {}; const { sources } = useSelect( ( select ) => { const _sources = unlock( @@ -77,47 +78,13 @@ const BlockBindingsPanel = ( { name, metadata } ) => { }; }, [] ); - const onCloseNewConnection = ( value, attribute ) => { - // Assuming the block expects a flat structure for its metadata attribute - const newMetadata = { - ...metadata, - // Adjust this according to the actual structure expected by your block - bindings: { - ...bindings, - [ attribute ]: { - source: 'core/post-meta', - args: { key: value }, - }, - }, - }; - - // Update the block's attributes with the new metadata - updateBlockAttributes( _id, { - metadata: newMetadata, - } ); - }; - - const removeConnection = ( key ) => { - const newMetadata = { ...metadata }; - delete newMetadata.bindings[ key ]; - if ( Object.keys( newMetadata.bindings ).length === 0 ) { - delete newMetadata.bindings; - } - updateBlockAttributes( _id, { - metadata: - Object.keys( newMetadata ).length === 0 - ? undefined - : newMetadata, - } ); - }; - const allAttributesBinded = Object.keys( filteredBindings ).length === bindableAttributes?.length; return ( { { - onCloseNewConnection( + addConnection( key, - attribute + attribute, + metadata, + _id, + updateBlockAttributes ); } } > @@ -179,27 +149,30 @@ const BlockBindingsPanel = ( { name, metadata } ) => { ) ) } ) } - - { Object.keys( filteredBindings ).map( ( key ) => { - const source = sources[ - filteredBindings[ key ].source - ] - ? sources[ filteredBindings[ key ].source ] - .label - : filteredBindings[ key ].source; - return ( - - removeConnection( key ) - } - icon={ reset } - > - { key } - { source } - - ); - } ) } - + { Object.keys( filteredBindings ).map( ( key ) => { + const source = sources[ + filteredBindings[ key ].source + ] + ? sources[ filteredBindings[ key ].source ] + .label + : filteredBindings[ key ].source; + return ( + + removeConnection( + key, + metadata, + _id, + updateBlockAttributes + ) + } + icon={ reset } + > + { key } - { source } + + ); + } ) } From be20d249feba5cf7e09c08e8da92218dc3542321 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 14/81] Use tools panel for connections --- packages/editor/src/bindings/utils.ts | 18 ++ packages/editor/src/hooks/block-bindings.js | 173 +++++++++----------- 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/packages/editor/src/bindings/utils.ts b/packages/editor/src/bindings/utils.ts index bacd6687542179..f7dc6d65995195 100644 --- a/packages/editor/src/bindings/utils.ts +++ b/packages/editor/src/bindings/utils.ts @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { useViewportMatch } from '@wordpress/compose'; + type MetaData = { bindings?: Record< string, string >; }; @@ -54,3 +59,16 @@ export const removeConnection = ( Object.keys( newMetadata ).length === 0 ? undefined : newMetadata, } ); }; + +export function useToolsPanelDropdownMenuProps() { + const isMobile = useViewportMatch( 'medium', '<' ); + return ! isMobile + ? { + popoverProps: { + placement: 'left-start', + // For non-mobile, inner sidebar width (248px) - button width (24px) - border (1px) + padding (16px) + spacing (20px) + offset: 259, + }, + } + : {}; +} diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index cf47608b4bd35d..85cdeb2efbf8e9 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -7,7 +7,11 @@ import { } from './use-bindings-attributes'; import { unlock } from '../lock-unlock'; import { store as editorStore } from '../store'; -import { removeConnection, addConnection } from '../bindings/utils'; +import { + removeConnection, + addConnection, + useToolsPanelDropdownMenuProps, +} from '../bindings/utils'; /** * WordPress dependencies @@ -15,14 +19,24 @@ import { removeConnection, addConnection } from '../bindings/utils'; import { __ } from '@wordpress/i18n'; import { store as blocksStore } from '@wordpress/blocks'; import { - BaseControl, - PanelBody, MenuGroup, MenuItem, privateApis as componentsPrivateApis, + __experimentalToolsPanel as ToolsPanel, + __experimentalToolsPanelItem as ToolsPanelItem, + __experimentalHStack as Hstack, + __experimentalTruncate as Truncate, + FlexItem, + Icon, + Button, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { plus, reset } from '@wordpress/icons'; +import { + chevronRightSmall, + customPostType, + plus, + reset, +} from '@wordpress/icons'; import { InspectorControls, store as blockEditorStore, @@ -30,12 +44,7 @@ import { import { addFilter } from '@wordpress/hooks'; import { createHigherOrderComponent } from '@wordpress/compose'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, - DropdownMenuItemHelpTextV2: DropDownMenuItemHelpText, -} = unlock( componentsPrivateApis ); +const { DropdownMenuV2: DropdownMenu } = unlock( componentsPrivateApis ); const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { bindings } = metadata || {}; @@ -49,6 +58,7 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { }, [] ); const bindableAttributes = getBindableAttributes( name ); + const dropdownMenuProps = useToolsPanelDropdownMenuProps(); // Don't show not allowed attributes. // Don't show the bindings connected to pattern overrides in the inspectors panel. @@ -83,99 +93,74 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { return ( - {} } + dropdownMenuProps={ dropdownMenuProps } > - - - { bindableAttributes.length > 0 && - ! allAttributesBinded && ( + { bindableAttributes.length > 0 && ! allAttributesBinded && ( + <> + { bindableAttributes.map( ( attribute ) => ( + false } + label={ attribute } + onDeselect={ () => {} } + > - { __( 'Add new connection' ) } - + + + { attribute } + + + + + } placement="left" gutter={ 20 } > - { bindableAttributes.map( ( attribute ) => ( - - - { attribute } - - - } - placement="left" - gutter={ 10 } - > - { Object.keys( postMeta ) - .filter( - ( value ) => - value !== 'footnotes' - ) - .map( ( key ) => ( - { - addConnection( - key, - attribute, - metadata, - _id, - updateBlockAttributes - ); - } } - > - + + { Object.keys( postMeta ).map( + ( key ) => ( + { + addConnection( + key, + attribute, + metadata, + _id, + updateBlockAttributes + ); + } } + icon={ + + } + iconPosition="left" + suffix={ + { postMeta[ key ] } - - - { key } - - - ) ) } - - ) ) } + + } + > + { key } + + ) + ) } + - ) } - { Object.keys( filteredBindings ).map( ( key ) => { - const source = sources[ - filteredBindings[ key ].source - ] - ? sources[ filteredBindings[ key ].source ] - .label - : filteredBindings[ key ].source; - return ( - - removeConnection( - key, - metadata, - _id, - updateBlockAttributes - ) - } - icon={ reset } - > - { key } - { source } - - ); - } ) } - - - + + ) ) } + + ) } + ); }; From 534367823a15b2ae5abe89bb22edffecc5a93f51 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 15/81] Add reset --- packages/editor/src/bindings/utils.ts | 27 ++- packages/editor/src/hooks/block-bindings.js | 178 +++++++++++------- packages/editor/src/hooks/block-bindings.scss | 5 +- 3 files changed, 138 insertions(+), 72 deletions(-) diff --git a/packages/editor/src/bindings/utils.ts b/packages/editor/src/bindings/utils.ts index f7dc6d65995195..8d4b777174df11 100644 --- a/packages/editor/src/bindings/utils.ts +++ b/packages/editor/src/bindings/utils.ts @@ -11,7 +11,7 @@ type UpdateBlockAttributes = ( attributes: Record< string, any > ) => void; -export const addConnection = ( +const addConnection = ( value: string, attribute: string, metadata: MetaData, @@ -30,14 +30,13 @@ export const addConnection = ( }, }, }; - // Update the block's attributes with the new metadata updateBlockAttributes( _id, { metadata: newMetadata, } ); }; -export const removeConnection = ( +const removeConnection = ( key: string, metadata: MetaData, _id: string, @@ -50,6 +49,7 @@ export const removeConnection = ( if ( ! newMetadata.bindings ) { return; } + delete newMetadata.bindings[ key ]; if ( Object.keys( newMetadata.bindings ).length === 0 ) { delete newMetadata.bindings; @@ -60,6 +60,27 @@ export const removeConnection = ( } ); }; +const removeAllConnections = ( + metadata: MetaData, + _id: string, + updateBlockAttributes: UpdateBlockAttributes +) => { + const newMetadata = { ...metadata }; + delete newMetadata.bindings; + updateBlockAttributes( _id, { + metadata: + Object.keys( newMetadata ).length === 0 ? undefined : newMetadata, + } ); +}; + +export function useBindingsUtils() { + return { + addConnection, + removeConnection, + removeAllConnections, + }; +} + export function useToolsPanelDropdownMenuProps() { const isMobile = useViewportMatch( 'medium', '<' ); return ! isMobile diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 85cdeb2efbf8e9..58075cdeb9a005 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -8,8 +8,7 @@ import { import { unlock } from '../lock-unlock'; import { store as editorStore } from '../store'; import { - removeConnection, - addConnection, + useBindingsUtils, useToolsPanelDropdownMenuProps, } from '../bindings/utils'; @@ -17,7 +16,6 @@ import { * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { store as blocksStore } from '@wordpress/blocks'; import { MenuGroup, MenuItem, @@ -26,9 +24,8 @@ import { __experimentalToolsPanelItem as ToolsPanelItem, __experimentalHStack as Hstack, __experimentalTruncate as Truncate, - FlexItem, + __experimentalText as Text, Icon, - Button, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { @@ -48,16 +45,10 @@ const { DropdownMenuV2: DropdownMenu } = unlock( componentsPrivateApis ); const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { bindings } = metadata || {}; - const { sources } = useSelect( ( select ) => { - const _sources = unlock( - select( blocksStore ) - ).getAllBlockBindingsSources(); - return { - sources: _sources, - }; - }, [] ); const bindableAttributes = getBindableAttributes( name ); + const { addConnection, removeConnection, removeAllConnections } = + useBindingsUtils(); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); // Don't show not allowed attributes. @@ -88,74 +79,125 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { }; }, [] ); - const allAttributesBinded = - Object.keys( filteredBindings ).length === bindableAttributes?.length; - return ( {} } + resetAll={ () => { + removeAllConnections( + metadata, + _id, + updateBlockAttributes + ); + } } dropdownMenuProps={ dropdownMenuProps } + className="components-panel__block-bindings-panel" > - { bindableAttributes.length > 0 && ! allAttributesBinded && ( + { bindableAttributes.length > 0 && ( <> { bindableAttributes.map( ( attribute ) => ( false } + hasValue={ () => + !! filteredBindings[ attribute ] + } label={ attribute } - onDeselect={ () => {} } + onDeselect={ () => { + removeConnection( + attribute, + metadata, + _id, + updateBlockAttributes + ); + } } > - - - { attribute } - - - - - - } - placement="left" - gutter={ 20 } - > - - { Object.keys( postMeta ).map( - ( key ) => ( - { - addConnection( - key, - attribute, - metadata, - _id, - updateBlockAttributes - ); - } } - icon={ - - } - iconPosition="left" - suffix={ - - { postMeta[ key ] } - - } - > - { key } - + { !! filteredBindings[ attribute ] ? ( + + removeConnection( + attribute, + metadata, + _id, + updateBlockAttributes ) - ) } - - + } + suffix={ } + className="components-panel__block-bindings-panel-item" + > + + { attribute } + + + { + filteredBindings[ + attribute + ].source + } + + + + ) : ( + + + { attribute } + + + + } + placement="left" + gutter={ 20 } + > + + { Object.keys( postMeta ).map( + ( key ) => ( + { + addConnection( + key, + attribute, + metadata, + _id, + updateBlockAttributes + ); + } } + icon={ + + } + iconPosition="left" + suffix={ + + { + postMeta[ + key + ] + } + + } + > + { key } + + ) + ) } + + + ) } ) ) } diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss index fd46674ad11426..252490afbd3611 100644 --- a/packages/editor/src/hooks/block-bindings.scss +++ b/packages/editor/src/hooks/block-bindings.scss @@ -1,3 +1,6 @@ -.components-panel__block-bindings-panel .components-item__block-bindings-source { +.components-panel__block-bindings-panel .components-panel__block-bindings-panel-item-source { color: $gray-700; } +.components-panel__block-bindings-panel .components-panel__block-bindings-panel-item { + padding: 0; +} From 58054ebe95ae556846437bbd884c68b9b17aa3ee Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 16/81] Add bordered items --- packages/editor/src/hooks/block-bindings.js | 227 ++++++++++-------- packages/editor/src/hooks/block-bindings.scss | 38 ++- 2 files changed, 169 insertions(+), 96 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 58075cdeb9a005..b6a5d6562457ed 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + /** * Internal dependencies */ @@ -5,7 +10,6 @@ import { canBindAttribute, getBindableAttributes, } from './use-bindings-attributes'; -import { unlock } from '../lock-unlock'; import { store as editorStore } from '../store'; import { useBindingsUtils, @@ -19,21 +23,18 @@ import { __ } from '@wordpress/i18n'; import { MenuGroup, MenuItem, - privateApis as componentsPrivateApis, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalHStack as Hstack, __experimentalTruncate as Truncate, - __experimentalText as Text, + __experimentalItemGroup as ItemGroup, + __experimentalDropdownContentWrapper as DropdownContentWrapper, + Dropdown, + Button, Icon, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { - chevronRightSmall, - customPostType, - plus, - reset, -} from '@wordpress/icons'; +import { chevronRightSmall, customPostType } from '@wordpress/icons'; import { InspectorControls, store as blockEditorStore, @@ -41,7 +42,13 @@ import { import { addFilter } from '@wordpress/hooks'; import { createHigherOrderComponent } from '@wordpress/compose'; -const { DropdownMenuV2: DropdownMenu } = unlock( componentsPrivateApis ); +const popoverProps = { + placement: 'left-start', + offset: 36, + shift: true, + className: 'block-editor-block-bindings__popover', + headerTitle: __( 'Custom Fields' ), +}; const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { bindings } = metadata || {}; @@ -82,7 +89,7 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { return ( { removeAllConnections( metadata, @@ -111,93 +118,123 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { ); } } > - { !! filteredBindings[ attribute ] ? ( - - removeConnection( - attribute, - metadata, - _id, - updateBlockAttributes - ) - } - suffix={ } - className="components-panel__block-bindings-panel-item" - > - - { attribute } - - { + const toggleProps = { + onClick: onToggle, + className: clsx( { + 'is-open': isOpen, + } ), + 'aria-expanded': isOpen, + }; + + return ( + + + + ); + } } + renderContent={ () => ( + + - { - filteredBindings[ - attribute - ].source - } - - - - ) : ( - - - { attribute } - - - - } - placement="left" - gutter={ 20 } - > - - { Object.keys( postMeta ).map( - ( key ) => ( - { - addConnection( - key, - attribute, - metadata, - _id, - updateBlockAttributes - ); - } } - icon={ - - } - iconPosition="left" - suffix={ - - { - postMeta[ - key - ] + { Object.keys( postMeta ).map( + ( key ) => ( + { + addConnection( + key, + attribute, + metadata, + _id, + updateBlockAttributes + ); + } } + icon={ + + } + iconPosition="left" + suffix={ + + { + postMeta[ + key + ] + } + + } + > + + { key } - } - > - { key } - - ) - ) } - - - ) } + + ) + ) } + + + ) } + /> ) ) } diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss index 252490afbd3611..4905b2e83161f6 100644 --- a/packages/editor/src/hooks/block-bindings.scss +++ b/packages/editor/src/hooks/block-bindings.scss @@ -1,6 +1,42 @@ +$swatch-size: 28px; +$swatch-gap: 12px; +$popover-width: 460px; +$popover-padding: $grid-unit-20; + +$swatch-columns: math.floor(math.div($popover-width + $swatch-gap - 2 * $popover-padding, $swatch-size + $swatch-gap)); + .components-panel__block-bindings-panel .components-panel__block-bindings-panel-item-source { color: $gray-700; } -.components-panel__block-bindings-panel .components-panel__block-bindings-panel-item { + + +.block-editor-block-bindings__popover { + > .components-popover__content { + padding: $popover-padding; + width: $popover-width; + } + + .components-menu-group__label { + padding: 0; + } + + .components-circular-option-picker__swatches { + display: grid; + grid-template-columns: repeat($swatch-columns, $swatch-size); + gap: $swatch-gap; + justify-content: space-between; + } +} +.block-editor-block-bindings-filters-panel__dropdown { + display: block; padding: 0; + + button { + width: 100%; + padding: $grid-unit-10; + + &.is-open { + background-color: $gray-100; + } + } } From 8e8a122767e7861fb103354285a6a01c8143061e Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 17/81] Fix some styles --- packages/editor/src/hooks/block-bindings.js | 279 ++++++++++-------- packages/editor/src/hooks/block-bindings.scss | 91 ++++-- 2 files changed, 217 insertions(+), 153 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index b6a5d6562457ed..82a8e18cd53443 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -98,147 +98,166 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { ); } } dropdownMenuProps={ dropdownMenuProps } - className="components-panel__block-bindings-panel" + className="block-bindings-support-panel" + hasInnerWrapper + __experimentalFirstVisibleItemClass="first" + __experimentalLastVisibleItemClass="last" > - { bindableAttributes.length > 0 && ( - <> - { bindableAttributes.map( ( attribute ) => ( - - !! filteredBindings[ attribute ] - } - label={ attribute } - onDeselect={ () => { - removeConnection( - attribute, - metadata, - _id, - updateBlockAttributes - ); - } } - > - { - const toggleProps = { - onClick: onToggle, - className: clsx( { - 'is-open': isOpen, - } ), - 'aria-expanded': isOpen, - }; - - return ( - - - +

+ { bindableAttributes.length > 0 && ( + <> + { bindableAttributes.map( ( attribute ) => ( + + !! filteredBindings[ attribute ] + } + label={ attribute } + onDeselect={ () => { + removeConnection( + attribute, + metadata, + _id, + updateBlockAttributes ); } } - renderContent={ () => ( - - - { Object.keys( postMeta ).map( - ( key ) => ( - { - addConnection( - key, - attribute, - metadata, - _id, - updateBlockAttributes - ); - } } - icon={ - - } - iconPosition="left" - suffix={ - - { - postMeta[ - key - ] - } - - } + > + { + const toggleProps = { + onClick: onToggle, + className: clsx( { + 'is-open': isOpen, + } ), + 'aria-expanded': isOpen, + }; + + return ( + + + + ); + } } + renderContent={ () => ( + + + { Object.keys( postMeta ) + .filter( + ( key ) => + key !== + 'footnotes' + ) + .map( ( key ) => ( + { + addConnection( + key, + attribute, + metadata, + _id, + updateBlockAttributes + ); + } } + icon={ + + } + iconPosition="left" + suffix={ + + { + postMeta[ + key + ] + } + + } + > + + { key } + + + ) ) } + + + ) } + /> + + ) ) } + + ) } +
); diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss index 4905b2e83161f6..2c5aca7ae30aed 100644 --- a/packages/editor/src/hooks/block-bindings.scss +++ b/packages/editor/src/hooks/block-bindings.scss @@ -5,38 +5,83 @@ $popover-padding: $grid-unit-20; $swatch-columns: math.floor(math.div($popover-width + $swatch-gap - 2 * $popover-padding, $swatch-size + $swatch-gap)); -.components-panel__block-bindings-panel .components-panel__block-bindings-panel-item-source { - color: $gray-700; -} - +.block-bindings-support-panel { + /* Increased specificity required to remove the slot wrapper's row gap */ + &#{&} { + .block-bindings-block-support-panel__inner-wrapper { + row-gap: 0; + } + } -.block-editor-block-bindings__popover { - > .components-popover__content { - padding: $popover-padding; - width: $popover-width; + .components-panel__block-bindings-panel-item-source { + color: $gray-700; + } + .components-button:hover .components-panel__block-bindings-panel-item-source { + color: inherit; } - .components-menu-group__label { + /** + * The following styles replicate the separated border of the + * `ItemGroup` component but allows for hidden items. This is because + * to maintain the order of `ToolsPanel` controls, each `ToolsPanelItem` + * must at least render a placeholder which would otherwise interfere + * with the `:last-child` styles. + */ + .components-tools-panel-item { padding: 0; - } + max-width: 100%; + + // Border styles. + border-left: 1px solid $gray-300; + border-right: 1px solid $gray-300; + border-bottom: 1px solid $gray-300; + + // Identify the first visible instance as placeholder items will not have this class. + &:nth-child(1 of &) { + border-top-left-radius: $radius-block-ui; + border-top-right-radius: $radius-block-ui; + border-top: 1px solid $gray-300; + } + + // Identify the last visible instance as placeholder items will not have this class. + &:nth-last-child(1 of &) { + border-bottom-left-radius: $radius-block-ui; + border-bottom-right-radius: $radius-block-ui; + } - .components-circular-option-picker__swatches { - display: grid; - grid-template-columns: repeat($swatch-columns, $swatch-size); - gap: $swatch-gap; - justify-content: space-between; + > div, + > div > button { + border-radius: inherit; + } } -} -.block-editor-block-bindings-filters-panel__dropdown { - display: block; - padding: 0; - button { + .block-editor-block-bindings-filters-panel__dropdown { + display: block; + padding: 0; width: 100%; - padding: $grid-unit-10; + button { + width: 100%; + padding: $grid-unit-10; + &.is-open { + background-color: $gray-100; + } + } + } +} - &.is-open { - background-color: $gray-100; +.block-editor-block-bindings__popover { + > .components-popover__content { + padding: $popover-padding; + width: $popover-width; + .components-panel__block-bindings-panel-item-source { + color: $gray-700; } + .components-button:hover .components-panel__block-bindings-panel-item-source { + color: inherit; + } + } + + .components-menu-group__label { + padding: 0; } } From 683abfbdb9dcf70db8ea75c786763190f509231c Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 18/81] Move utils back to component --- packages/editor/src/bindings/utils.ts | 95 --------------------- packages/editor/src/hooks/block-bindings.js | 90 ++++++++++++++----- 2 files changed, 68 insertions(+), 117 deletions(-) delete mode 100644 packages/editor/src/bindings/utils.ts diff --git a/packages/editor/src/bindings/utils.ts b/packages/editor/src/bindings/utils.ts deleted file mode 100644 index 8d4b777174df11..00000000000000 --- a/packages/editor/src/bindings/utils.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * WordPress dependencies - */ -import { useViewportMatch } from '@wordpress/compose'; - -type MetaData = { - bindings?: Record< string, string >; -}; -type UpdateBlockAttributes = ( - id: string, - attributes: Record< string, any > -) => void; - -const addConnection = ( - value: string, - attribute: string, - metadata: MetaData, - _id: string, - updateBlockAttributes: UpdateBlockAttributes -) => { - // Assuming the block expects a flat structure for its metadata attribute - const newMetadata = { - ...metadata, - // Adjust this according to the actual structure expected by your block - bindings: { - ...metadata?.bindings, - [ attribute ]: { - source: 'core/post-meta', - args: { key: value }, - }, - }, - }; - // Update the block's attributes with the new metadata - updateBlockAttributes( _id, { - metadata: newMetadata, - } ); -}; - -const removeConnection = ( - key: string, - metadata: MetaData, - _id: string, - updateBlockAttributes: ( - id: string, - attributes: Record< string, any > - ) => void -) => { - const newMetadata = { ...metadata }; - if ( ! newMetadata.bindings ) { - return; - } - - delete newMetadata.bindings[ key ]; - if ( Object.keys( newMetadata.bindings ).length === 0 ) { - delete newMetadata.bindings; - } - updateBlockAttributes( _id, { - metadata: - Object.keys( newMetadata ).length === 0 ? undefined : newMetadata, - } ); -}; - -const removeAllConnections = ( - metadata: MetaData, - _id: string, - updateBlockAttributes: UpdateBlockAttributes -) => { - const newMetadata = { ...metadata }; - delete newMetadata.bindings; - updateBlockAttributes( _id, { - metadata: - Object.keys( newMetadata ).length === 0 ? undefined : newMetadata, - } ); -}; - -export function useBindingsUtils() { - return { - addConnection, - removeConnection, - removeAllConnections, - }; -} - -export function useToolsPanelDropdownMenuProps() { - const isMobile = useViewportMatch( 'medium', '<' ); - return ! isMobile - ? { - popoverProps: { - placement: 'left-start', - // For non-mobile, inner sidebar width (248px) - button width (24px) - border (1px) + padding (16px) + spacing (20px) - offset: 259, - }, - } - : {}; -} diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 82a8e18cd53443..685586157bd2ed 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -11,10 +11,6 @@ import { getBindableAttributes, } from './use-bindings-attributes'; import { store as editorStore } from '../store'; -import { - useBindingsUtils, - useToolsPanelDropdownMenuProps, -} from '../bindings/utils'; /** * WordPress dependencies @@ -40,7 +36,10 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { addFilter } from '@wordpress/hooks'; -import { createHigherOrderComponent } from '@wordpress/compose'; +import { + createHigherOrderComponent, + useViewportMatch, +} from '@wordpress/compose'; const popoverProps = { placement: 'left-start', @@ -50,12 +49,23 @@ const popoverProps = { headerTitle: __( 'Custom Fields' ), }; +const useToolsPanelDropdownMenuProps = () => { + const isMobile = useViewportMatch( 'medium', '<' ); + return ! isMobile + ? { + popoverProps: { + placement: 'left-start', + // For non-mobile, inner sidebar width (248px) - button width (24px) - border (1px) + padding (16px) + spacing (20px) + offset: 259, + }, + } + : {}; +}; + const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { bindings } = metadata || {}; const bindableAttributes = getBindableAttributes( name ); - const { addConnection, removeConnection, removeAllConnections } = - useBindingsUtils(); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); // Don't show not allowed attributes. @@ -86,16 +96,60 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { }; }, [] ); + const removeAllConnections = () => { + const newMetadata = { ...metadata }; + delete newMetadata.bindings; + updateBlockAttributes( _id, { + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, + } ); + }; + + const addConnection = ( value, attribute ) => { + // Assuming the block expects a flat structure for its metadata attribute + const newMetadata = { + ...metadata, + // Adjust this according to the actual structure expected by your block + bindings: { + ...metadata?.bindings, + [ attribute ]: { + source: 'core/post-meta', + args: { key: value }, + }, + }, + }; + // Update the block's attributes with the new metadata + updateBlockAttributes( _id, { + metadata: newMetadata, + } ); + }; + + const removeConnection = ( key ) => { + const newMetadata = { ...metadata }; + if ( ! newMetadata.bindings ) { + return; + } + + delete newMetadata.bindings[ key ]; + if ( Object.keys( newMetadata.bindings ).length === 0 ) { + delete newMetadata.bindings; + } + updateBlockAttributes( _id, { + metadata: + Object.keys( newMetadata ).length === 0 + ? undefined + : newMetadata, + } ); + }; + return ( { - removeAllConnections( - metadata, - _id, - updateBlockAttributes - ); + removeAllConnections(); } } dropdownMenuProps={ dropdownMenuProps } className="block-bindings-support-panel" @@ -114,12 +168,7 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { } label={ attribute } onDeselect={ () => { - removeConnection( - attribute, - metadata, - _id, - updateBlockAttributes - ); + removeConnection( attribute ); } } > { onClick={ () => { addConnection( key, - attribute, - metadata, - _id, - updateBlockAttributes + attribute ); } } icon={ From d3ba547668599b7ecb8b7fddfa053faea9cd4039 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 19/81] Remove not needed comments --- packages/editor/src/hooks/block-bindings.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 685586157bd2ed..2a20f47c432a4b 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -68,9 +68,6 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const bindableAttributes = getBindableAttributes( name ); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); - // Don't show not allowed attributes. - // Don't show the bindings connected to pattern overrides in the inspectors panel. - // TODO: Explore if this should be abstracted to let other sources decide. const filteredBindings = { ...bindings }; Object.keys( filteredBindings ).forEach( ( key ) => { if ( @@ -81,7 +78,6 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { } } ); const postMeta = useSelect( ( select ) => { - // eslint-disable-next-line @wordpress/data-no-store-string-literals return select( editorStore ).getEditedPostAttribute( 'meta' ); }, [] ); From 3b703f7d0889aab9bf80c21414d40314e9c91075 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 20/81] Some refactor --- packages/editor/src/hooks/block-bindings.js | 250 +++++++++----------- 1 file changed, 106 insertions(+), 144 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 2a20f47c432a4b..32057409eae88f 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -62,6 +62,70 @@ const useToolsPanelDropdownMenuProps = () => { : {}; }; +function BlockBindingsPanelDropdown( { postMeta, addConnection, attribute } ) { + return ( + + + { Object.entries( postMeta ) + .filter( ( [ key ] ) => key !== 'footnotes' ) + .map( ( [ key, value ] ) => ( + addConnection( key, attribute ) } + icon={ } + iconPosition="left" + suffix={ + + { value } + + } + > + + { key } + + + ) ) } + + + ); +} + +function BlockBindingsAttribute( { + toggleProps, + attribute, + filteredBindings, +} ) { + return ( + + + + ); +} + const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { bindings } = metadata || {}; @@ -154,151 +218,49 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { __experimentalLastVisibleItemClass="last" >
- { bindableAttributes.length > 0 && ( - <> - { bindableAttributes.map( ( attribute ) => ( - - !! filteredBindings[ attribute ] - } - label={ attribute } - onDeselect={ () => { - removeConnection( attribute ); + { bindableAttributes.length > 0 && + bindableAttributes.map( ( attribute ) => ( + + !! filteredBindings[ attribute ] + } + label={ attribute } + onDeselect={ () => { + removeConnection( attribute ); + } } + > + { + const toggleProps = { + onClick: onToggle, + className: clsx( { + 'is-open': isOpen, + } ), + 'aria-expanded': isOpen, + }; + return ( + + ); } } - > - { - const toggleProps = { - onClick: onToggle, - className: clsx( { - 'is-open': isOpen, - } ), - 'aria-expanded': isOpen, - }; - - return ( - - - - ); - } } - renderContent={ () => ( - - - { Object.keys( postMeta ) - .filter( - ( key ) => - key !== - 'footnotes' - ) - .map( ( key ) => ( - { - addConnection( - key, - attribute - ); - } } - icon={ - - } - iconPosition="left" - suffix={ - - { - postMeta[ - key - ] - } - - } - > - - { key } - - - ) ) } - - - ) } - /> - - ) ) } - - ) } + renderContent={ () => ( + + ) } + /> + + ) ) }
From f0cd95a3eb35f87f662c4b5c3767558fbccb1597 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 21/81] Prevent UI with no meta data --- packages/editor/src/hooks/block-bindings.js | 88 ++++++++++----------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 32057409eae88f..35fef18037dfa2 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -141,9 +141,6 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { delete filteredBindings[ key ]; } } ); - const postMeta = useSelect( ( select ) => { - return select( editorStore ).getEditedPostAttribute( 'meta' ); - }, [] ); const { updateBlockAttributes } = useDispatch( blockEditorStore ); @@ -203,6 +200,12 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { : newMetadata, } ); }; + const postMeta = useSelect( ( select ) => { + return select( editorStore ).getEditedPostAttribute( 'meta' ); + }, [] ); + if ( postMeta === undefined || bindableAttributes.length === 0 ) { + return null; + } return ( @@ -218,49 +221,46 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { __experimentalLastVisibleItemClass="last" >
- { bindableAttributes.length > 0 && - bindableAttributes.map( ( attribute ) => ( - - !! filteredBindings[ attribute ] - } - label={ attribute } - onDeselect={ () => { - removeConnection( attribute ); - } } - > - { - const toggleProps = { - onClick: onToggle, - className: clsx( { - 'is-open': isOpen, - } ), - 'aria-expanded': isOpen, - }; - return ( - - ); - } } - renderContent={ () => ( - ( + !! filteredBindings[ attribute ] } + label={ attribute } + onDeselect={ () => { + removeConnection( attribute ); + } } + > + { + const toggleProps = { + onClick: onToggle, + className: clsx( { + 'is-open': isOpen, + } ), + 'aria-expanded': isOpen, + }; + return ( + - ) } - /> - - ) ) } + ); + } } + renderContent={ () => ( + + ) } + /> + + ) ) }
From 3bc60721a8d2b039d20d6bd2e02bfe80888dcafe Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 22/81] Add helper --- packages/editor/src/hooks/block-bindings.js | 85 ++++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 35fef18037dfa2..4aff2f056c3f8d 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -28,6 +28,7 @@ import { Dropdown, Button, Icon, + BaseControl, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { chevronRightSmall, customPostType } from '@wordpress/icons'; @@ -221,46 +222,54 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { __experimentalLastVisibleItemClass="last" >
- { bindableAttributes.map( ( attribute ) => ( - !! filteredBindings[ attribute ] } - label={ attribute } - onDeselect={ () => { - removeConnection( attribute ); - } } - > - { - const toggleProps = { - onClick: onToggle, - className: clsx( { - 'is-open': isOpen, - } ), - 'aria-expanded': isOpen, - }; - return ( - + { bindableAttributes.map( ( attribute ) => ( + + !! filteredBindings[ attribute ] + } + label={ attribute } + onDeselect={ () => { + removeConnection( attribute ); + } } + > + { + const toggleProps = { + onClick: onToggle, + className: clsx( { + 'is-open': isOpen, + } ), + 'aria-expanded': isOpen, + }; + return ( + + ); + } } + renderContent={ () => ( + - ); - } } - renderContent={ () => ( - - ) } - /> - - ) ) } + ) } + /> + + ) ) } +
From da6845ec254e79b37b386343e1b5629bb14a502a Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 23/81] Add helper --- packages/editor/src/hooks/block-bindings.js | 89 +++++++++---------- packages/editor/src/hooks/block-bindings.scss | 8 ++ 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/editor/src/hooks/block-bindings.js index 4aff2f056c3f8d..a2840e5e07ba82 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/editor/src/hooks/block-bindings.js @@ -28,7 +28,6 @@ import { Dropdown, Button, Icon, - BaseControl, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { chevronRightSmall, customPostType } from '@wordpress/icons'; @@ -222,54 +221,50 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { __experimentalLastVisibleItemClass="last" >
- - { bindableAttributes.map( ( attribute ) => ( - - !! filteredBindings[ attribute ] - } - label={ attribute } - onDeselect={ () => { - removeConnection( attribute ); - } } - > - { - const toggleProps = { - onClick: onToggle, - className: clsx( { - 'is-open': isOpen, - } ), - 'aria-expanded': isOpen, - }; - return ( - - ); - } } - renderContent={ () => ( - ( + !! filteredBindings[ attribute ] } + label={ attribute } + onDeselect={ () => { + removeConnection( attribute ); + } } + > + { + const toggleProps = { + onClick: onToggle, + className: clsx( { + 'is-open': isOpen, + } ), + 'aria-expanded': isOpen, + }; + return ( + - ) } - /> - - ) ) } - + ); + } } + renderContent={ () => ( + + ) } + /> + + ) ) } + { /* TODO: Add a helper to ToolPanel item */ } +

+ { __( 'Attributes connected to various sources.' ) } +

diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss index 2c5aca7ae30aed..7fd9a0c6b56483 100644 --- a/packages/editor/src/hooks/block-bindings.scss +++ b/packages/editor/src/hooks/block-bindings.scss @@ -11,6 +11,14 @@ $swatch-columns: math.floor(math.div($popover-width + $swatch-gap - 2 * $popover .block-bindings-block-support-panel__inner-wrapper { row-gap: 0; } + .block-bindings-styled-help { + margin-top: $grid-unit-10; + margin-bottom: 0; + font-size: $helptext-font-size; + font-style: normal; + color: $gray-700; + grid-column: 1/-1; + } } .components-panel__block-bindings-panel-item-source { From 28ceffe2575dfa94c38a103f30d257716f155a6d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 24/81] Add simple e2e --- .../editor/various/block-bindings.spec.js | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 1499e255482c63..d80ddcc9c621bd 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1390,6 +1390,24 @@ test.describe( 'Block bindings', () => { 'false' ); } ); + test( 'should show a selector for content', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const contentAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ); + await expect( contentAttribute ).toBeVisible(); + } ); } ); test.describe( 'Heading', () => { @@ -1471,6 +1489,24 @@ test.describe( 'Block bindings', () => { await expect( newEmptyParagraph ).toHaveText( '' ); await expect( newEmptyParagraph ).toBeEditable(); } ); + test( 'should show a selector for content', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const contentAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ); + await expect( contentAttribute ).toBeVisible(); + } ); } ); test.describe( 'Button', () => { @@ -1648,6 +1684,64 @@ test.describe( 'Block bindings', () => { await expect( newEmptyButton ).toHaveText( '' ); await expect( newEmptyButton ).toBeEditable(); } ); + test( 'should show a selector for url, text, linkTarget and rel', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/buttons', + innerBlocks: [ + { + name: 'core/button', + attributes: { + anchor: 'button-text-binding', + text: 'button default text', + url: '#default-url', + metadata: { + bindings: { + text: { + source: 'core/post-meta', + args: { key: 'text_custom_field' }, + }, + }, + }, + }, + }, + ], + } ); + await editor.canvas + .getByRole( 'document', { + name: 'Block: Button', + exact: true, + } ) + .getByRole( 'textbox' ) + .click(); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const urlAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show url', + } ); + await expect( urlAttribute ).toBeVisible(); + const textAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Hide and reset text', + } ); + await expect( textAttribute ).toBeVisible(); + const linkTargetAttribute = page.getByRole( + 'menuitemcheckbox', + { + name: 'Show linkTarget', + } + ); + await expect( linkTargetAttribute ).toBeVisible(); + const relAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show rel', + } ); + await expect( relAttribute ).toBeVisible(); + } ); } ); test.describe( 'Image', () => { @@ -1933,6 +2027,42 @@ test.describe( 'Block bindings', () => { 'default title value' ); } ); + test( 'should show a selector for url, id, title and alt', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/image', + attributes: { + anchor: 'image-multiple-bindings', + url: imagePlaceholderSrc, + alt: 'default alt value', + title: 'default title value', + }, + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + const urlAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show url', + } ); + await expect( urlAttribute ).toBeVisible(); + const idAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show id', + } ); + await expect( idAttribute ).toBeVisible(); + const titleAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show title', + } ); + await expect( titleAttribute ).toBeVisible(); + const altAttribute = page.getByRole( 'menuitemcheckbox', { + name: 'Show alt', + } ); + await expect( altAttribute ).toBeVisible(); + } ); } ); test.describe( 'Edit custom fields', () => { From a90d9da3c35c4a6f854498ed89f8b1c3b36f7df6 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 25/81] Add one more menuitem to the list --- .../block-editor/src/components/block-switcher/test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-switcher/test/index.js b/packages/block-editor/src/components/block-switcher/test/index.js index bc1b7d1a4a3640..e90ab49f1dd730 100644 --- a/packages/block-editor/src/components/block-switcher/test/index.js +++ b/packages/block-editor/src/components/block-switcher/test/index.js @@ -129,7 +129,7 @@ describe( 'BlockSwitcher', () => { } ); await waitFor( () => expect( dropdown ).toBeVisible() ); const items = within( dropdown ).getAllByRole( 'menuitem' ); - expect( items ).toHaveLength( 2 ); + expect( items ).toHaveLength( 3 ); expect( items[ 0 ] ).toHaveTextContent( paragraphBlockType.title ); expect( items[ 1 ] ).toHaveTextContent( headingBlockType.title ); } ); From 2df3ef32c44c0e7dea534265ee146854fe0f03be Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 26/81] Update e2e tests now a new tab appears by default --- test/e2e/specs/editor/blocks/heading.spec.js | 4 ++++ .../editor/plugins/post-type-locking.spec.js | 1 + .../specs/editor/various/block-switcher.spec.js | 17 +++++++++++++++-- .../editor/various/content-only-lock.spec.js | 1 + .../specs/editor/various/editor-modes.spec.js | 11 +++++++---- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/test/e2e/specs/editor/blocks/heading.spec.js b/test/e2e/specs/editor/blocks/heading.spec.js index 4670196c485f5f..0d1957a1048c7b 100644 --- a/test/e2e/specs/editor/blocks/heading.spec.js +++ b/test/e2e/specs/editor/blocks/heading.spec.js @@ -176,6 +176,8 @@ test.describe( 'Heading', () => { await page.keyboard.type( '### Heading' ); await editor.openDocumentSettingsSidebar(); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); + const textColor = page .getByRole( 'region', { name: 'Editor settings', @@ -210,6 +212,8 @@ test.describe( 'Heading', () => { await page.keyboard.type( '## Heading' ); await editor.openDocumentSettingsSidebar(); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); + const textColor = page .getByRole( 'region', { name: 'Editor settings', diff --git a/test/e2e/specs/editor/plugins/post-type-locking.spec.js b/test/e2e/specs/editor/plugins/post-type-locking.spec.js index dc56b6a9b3b421..b3f2decca7d56f 100644 --- a/test/e2e/specs/editor/plugins/post-type-locking.spec.js +++ b/test/e2e/specs/editor/plugins/post-type-locking.spec.js @@ -367,6 +367,7 @@ test.describe( 'Post-type locking', () => { 'Preformatted', 'Pullquote', 'Verse', + 'Connect Block', ] ); } ); } ); diff --git a/test/e2e/specs/editor/various/block-switcher.spec.js b/test/e2e/specs/editor/various/block-switcher.spec.js index 88d58651a715a4..900d9017dcd0d8 100644 --- a/test/e2e/specs/editor/various/block-switcher.spec.js +++ b/test/e2e/specs/editor/various/block-switcher.spec.js @@ -34,7 +34,14 @@ test.describe( 'Block Switcher', () => { await blockSwitcher.click(); await expect( page.getByRole( 'menu', { name: 'List' } ).getByRole( 'menuitem' ) - ).toHaveText( [ 'Paragraph', 'Heading', 'Quote', 'Columns', 'Group' ] ); + ).toHaveText( [ + 'Paragraph', + 'Heading', + 'Quote', + 'Columns', + 'Group', + 'Connect Block', + ] ); } ); test( 'Should show the expected block transforms on the list block when the quote block is removed', async ( { @@ -74,7 +81,13 @@ test.describe( 'Block Switcher', () => { await blockSwitcher.click(); await expect( page.getByRole( 'menu', { name: 'List' } ).getByRole( 'menuitem' ) - ).toHaveText( [ 'Paragraph', 'Heading', 'Columns', 'Group' ] ); + ).toHaveText( [ + 'Paragraph', + 'Heading', + 'Columns', + 'Group', + 'Connect Block', + ] ); } ); test( 'Should not show the block switcher if the block has no styles and cannot be removed', async ( { diff --git a/test/e2e/specs/editor/various/content-only-lock.spec.js b/test/e2e/specs/editor/various/content-only-lock.spec.js index 9784aea1ee068f..a9fef883615b06 100644 --- a/test/e2e/specs/editor/various/content-only-lock.spec.js +++ b/test/e2e/specs/editor/various/content-only-lock.spec.js @@ -113,6 +113,7 @@ test.describe( 'Content-only lock', () => { .locator( 'role=document[name="Block: Paragraph"i]' ) .first() .click(); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await expect( page.locator( '.color-block-support-panel' ) ).toBeAttached(); diff --git a/test/e2e/specs/editor/various/editor-modes.spec.js b/test/e2e/specs/editor/various/editor-modes.spec.js index 95c409f0589e31..3ef05c721dc80b 100644 --- a/test/e2e/specs/editor/various/editor-modes.spec.js +++ b/test/e2e/specs/editor/various/editor-modes.spec.js @@ -39,6 +39,7 @@ test.describe( 'Editing modes (visual/HTML)', () => { await editor.clickBlockOptionsMenuItem( 'Edit as HTML' ); await editor.openDocumentSettingsSidebar(); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); // The `drop cap` toggle for the paragraph block should appear, even in // HTML editing mode. await page @@ -69,6 +70,7 @@ test.describe( 'Editing modes (visual/HTML)', () => { // Make sure the paragraph content is rendered as expected. await expect( paragraphHTML ).toHaveValue( '

Hello world!

' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); // Change the `drop cap` using the sidebar. await page .getByRole( 'button', { name: 'Typography options' } ) @@ -93,10 +95,11 @@ test.describe( 'Editing modes (visual/HTML)', () => { const editorSettings = page.getByRole( 'region', { name: 'Editor settings', } ); - const activeTab = editorSettings.getByRole( 'tab', { selected: true } ); + + const blockTab = editorSettings.getByRole( 'tab', { name: 'Block' } ); // The Block inspector should be active. - await expect( activeTab ).toHaveText( 'Block' ); + await expect( blockTab ).toHaveAttribute( 'data-active-item' ); await expect( editorSettings.locator( '.block-editor-block-card__title' ) ).toHaveText( 'Paragraph' ); @@ -105,9 +108,9 @@ test.describe( 'Editing modes (visual/HTML)', () => { await pageUtils.pressKeys( 'secondary+M' ); // The Block inspector should not be active anymore. - await expect( activeTab ).not.toHaveText( 'Block' ); + await expect( blockTab ).not.toHaveAttribute( 'data-active-item' ); - await editorSettings.getByRole( 'tab', { name: 'Block' } ).click(); + await blockTab.click(); await expect( editorSettings.locator( '.block-editor-block-inspector__no-blocks' ) ).toHaveText( 'No block selected.' ); From 6be184918a75b1092fcab362b2f3a5da6d16c271 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 27/81] Another test --- test/e2e/specs/editor/various/change-detection.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/specs/editor/various/change-detection.spec.js b/test/e2e/specs/editor/various/change-detection.spec.js index 4ac262f4c1348d..e87d81ca7e3d0a 100644 --- a/test/e2e/specs/editor/various/change-detection.spec.js +++ b/test/e2e/specs/editor/various/change-detection.spec.js @@ -451,6 +451,7 @@ test.describe( 'Change detection', () => { ] ); // Change the paragraph's `drop cap`. + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'region', { name: 'Editor settings' } ) .getByRole( 'button', { name: 'Typography options' } ) From 0380ee8e8b55f120e294c8f2272a042b7d66c13f Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 28/81] Add e2e to check paragraph --- .../editor/various/block-bindings.spec.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index d80ddcc9c621bd..9663775681d3ce 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1507,6 +1507,33 @@ test.describe( 'Block bindings', () => { } ); await expect( contentAttribute ).toBeVisible(); } ); + test( 'should use a selector to update the content', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByLabel( 'Attributes options' ) + .click(); + await page + .getByRole( 'menuitemcheckbox', { + name: 'Show content', + } ) + .click(); + await page.getByRole( 'button', { name: 'content' } ).click(); + await page.keyboard.press( 'Enter' ); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Value of the text_custom_field' + ); + } ); } ); test.describe( 'Button', () => { From fe88757027f336e0a862cba7dd3a7362e9bc157d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 29/81] Remove not needed experiment --- .../src/components/block-switcher/index.js | 40 +------------------ .../src/components/block-switcher/style.scss | 4 -- .../components/block-switcher/test/index.js | 2 +- 3 files changed, 2 insertions(+), 44 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index 8726f522bc28f5..dcb24ada1a7855 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -8,10 +8,7 @@ import { ToolbarItem, __experimentalText as Text, MenuGroup, - MenuItem, - Dropdown, DropdownMenu, - FormTokenField, } from '@wordpress/components'; import { switchToBlockType, @@ -32,7 +29,6 @@ import { useBlockVariationTransforms } from './block-variation-transformations'; import BlockStylesMenu from './block-styles-menu'; import PatternTransformationsMenu from './pattern-transformations-menu'; import useBlockDisplayTitle from '../block-title/use-block-display-title'; -import { unlock } from '../../lock-unlock'; function BlockSwitcherDropdownMenuContents( { onClose, @@ -119,16 +115,6 @@ function BlockSwitcherDropdownMenuContents( { hasBlockOrBlockVariationTransforms || hasPatternTransformation; - const { sources } = useSelect( ( select ) => { - const _sources = unlock( - select( blocksStore ) - ).getAllBlockBindingsSources(); - - return { - sources: _sources, - }; - }, [] ); - if ( ! hasContents ) { return (

@@ -185,36 +171,12 @@ function BlockSwitcherDropdownMenuContents( { onSwitch={ onClose } /> ) } - { isUsingBindings ? ( + { isUsingBindings && ( { connectedBlockDescription } - ) : ( - - ( - - { __( 'Connect Block' ) } - - ) } - renderContent={ () => ( - {} } - suggestions={ Object.keys( sources ) } - value={ [] } - className="block-editor-block-switcher__binding-connector" - /> - ) } - /> - ) } ); diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index a3381e3d73bea7..afcb576bd8db49 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -199,7 +199,3 @@ display: block; padding: $grid-unit; } - -.block-editor-block-switcher__binding-connector { - min-width: 100%; -} diff --git a/packages/block-editor/src/components/block-switcher/test/index.js b/packages/block-editor/src/components/block-switcher/test/index.js index e90ab49f1dd730..bc1b7d1a4a3640 100644 --- a/packages/block-editor/src/components/block-switcher/test/index.js +++ b/packages/block-editor/src/components/block-switcher/test/index.js @@ -129,7 +129,7 @@ describe( 'BlockSwitcher', () => { } ); await waitFor( () => expect( dropdown ).toBeVisible() ); const items = within( dropdown ).getAllByRole( 'menuitem' ); - expect( items ).toHaveLength( 3 ); + expect( items ).toHaveLength( 2 ); expect( items[ 0 ] ).toHaveTextContent( paragraphBlockType.title ); expect( items[ 1 ] ).toHaveTextContent( headingBlockType.title ); } ); From 41691df82ccba62ff4b256505302213b1f095b22 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 30/81] Remove extra blank spaces --- packages/block-editor/src/components/block-switcher/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index dcb24ada1a7855..f28d0e49333817 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -3,12 +3,12 @@ */ import { __, _n, sprintf, _x } from '@wordpress/i18n'; import { + DropdownMenu, ToolbarButton, ToolbarGroup, ToolbarItem, __experimentalText as Text, MenuGroup, - DropdownMenu, } from '@wordpress/components'; import { switchToBlockType, @@ -114,7 +114,6 @@ function BlockSwitcherDropdownMenuContents( { hasBlockStyles || hasBlockOrBlockVariationTransforms || hasPatternTransformation; - if ( ! hasContents ) { return (

From 4f097d0da9e90183a8ac876bd7b9a9e850c176b8 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 31/81] update e2e --- .../editor/plugins/post-type-locking.spec.js | 1 - .../specs/editor/various/block-switcher.spec.js | 17 ++--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/test/e2e/specs/editor/plugins/post-type-locking.spec.js b/test/e2e/specs/editor/plugins/post-type-locking.spec.js index b3f2decca7d56f..dc56b6a9b3b421 100644 --- a/test/e2e/specs/editor/plugins/post-type-locking.spec.js +++ b/test/e2e/specs/editor/plugins/post-type-locking.spec.js @@ -367,7 +367,6 @@ test.describe( 'Post-type locking', () => { 'Preformatted', 'Pullquote', 'Verse', - 'Connect Block', ] ); } ); } ); diff --git a/test/e2e/specs/editor/various/block-switcher.spec.js b/test/e2e/specs/editor/various/block-switcher.spec.js index 900d9017dcd0d8..88d58651a715a4 100644 --- a/test/e2e/specs/editor/various/block-switcher.spec.js +++ b/test/e2e/specs/editor/various/block-switcher.spec.js @@ -34,14 +34,7 @@ test.describe( 'Block Switcher', () => { await blockSwitcher.click(); await expect( page.getByRole( 'menu', { name: 'List' } ).getByRole( 'menuitem' ) - ).toHaveText( [ - 'Paragraph', - 'Heading', - 'Quote', - 'Columns', - 'Group', - 'Connect Block', - ] ); + ).toHaveText( [ 'Paragraph', 'Heading', 'Quote', 'Columns', 'Group' ] ); } ); test( 'Should show the expected block transforms on the list block when the quote block is removed', async ( { @@ -81,13 +74,7 @@ test.describe( 'Block Switcher', () => { await blockSwitcher.click(); await expect( page.getByRole( 'menu', { name: 'List' } ).getByRole( 'menuitem' ) - ).toHaveText( [ - 'Paragraph', - 'Heading', - 'Columns', - 'Group', - 'Connect Block', - ] ); + ).toHaveText( [ 'Paragraph', 'Heading', 'Columns', 'Group' ] ); } ); test( 'Should not show the block switcher if the block has no styles and cannot be removed', async ( { From 6e040368b4989f6527dfb4ebad184866041aeed7 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 32/81] Keep updating e2e --- test/e2e/specs/editor/various/font-size-picker.spec.js | 8 ++++++++ .../various/keep-styles-on-block-transforms.spec.js | 3 +++ 2 files changed, 11 insertions(+) diff --git a/test/e2e/specs/editor/various/font-size-picker.spec.js b/test/e2e/specs/editor/various/font-size-picker.spec.js index 597b458d682e84..8616f1f6a66090 100644 --- a/test/e2e/specs/editor/various/font-size-picker.spec.js +++ b/test/e2e/specs/editor/various/font-size-picker.spec.js @@ -28,6 +28,7 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph to be made "small"' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=region[name="Editor settings"i] >> role=button[name="Set custom size"i]' ); @@ -51,6 +52,7 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph reset - custom size' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=region[name="Editor settings"i] >> role=button[name="Set custom size"i]' ); @@ -143,6 +145,7 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph to be made "large"' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=group[name="Font size"i] >> role=combobox[name="Font size"i]' ); @@ -167,6 +170,7 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using tools panel menu' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=group[name="Font size"i] >> role=combobox[name="Font size"i]' ); @@ -200,6 +204,7 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using input field' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=group[name="Font size"i] >> role=combobox[name="Font size"i]' ); @@ -235,6 +240,7 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph to be made "large"' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radiogroup[name="Font size"i] >> role=radio[name="Large"i]' ); @@ -256,6 +262,7 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using tools panel menu' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radiogroup[name="Font size"i] >> role=radio[name="Small"i]' ); @@ -287,6 +294,7 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using input field' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radiogroup[name="Font size"i] >> role=radio[name="Small"i]' ); diff --git a/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js b/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js index 57b958fdfc4b44..b24af6fca8f69d 100644 --- a/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js +++ b/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js @@ -17,6 +17,7 @@ test.describe( 'Keep styles on block transforms', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( '## Heading' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=button[name="Color Text styles"i]' ); await page.click( 'role=option[name="Color: Luminous vivid orange"i]' ); @@ -50,6 +51,7 @@ test.describe( 'Keep styles on block transforms', () => { await page.keyboard.type( 'Line 3 to be made large' ); await pageUtils.pressKeys( 'shift+ArrowUp' ); await pageUtils.pressKeys( 'shift+ArrowUp' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radio[name="Large"i]' ); await page.click( 'role=button[name="Multiple blocks selected"i]' ); await page.click( 'role=menuitem[name="Heading"i]' ); @@ -79,6 +81,7 @@ test.describe( 'Keep styles on block transforms', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Line 1 to be made large' ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radio[name="Large"i]' ); await editor.showBlockToolbar(); await page.click( 'role=button[name="Paragraph"i]' ); From 51904df628d29cda727f64f904e42fc1100575f1 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 33/81] Remove css to the minimum --- packages/editor/src/hooks/block-bindings.scss | 37 ++----------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss index 7fd9a0c6b56483..c58e2abc831de4 100644 --- a/packages/editor/src/hooks/block-bindings.scss +++ b/packages/editor/src/hooks/block-bindings.scss @@ -1,10 +1,3 @@ -$swatch-size: 28px; -$swatch-gap: 12px; -$popover-width: 460px; -$popover-padding: $grid-unit-20; - -$swatch-columns: math.floor(math.div($popover-width + $swatch-gap - 2 * $popover-padding, $swatch-size + $swatch-gap)); - .block-bindings-support-panel { /* Increased specificity required to remove the slot wrapper's row gap */ &#{&} { @@ -37,7 +30,6 @@ $swatch-columns: math.floor(math.div($popover-width + $swatch-gap - 2 * $popover */ .components-tools-panel-item { padding: 0; - max-width: 100%; // Border styles. border-left: 1px solid $gray-300; @@ -62,34 +54,13 @@ $swatch-columns: math.floor(math.div($popover-width + $swatch-gap - 2 * $popover border-radius: inherit; } } - - .block-editor-block-bindings-filters-panel__dropdown { - display: block; - padding: 0; - width: 100%; - button { - width: 100%; - padding: $grid-unit-10; - &.is-open { - background-color: $gray-100; - } - } - } } .block-editor-block-bindings__popover { - > .components-popover__content { - padding: $popover-padding; - width: $popover-width; - .components-panel__block-bindings-panel-item-source { - color: $gray-700; - } - .components-button:hover .components-panel__block-bindings-panel-item-source { - color: inherit; - } + .components-panel__block-bindings-panel-item-source { + color: $gray-700; } - - .components-menu-group__label { - padding: 0; + .components-button:hover .components-panel__block-bindings-panel-item-source { + color: inherit; } } From 28ba254ef7f7d9627b9d1f24ed1c7ad34e62bf7b Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 34/81] Less CSS --- packages/editor/src/hooks/block-bindings.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/editor/src/hooks/block-bindings.scss index c58e2abc831de4..87259836c74ceb 100644 --- a/packages/editor/src/hooks/block-bindings.scss +++ b/packages/editor/src/hooks/block-bindings.scss @@ -29,8 +29,6 @@ * with the `:last-child` styles. */ .components-tools-panel-item { - padding: 0; - // Border styles. border-left: 1px solid $gray-300; border-right: 1px solid $gray-300; From 25051fcb076b854c4f28a6ebf7de2f9ba48e7e4d Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 35/81] Abstract fields and move hooks back to block-editor --- .../src/hooks/block-bindings.js | 118 +++++++++--------- .../src/hooks/block-bindings.scss | 0 packages/block-editor/src/hooks/index.js | 2 + packages/block-editor/src/style.scss | 1 + packages/blocks/src/store/private-actions.js | 1 + packages/blocks/src/store/reducer.js | 1 + packages/editor/src/bindings/post-meta.js | 12 ++ packages/editor/src/hooks/index.js | 1 - .../src/hooks/use-bindings-attributes.js | 46 ------- packages/editor/src/style.scss | 1 - 10 files changed, 75 insertions(+), 108 deletions(-) rename packages/{editor => block-editor}/src/hooks/block-bindings.js (77%) rename packages/{editor => block-editor}/src/hooks/block-bindings.scss (100%) delete mode 100644 packages/editor/src/hooks/use-bindings-attributes.js diff --git a/packages/editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js similarity index 77% rename from packages/editor/src/hooks/block-bindings.js rename to packages/block-editor/src/hooks/block-bindings.js index a2840e5e07ba82..9fd43bfdf8673c 100644 --- a/packages/editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -3,19 +3,11 @@ */ import clsx from 'clsx'; -/** - * Internal dependencies - */ -import { - canBindAttribute, - getBindableAttributes, -} from './use-bindings-attributes'; -import { store as editorStore } from '../store'; - /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { store as blocksStore } from '@wordpress/blocks'; import { MenuGroup, MenuItem, @@ -29,17 +21,22 @@ import { Button, Icon, } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { useContext } from '@wordpress/element'; import { chevronRightSmall, customPostType } from '@wordpress/icons'; +import { useViewportMatch } from '@wordpress/compose'; + +/** + * Internal dependencies + */ import { - InspectorControls, - store as blockEditorStore, -} from '@wordpress/block-editor'; -import { addFilter } from '@wordpress/hooks'; -import { - createHigherOrderComponent, - useViewportMatch, -} from '@wordpress/compose'; + canBindAttribute, + getBindableAttributes, +} from '../hooks/use-bindings-attributes'; +import { store as blockEditorStore } from '../store'; +import { unlock } from '../lock-unlock'; +import InspectorControls from '../components/inspector-controls'; +import BlockContext from '../components/block-context'; const popoverProps = { placement: 'left-start', @@ -62,13 +59,16 @@ const useToolsPanelDropdownMenuProps = () => { : {}; }; -function BlockBindingsPanelDropdown( { postMeta, addConnection, attribute } ) { +function BlockBindingsPanelDropdown( { + fieldsList, + addConnection, + attribute, +} ) { return ( - - { Object.entries( postMeta ) - .filter( ( [ key ] ) => key !== 'footnotes' ) - .map( ( [ key, value ] ) => ( + { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( + + { Object.entries( fields ).map( ( [ key, value ] ) => ( ) ) } - + + ) ) } ); } @@ -126,7 +127,9 @@ function BlockBindingsAttribute( { ); } -const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { +export const BlockBindingsPanel = ( { name, metadata } ) => { + const registry = useRegistry(); + const context = useContext( BlockContext ); const { bindings } = metadata || {}; const bindableAttributes = getBindableAttributes( name ); @@ -144,15 +147,22 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { const { updateBlockAttributes } = useDispatch( blockEditorStore ); - const { _id } = useSelect( ( select ) => { + const { _id, registeredSources } = useSelect( ( select ) => { const { getSelectedBlockClientId } = select( blockEditorStore ); const selectedBlockClientId = getSelectedBlockClientId(); return { _id: selectedBlockClientId, + registeredSources: unlock( + select( blocksStore ) + ).getAllBlockBindingsSources(), }; }, [] ); + if ( bindableAttributes.length === 0 ) { + return null; + } + const removeAllConnections = () => { const newMetadata = { ...metadata }; delete newMetadata.bindings; @@ -200,10 +210,21 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { : newMetadata, } ); }; - const postMeta = useSelect( ( select ) => { - return select( editorStore ).getEditedPostAttribute( 'meta' ); - }, [] ); - if ( postMeta === undefined || bindableAttributes.length === 0 ) { + + const fieldsList = {}; + Object.values( registeredSources ).forEach( + ( { getFieldsList, label } ) => { + if ( getFieldsList ) { + // TODO: Filter only the needed context defined in usesContext. + fieldsList[ label ] = getFieldsList( { + registry, + context, + } ); + } + } + ); + + if ( Object.keys( fieldsList ).length === 0 ) { return null; } @@ -253,7 +274,7 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { } } renderContent={ () => ( @@ -271,33 +292,10 @@ const BlockBindingsPanel = ( { name, attributes: { metadata } } ) => { ); }; -/** - * Override the default edit UI to include a new block inspector control for - * assigning a partial syncing controls to supported blocks in the pattern editor. - * Currently, only the `core/paragraph` block is supported. - * - * @param {Component} BlockEdit Original component. - * - * @return {Component} Wrapped component. - */ -const withBlockBindings = createHigherOrderComponent( - // Prevent this from running on every write block. - ( BlockEdit ) => ( props ) => { - const bindableAttributes = getBindableAttributes( props?.name ); - return ( - <> - - { bindableAttributes.length > 0 && ( - - ) } - - ); +export default { + edit: BlockBindingsPanel, + attributeKeys: [ 'metadata' ], + hasSupport() { + return true; }, - 'withBlockBindings' -); - -addFilter( - 'editor.BlockEdit', - 'core/editor/with-block-bindings', - withBlockBindings -); +}; diff --git a/packages/editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss similarity index 100% rename from packages/editor/src/hooks/block-bindings.scss rename to packages/block-editor/src/hooks/block-bindings.scss diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 1b863c4bf338ec..2f74640ef4f633 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -30,6 +30,7 @@ import childLayout from './layout-child'; import contentLockUI from './content-lock-ui'; import './metadata'; import blockHooks from './block-hooks'; +import blockBindingsPanel from './block-bindings'; import './block-renaming'; import './use-bindings-attributes'; import './grid-visualizer'; @@ -46,6 +47,7 @@ createBlockEditFilter( layout, contentLockUI, blockHooks, + blockBindingsPanel, childLayout, ].filter( Boolean ) ); diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index c2165216addfc3..47b87bb50918df 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -47,6 +47,7 @@ @import "./components/url-input/style.scss"; @import "./components/url-popover/style.scss"; @import "./hooks/block-hooks.scss"; +@import "./hooks/block-bindings.scss"; @import "./hooks/border.scss"; @import "./hooks/color.scss"; @import "./hooks/dimensions.scss"; diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 977270cf1d0c97..6d2f7598ef7838 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -56,6 +56,7 @@ export function addBlockBindingsSource( source ) { setValues: source.setValues, getPlaceholder: source.getPlaceholder, canUserEditValue: source.canUserEditValue, + getFieldsList: source.getFieldsList, }; } diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 2f141fb0cf9927..df6b33314fb492 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -393,6 +393,7 @@ export function blockBindingsSources( state = {}, action ) { setValues: action.setValues, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, + getFieldsList: action.getFieldsList, }, }; case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE': diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index aafc784a21bd4a..e9e8c33419ee76 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -75,4 +75,16 @@ export default { return true; }, + getFieldsList( { registry, context } ) { + const metaFields = registry + .select( coreDataStore ) + .getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta; + // Remove footnotes from the list of fields + delete metaFields.footnotes; + return metaFields; + }, }; diff --git a/packages/editor/src/hooks/index.js b/packages/editor/src/hooks/index.js index 8332a1b26ae71c..6001d53f65c103 100644 --- a/packages/editor/src/hooks/index.js +++ b/packages/editor/src/hooks/index.js @@ -5,4 +5,3 @@ import './custom-sources-backwards-compatibility'; import './default-autocompleters'; import './media-upload'; import './pattern-overrides'; -import './block-bindings'; diff --git a/packages/editor/src/hooks/use-bindings-attributes.js b/packages/editor/src/hooks/use-bindings-attributes.js deleted file mode 100644 index 69d69ea401ffe0..00000000000000 --- a/packages/editor/src/hooks/use-bindings-attributes.js +++ /dev/null @@ -1,46 +0,0 @@ -/** @typedef {import('@wordpress/compose').WPHigherOrderComponent} WPHigherOrderComponent */ -/** @typedef {import('@wordpress/blocks').WPBlockSettings} WPBlockSettings */ - -/** - * Given a binding of block attributes, returns a higher order component that - * overrides its `attributes` and `setAttributes` props to sync any changes needed. - * - * @return {WPHigherOrderComponent} Higher-order component. - */ - -const BLOCK_BINDINGS_ALLOWED_BLOCKS = { - 'core/paragraph': [ 'content' ], - 'core/heading': [ 'content' ], - 'core/image': [ 'id', 'url', 'title', 'alt' ], - 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], -}; - -/** - * Based on the given block name, - * check if it is possible to bind the block. - * - * @param {string} blockName - The block name. - * @return {boolean} Whether it is possible to bind the block to sources. - */ -export function canBindBlock( blockName ) { - return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; -} - -/** - * Based on the given block name and attribute name, - * check if it is possible to bind the block attribute. - * - * @param {string} blockName - The block name. - * @param {string} attributeName - The attribute name. - * @return {boolean} Whether it is possible to bind the block attribute. - */ -export function canBindAttribute( blockName, attributeName ) { - return ( - canBindBlock( blockName ) && - BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) - ); -} - -export function getBindableAttributes( blockName ) { - return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ] || []; -} diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index e1e7089cef53cf..d1af3095230f34 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -56,4 +56,3 @@ @import "./components/table-of-contents/style.scss"; @import "./components/text-editor/style.scss"; @import "./components/visual-editor/style.scss"; -@import "./hooks/block-bindings.scss"; From 981367a6ce976638e31771edc480fb61831b4efd Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 36/81] Return null when no bindableAttributes --- packages/block-editor/src/hooks/block-bindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 9fd43bfdf8673c..ed2b1d76c3418c 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -159,7 +159,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { }; }, [] ); - if ( bindableAttributes.length === 0 ) { + if ( ! bindableAttributes || bindableAttributes.length === 0 ) { return null; } From b1aaa7a0db43cd2c2406b2c93c1302c956754337 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 37/81] Add checks to registration --- packages/blocks/src/api/registration.js | 10 ++++++++++ packages/blocks/src/api/test/registration.js | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 7cce959c78cc80..9acee6ab7b85d9 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -775,6 +775,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * @param {Function} [source.setValues] Function to update multiple values connected to the source. * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. + * @param {Function} [source.getFieldsList] Function to get the lists of fields to expose in the connections panel. * * @example * ```js @@ -800,6 +801,7 @@ export const registerBlockBindingsSource = ( source ) => { setValues, getPlaceholder, canUserEditValue, + getFieldsList, } = source; const existingSource = unlock( @@ -899,6 +901,14 @@ export const registerBlockBindingsSource = ( source ) => { return; } + // Check the `getFieldsList` property is correct. + if ( getFieldsList && typeof getFieldsList !== 'function' ) { + console.error( + 'Block bindings source getFieldsList must be a function.' + ); + return; + } + return unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source ); }; diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index cc339e59d27053..42272525de1e95 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1656,6 +1656,19 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); + // Check the `getFieldsList` callback is correct. + it( 'should reject invalid getFieldsList callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + getFieldsList: 'should be a function', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source getFieldsList must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + // Check correct sources are registered as expected. it( 'should register a valid source', () => { const sourceProperties = { @@ -1665,6 +1678,9 @@ describe( 'blocks', () => { setValues: () => 'new values', getPlaceholder: () => 'placeholder', canUserEditValue: () => true, + getFieldsList: () => { + return { field: 'value' }; + }, }; registerBlockBindingsSource( { name: 'core/valid-source', @@ -1687,6 +1703,7 @@ describe( 'blocks', () => { expect( source.setValues ).toBeUndefined(); expect( source.getPlaceholder ).toBeUndefined(); expect( source.canUserEditValue ).toBeUndefined(); + expect( source.getFieldsList ).toBeUndefined(); unregisterBlockBindingsSource( 'core/valid-source' ); } ); From 3d9182e3864c454015f4279e8fed8580b271a924 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 38/81] Fix when the list of fields is empty --- packages/block-editor/src/hooks/block-bindings.js | 6 +++++- packages/editor/src/bindings/post-meta.js | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ed2b1d76c3418c..191c18a72a6b1a 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -216,10 +216,14 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { ( { getFieldsList, label } ) => { if ( getFieldsList ) { // TODO: Filter only the needed context defined in usesContext. - fieldsList[ label ] = getFieldsList( { + const sourceList = getFieldsList( { registry, context, } ); + // Only add source if the list is not empty. + if ( sourceList ) { + fieldsList[ label ] = { ...sourceList }; + } } } ); diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index e9e8c33419ee76..7ff8ab05c07fec 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -83,6 +83,11 @@ export default { context?.postType, context?.postId ).meta; + + if ( ! metaFields ) { + return null; + } + // Remove footnotes from the list of fields delete metaFields.footnotes; return metaFields; From ff7c393ab3758be2ee2412937e3f3fe91d1c3370 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 39/81] Properly filter footnotes --- packages/editor/src/bindings/post-meta.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 7ff8ab05c07fec..9fb1bf63de08b3 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -89,7 +89,10 @@ export default { } // Remove footnotes from the list of fields - delete metaFields.footnotes; - return metaFields; + return Object.fromEntries( + Object.entries( metaFields ).filter( + ( [ key ] ) => key !== 'footnotes' + ) + ); }, }; From f2469c944fbaf16a210734da925446e03c497a88 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 40/81] Update tests --- test/e2e/specs/editor/various/font-appearance-control.spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/e2e/specs/editor/various/font-appearance-control.spec.js b/test/e2e/specs/editor/various/font-appearance-control.spec.js index 4b148b6dd8587c..df76019dab06f2 100644 --- a/test/e2e/specs/editor/various/font-appearance-control.spec.js +++ b/test/e2e/specs/editor/various/font-appearance-control.spec.js @@ -21,6 +21,7 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); @@ -37,6 +38,7 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); @@ -53,6 +55,7 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); @@ -77,6 +80,7 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); From 26b5988266bd93c2b47ea453c81d413664352c43 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 41/81] Remove classes from component --- .../block-editor/src/hooks/block-bindings.js | 14 ++++---- .../src/hooks/block-bindings.scss | 35 +++++++++++++------ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 191c18a72a6b1a..63b190d702a97a 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -70,7 +70,6 @@ function BlockBindingsPanelDropdown( { { Object.entries( fields ).map( ( [ key, value ] ) => ( addConnection( key, attribute ) } icon={ } @@ -79,7 +78,7 @@ function BlockBindingsPanelDropdown( { { value } @@ -115,7 +114,7 @@ function BlockBindingsAttribute( { { filteredBindings[ attribute ]?.args?.key } @@ -240,12 +239,12 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { removeAllConnections(); } } dropdownMenuProps={ dropdownMenuProps } - className="block-bindings-support-panel" + className="block-editor-block-bindings-support-panel" hasInnerWrapper __experimentalFirstVisibleItemClass="first" __experimentalLastVisibleItemClass="last" > -

+
{ bindableAttributes.map( ( attribute ) => ( { ) ) } { /* TODO: Add a helper to ToolPanel item */ } -

+

{ __( 'Attributes connected to various sources.' ) }

diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 87259836c74ceb..362ada86faa591 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,10 +1,11 @@ -.block-bindings-support-panel { +$popover-width: 320px; +.block-editor-block-bindings-support-panel { /* Increased specificity required to remove the slot wrapper's row gap */ &#{&} { - .block-bindings-block-support-panel__inner-wrapper { + .block-editor-block-bindings-block-support-panel__inner-wrapper { row-gap: 0; } - .block-bindings-styled-help { + .block-editor-block-bindings-styled-help { margin-top: $grid-unit-10; margin-bottom: 0; font-size: $helptext-font-size; @@ -14,15 +15,15 @@ } } - .components-panel__block-bindings-panel-item-source { + .block-editor-block-bindings-panel-item-source { color: $gray-700; } - .components-button:hover .components-panel__block-bindings-panel-item-source { + .components-button:hover .block-editor-block-bindings-panel-item-source { color: inherit; } /** - * The following styles replicate the separated border of the + * The following styles replicatxºe the separated border of the * `ItemGroup` component but allows for hidden items. This is because * to maintain the order of `ToolsPanel` controls, each `ToolsPanelItem` * must at least render a placeholder which would otherwise interfere @@ -52,13 +53,25 @@ border-radius: inherit; } } + .block-editor-block-bindings-filters-panel__dropdown { + width: 100%; + button { + width: 100%; + &.is-open { + background-color: $gray-100; + } + } + } } .block-editor-block-bindings__popover { - .components-panel__block-bindings-panel-item-source { - color: $gray-700; - } - .components-button:hover .components-panel__block-bindings-panel-item-source { - color: inherit; + > .components-popover__content { + width: $popover-width; + .block-editor-block-bindings-panel-item-source { + color: $gray-700; + } + .components-button:hover .block-editor-block-bindings-panel-item-source { + color: inherit; + } } } From 8798953fb78cadeff5d3bba3e17f3d3e8ad3e0f4 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 42/81] Remove all components mention --- .../block-editor/src/hooks/block-bindings.js | 7 +++++-- .../block-editor/src/hooks/block-bindings.scss | 17 ++++------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 63b190d702a97a..ea5a0fa6303a63 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -43,7 +43,6 @@ const popoverProps = { offset: 36, shift: true, className: 'block-editor-block-bindings__popover', - headerTitle: __( 'Custom Fields' ), }; const useToolsPanelDropdownMenuProps = () => { @@ -65,7 +64,10 @@ function BlockBindingsPanelDropdown( { attribute, } ) { return ( - + { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( { Object.entries( fields ).map( ( [ key, value ] ) => ( @@ -253,6 +255,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { onDeselect={ () => { removeConnection( attribute ); } } + className="block-editor-block-bindings-panel-item" > .components-popover__content { - width: $popover-width; - .block-editor-block-bindings-panel-item-source { - color: $gray-700; - } - .components-button:hover .block-editor-block-bindings-panel-item-source { - color: inherit; - } - } +.block-editor-block-bindings__popover_inner-wrapper { + width: $popover-width; } From 27639badfd349b7b97f9d9a25606dca83309e44d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 43/81] Add ignore console error --- packages/blocks/src/api/registration.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 9acee6ab7b85d9..2b7fb3112f1a8d 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -903,6 +903,7 @@ export const registerBlockBindingsSource = ( source ) => { // Check the `getFieldsList` property is correct. if ( getFieldsList && typeof getFieldsList !== 'function' ) { + // eslint-disable-next-line no-console console.error( 'Block bindings source getFieldsList must be a function.' ); From f0a0680aea9aab6fce01890fbc75bbaf0f04ce25 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 44/81] Add icons and fix styling --- .../block-editor/src/hooks/block-bindings.js | 58 +++++++------------ .../src/hooks/block-bindings.scss | 24 +++++++- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ea5a0fa6303a63..ee5f022fdb10d1 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -13,17 +13,14 @@ import { MenuItem, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, - __experimentalHStack as Hstack, __experimentalTruncate as Truncate, - __experimentalItemGroup as ItemGroup, __experimentalDropdownContentWrapper as DropdownContentWrapper, Dropdown, - Button, Icon, } from '@wordpress/components'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { useContext } from '@wordpress/element'; -import { chevronRightSmall, customPostType } from '@wordpress/icons'; +import { customPostType, edit } from '@wordpress/icons'; import { useViewportMatch } from '@wordpress/compose'; /** @@ -77,18 +74,12 @@ function BlockBindingsPanelDropdown( { icon={ } iconPosition="left" suffix={ - + { value } } > - - { key } - + { key } ) ) } @@ -103,28 +94,16 @@ function BlockBindingsAttribute( { filteredBindings, } ) { return ( - - - + + + { attribute } + + { !! filteredBindings[ attribute ] && ( + + { filteredBindings[ attribute ].args.key } + + ) } + ); } @@ -263,10 +242,15 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { renderToggle={ ( { onToggle, isOpen } ) => { const toggleProps = { onClick: onToggle, - className: clsx( { - 'is-open': isOpen, - } ), + className: clsx( + 'block-editor-block-bindings-attributes', + { + 'is-open': isOpen, + } + ), 'aria-expanded': isOpen, + icon: edit, + iconPosition: 'right', }; return ( span { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + } + &[aria-expanded="true"], + &:hover { + .block-editor-block-bindings-panel-item__source { + color: inherit; + } + } + .block-editor-block-bindings-panel-item__source { + color: $gray-700; + width: 100%; + text-align: left; + } + } } .block-editor-block-bindings__popover_inner-wrapper { width: $popover-width; From 42693a44016a7295ffc784bcd3269a83f62ba3db Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 45/81] Remove not needed as p --- packages/block-editor/src/hooks/block-bindings.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ee5f022fdb10d1..7f2fac98f6b82e 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -273,10 +273,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { ) ) } { /* TODO: Add a helper to ToolPanel item */ } -

+

{ __( 'Attributes connected to various sources.' ) }

From b7efec21c0b786cf90e486d9aa594957003984a4 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 46/81] Remove icon --- packages/block-editor/src/hooks/block-bindings.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 7f2fac98f6b82e..283c9a80a05a53 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -20,7 +20,7 @@ import { } from '@wordpress/components'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { useContext } from '@wordpress/element'; -import { customPostType, edit } from '@wordpress/icons'; +import { customPostType } from '@wordpress/icons'; import { useViewportMatch } from '@wordpress/compose'; /** @@ -249,8 +249,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } ), 'aria-expanded': isOpen, - icon: edit, - iconPosition: 'right', }; return ( Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 47/81] Remove icons, show label only if there are more than one source --- packages/block-editor/src/hooks/block-bindings.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 283c9a80a05a53..bf0ad4fb347beb 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -16,11 +16,9 @@ import { __experimentalTruncate as Truncate, __experimentalDropdownContentWrapper as DropdownContentWrapper, Dropdown, - Icon, } from '@wordpress/components'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { useContext } from '@wordpress/element'; -import { customPostType } from '@wordpress/icons'; import { useViewportMatch } from '@wordpress/compose'; /** @@ -66,13 +64,16 @@ function BlockBindingsPanelDropdown( { className="block-editor-block-bindings__popover_inner-wrapper" > { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( - + 1 ? label : null + } + > { Object.entries( fields ).map( ( [ key, value ] ) => ( addConnection( key, attribute ) } - icon={ } - iconPosition="left" suffix={ { value } From 58eb28c022ca71d9c7a5a51ea337dae9171570e5 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:22 +0200 Subject: [PATCH 48/81] Simplify style names --- .../block-editor/src/hooks/block-bindings.js | 23 ++++++++----------- .../src/hooks/block-bindings.scss | 23 ++++++++++--------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index bf0ad4fb347beb..effedb02f79d06 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -37,7 +37,6 @@ const popoverProps = { placement: 'left-start', offset: 36, shift: true, - className: 'block-editor-block-bindings__popover', }; const useToolsPanelDropdownMenuProps = () => { @@ -61,7 +60,7 @@ function BlockBindingsPanelDropdown( { return ( { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( addConnection( key, attribute ) } suffix={ - + { value } } @@ -96,11 +95,9 @@ function BlockBindingsAttribute( { } ) { return ( - - { attribute } - + { attribute } { !! filteredBindings[ attribute ] && ( - + { filteredBindings[ attribute ].args.key } ) } @@ -221,12 +218,12 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { removeAllConnections(); } } dropdownMenuProps={ dropdownMenuProps } - className="block-editor-block-bindings-support-panel" + className="block-editor-bindings__panel" hasInnerWrapper __experimentalFirstVisibleItemClass="first" __experimentalLastVisibleItemClass="last" > -
+
{ bindableAttributes.map( ( attribute ) => ( { onDeselect={ () => { removeConnection( attribute ); } } - className="block-editor-block-bindings-panel-item" + className="block-editor-bindings__item" > { const toggleProps = { onClick: onToggle, className: clsx( - 'block-editor-block-bindings-attributes', + 'block-editor-bindings__attributes', { 'is-open': isOpen, } @@ -272,7 +269,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { ) ) } { /* TODO: Add a helper to ToolPanel item */ } -

+

{ __( 'Attributes connected to various sources.' ) }

diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index e8c812f5715c80..58d9630351d9d3 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,11 +1,11 @@ $popover-width: 360px; -.block-editor-block-bindings-support-panel { +.block-editor-bindings__panel { /* Increased specificity required to remove the slot wrapper's row gap */ &#{&} { - .block-editor-block-bindings-block-support-panel__inner-wrapper { + .block-editor-bindings__panel__inner-wrapper { row-gap: 0; } - .block-editor-block-bindings-styled-help { + .block-editor-bindings__helper { margin-top: $grid-unit-10; margin-bottom: 0; font-size: $helptext-font-size; @@ -15,10 +15,10 @@ $popover-width: 360px; } } - .block-editor-block-bindings-panel-item-source { + .block-editor-bindings__item-source { color: $gray-700; } - button:hover .block-editor-block-bindings-panel-item-source { + button:hover .block-editor-bindings__item-source { color: inherit; } @@ -29,7 +29,7 @@ $popover-width: 360px; * must at least render a placeholder which would otherwise interfere * with the `:last-child` styles. */ - .block-editor-block-bindings-panel-item { + .block-editor-bindings__item { // Border styles. border-left: 1px solid $gray-300; border-right: 1px solid $gray-300; @@ -53,7 +53,7 @@ $popover-width: 360px; border-radius: inherit; } } - .block-editor-block-bindings-filters-panel__dropdown { + .block-editor-bindings__dropdown { width: 100%; button { width: 100%; @@ -62,7 +62,7 @@ $popover-width: 360px; } } } - .block-editor-block-bindings-attributes { + .block-editor-bindings__attributes { height: 100%; min-height: $grid-unit-50; text-transform: capitalize; @@ -74,17 +74,18 @@ $popover-width: 360px; } &[aria-expanded="true"], &:hover { - .block-editor-block-bindings-panel-item__source { + .block-editor-bindings__item-source { color: inherit; } } - .block-editor-block-bindings-panel-item__source { + .block-editor-bindings__item-source { color: $gray-700; width: 100%; text-align: left; } } } -.block-editor-block-bindings__popover_inner-wrapper { +.block-editor-bindings__popover { width: $popover-width; } + From d17b593af813ddc27638f9011e6b0842b35a0b0e Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 49/81] Adapt design --- .../block-editor/src/hooks/block-bindings.js | 13 ++--- .../src/hooks/block-bindings.scss | 47 ++++++++++--------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index effedb02f79d06..940ca7b44b374e 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -73,13 +73,14 @@ function BlockBindingsPanelDropdown( { addConnection( key, attribute ) } - suffix={ - - { value } - - } + className="block-editor-bindings__attributes" > - { key } + + { key } + + + { value } + ) ) } diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 58d9630351d9d3..983ce4f982ff85 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -62,30 +62,33 @@ $popover-width: 360px; } } } - .block-editor-bindings__attributes { - height: 100%; - min-height: $grid-unit-50; - text-transform: capitalize; - > span { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: center; - } - &[aria-expanded="true"], - &:hover { - .block-editor-bindings__item-source { - color: inherit; - } - } - .block-editor-bindings__item-source { - color: $gray-700; - width: 100%; - text-align: left; - } - } } .block-editor-bindings__popover { width: $popover-width; } +.block-editor-bindings__attributes { + height: 100%; + min-height: $grid-unit-50; + > span { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + } + &[aria-expanded="true"], + &:hover { + .block-editor-bindings__item-source { + color: inherit; + } + } + .block-editor-bindings__item-source { + color: $gray-700; + width: 100%; + text-align: left; + } + .block-editor-bindings__item-key { + width: 100%; + text-align: left; + } +} From dfeba8ba6c78fbcef36e2b934f84ec38319e8ef7 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 50/81] Use `ItemGroup` inside `ToolsPanel` --- .../block-editor/src/hooks/block-bindings.js | 56 +++++++------ .../src/hooks/block-bindings.scss | 84 +++---------------- 2 files changed, 40 insertions(+), 100 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 940ca7b44b374e..b43c8199b5c4de 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -9,8 +9,9 @@ import clsx from 'clsx'; import { __ } from '@wordpress/i18n'; import { store as blocksStore } from '@wordpress/blocks'; import { - MenuGroup, - MenuItem, + __experimentalItemGroup as ItemGroup, + __experimentalItem as Item, + __experimentalVStack as VStack, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalTruncate as Truncate, @@ -63,27 +64,26 @@ function BlockBindingsPanelDropdown( { className="block-editor-bindings__popover" > { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( - 1 ? label : null } > { Object.entries( fields ).map( ( [ key, value ] ) => ( - addConnection( key, attribute ) } - className="block-editor-bindings__attributes" > - - { key } - - - { value } - - + + { key } + + { value } + + + ) ) } - + ) ) } ); @@ -95,14 +95,16 @@ function BlockBindingsAttribute( { filteredBindings, } ) { return ( - - { attribute } - { !! filteredBindings[ attribute ] && ( - - { filteredBindings[ attribute ].args.key } - - ) } - + + + { attribute } + { !! filteredBindings[ attribute ] && ( + + { filteredBindings[ attribute ].args.key } + + ) } + + ); } @@ -224,7 +226,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { __experimentalFirstVisibleItemClass="first" __experimentalLastVisibleItemClass="last" > -
+ { bindableAttributes.map( ( attribute ) => ( { /> ) ) } - { /* TODO: Add a helper to ToolPanel item */ } -

- { __( 'Attributes connected to various sources.' ) } -

-
+ + { /* TODO: Add a helper to ToolPanel item */ } +

+ { __( 'Attributes connected to various sources.' ) } +

); diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 983ce4f982ff85..2f108ea05712eb 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,57 +1,12 @@ $popover-width: 360px; .block-editor-bindings__panel { - /* Increased specificity required to remove the slot wrapper's row gap */ - &#{&} { - .block-editor-bindings__panel__inner-wrapper { - row-gap: 0; - } - .block-editor-bindings__helper { - margin-top: $grid-unit-10; - margin-bottom: 0; - font-size: $helptext-font-size; - font-style: normal; - color: $gray-700; - grid-column: 1/-1; - } - } - - .block-editor-bindings__item-source { + .block-editor-bindings__helper { + margin-top: $grid-unit-10; + margin-bottom: 0; + font-size: $helptext-font-size; + font-style: normal; color: $gray-700; - } - button:hover .block-editor-bindings__item-source { - color: inherit; - } - - /** - * The following styles replicatxºe the separated border of the - * `ItemGroup` component but allows for hidden items. This is because - * to maintain the order of `ToolsPanel` controls, each `ToolsPanelItem` - * must at least render a placeholder which would otherwise interfere - * with the `:last-child` styles. - */ - .block-editor-bindings__item { - // Border styles. - border-left: 1px solid $gray-300; - border-right: 1px solid $gray-300; - border-bottom: 1px solid $gray-300; - - // Identify the first visible instance as placeholder items will not have this class. - &:nth-child(1 of &) { - border-top-left-radius: $radius-block-ui; - border-top-right-radius: $radius-block-ui; - border-top: 1px solid $gray-300; - } - - // Identify the last visible instance as placeholder items will not have this class. - &:nth-last-child(1 of &) { - border-bottom-left-radius: $radius-block-ui; - border-bottom-right-radius: $radius-block-ui; - } - - > div, - > div > button { - border-radius: inherit; - } + grid-column: 1/-1; } .block-editor-bindings__dropdown { width: 100%; @@ -66,29 +21,12 @@ $popover-width: 360px; .block-editor-bindings__popover { width: $popover-width; } -.block-editor-bindings__attributes { - height: 100%; - min-height: $grid-unit-50; - > span { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: center; - } - &[aria-expanded="true"], - &:hover { - .block-editor-bindings__item-source { - color: inherit; - } - } - .block-editor-bindings__item-source { +.block-editor-bindings__panel, +.block-editor-bindings__popover { + .block-editor-bindings__item-explanation { color: $gray-700; - width: 100%; - text-align: left; } - .block-editor-bindings__item-key { - width: 100%; - text-align: left; + button:hover .block-editor-bindings__item-explanation { + color: inherit; } } - From 9e67785a829181dae11170c1a76ac261555f374c Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 51/81] Use `Text` component --- packages/block-editor/src/hooks/block-bindings.js | 5 +++-- packages/block-editor/src/hooks/block-bindings.scss | 8 ++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index b43c8199b5c4de..9ce33952d2b388 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -12,6 +12,7 @@ import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, __experimentalVStack as VStack, + __experimentalText as Text, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalTruncate as Truncate, @@ -273,9 +274,9 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { ) ) } { /* TODO: Add a helper to ToolPanel item */ } -

+ { __( 'Attributes connected to various sources.' ) } -

+ ); diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 2f108ea05712eb..305561ecddd2f1 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -1,11 +1,7 @@ -$popover-width: 360px; .block-editor-bindings__panel { .block-editor-bindings__helper { - margin-top: $grid-unit-10; - margin-bottom: 0; + margin: 0; font-size: $helptext-font-size; - font-style: normal; - color: $gray-700; grid-column: 1/-1; } .block-editor-bindings__dropdown { @@ -19,7 +15,7 @@ $popover-width: 360px; } } .block-editor-bindings__popover { - width: $popover-width; + max-width: 360px; } .block-editor-bindings__panel, .block-editor-bindings__popover { From b19d01ea1d7eb8dbf2f46456a285981ea2be8a37 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 52/81] Use `getBlockBindingsSources` function --- packages/block-editor/src/hooks/block-bindings.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 9ce33952d2b388..2a7d9c8b509bf8 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { store as blocksStore } from '@wordpress/blocks'; +import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, @@ -129,15 +129,11 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { const { updateBlockAttributes } = useDispatch( blockEditorStore ); - const { _id, registeredSources } = useSelect( ( select ) => { + const { _id } = useSelect( ( select ) => { const { getSelectedBlockClientId } = select( blockEditorStore ); - const selectedBlockClientId = getSelectedBlockClientId(); return { - _id: selectedBlockClientId, - registeredSources: unlock( - select( blocksStore ) - ).getAllBlockBindingsSources(), + _id: getSelectedBlockClientId(), }; }, [] ); @@ -194,6 +190,8 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { }; const fieldsList = {}; + const { getBlockBindingsSources } = unlock( blocksPrivateApis ); + const registeredSources = getBlockBindingsSources(); Object.values( registeredSources ).forEach( ( { getFieldsList, label } ) => { if ( getFieldsList ) { From fb4a51bd462c9ad738c6be2b5bf3bdc08c3fe98e Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 53/81] Revert change to popover max-width --- packages/block-editor/src/hooks/block-bindings.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 305561ecddd2f1..f24e6b93f562d3 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -15,7 +15,7 @@ } } .block-editor-bindings__popover { - max-width: 360px; + width: 360px; } .block-editor-bindings__panel, .block-editor-bindings__popover { From 6439308152c27290e299e88696cd854661e004e4 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 54/81] Remove not used classes --- packages/block-editor/src/hooks/block-bindings.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 2a7d9c8b509bf8..d46282eee91e34 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - /** * WordPress dependencies */ @@ -234,7 +229,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { onDeselect={ () => { removeConnection( attribute ); } } - className="block-editor-bindings__item" > { renderToggle={ ( { onToggle, isOpen } ) => { const toggleProps = { onClick: onToggle, - className: clsx( - 'block-editor-bindings__attributes', - { - 'is-open': isOpen, - } - ), + className: isOpen ? 'is-open' : '', 'aria-expanded': isOpen, }; return ( From 9f277b387028352ea40c69940d62ed80ce7293d2 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 55/81] Remove unused props --- packages/block-editor/src/hooks/block-bindings.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index d46282eee91e34..1d36713710b80f 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -217,8 +217,6 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { dropdownMenuProps={ dropdownMenuProps } className="block-editor-bindings__panel" hasInnerWrapper - __experimentalFirstVisibleItemClass="first" - __experimentalLastVisibleItemClass="last" > { bindableAttributes.map( ( attribute ) => ( From 0beff3464795b2edeaea0f53a83c6c1784375f0d Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 56/81] Add fallbacks for undefined keys --- .../block-editor/src/hooks/block-bindings.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 1d36713710b80f..28068d6e68d857 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -85,18 +85,17 @@ function BlockBindingsPanelDropdown( { ); } -function BlockBindingsAttribute( { - toggleProps, - attribute, - filteredBindings, -} ) { +function BlockBindingsAttribute( { toggleProps, attribute, binding } ) { + const { source: sourceName, args } = binding || {}; + const sourceProps = + unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); return ( { attribute } - { !! filteredBindings[ attribute ] && ( + { !! binding && ( - { filteredBindings[ attribute ].args.key } + { args?.key || sourceProps?.label || sourceName } ) } @@ -241,8 +240,8 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { ); From 8e6ad14b7b70da19955224a19babda16505b9e94 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 57/81] Try: Use `DropdownMenuV2` --- .../block-editor/src/hooks/block-bindings.js | 120 +++++++++--------- .../src/hooks/block-bindings.scss | 18 --- 2 files changed, 59 insertions(+), 79 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 28068d6e68d857..63f5a4b3806e30 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -6,13 +6,10 @@ import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, - __experimentalVStack as VStack, __experimentalText as Text, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, - __experimentalTruncate as Truncate, - __experimentalDropdownContentWrapper as DropdownContentWrapper, - Dropdown, + privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { useContext } from '@wordpress/element'; @@ -30,11 +27,13 @@ import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; -const popoverProps = { - placement: 'left-start', - offset: 36, - shift: true, -}; +const { + DropdownMenuV2: DropdownMenu, + DropdownMenuGroupV2: DropdownMenuGroup, + DropdownMenuCheckboxItemV2: DropdownMenuCheckboxItem, + DropdownMenuItemLabelV2: DropdownMenuItemLabel, + DropdownMenuItemHelpTextV2: DropdownMenuItemHelpText, +} = unlock( componentsPrivateApis ); const useToolsPanelDropdownMenuProps = () => { const isMobile = useViewportMatch( 'medium', '<' ); @@ -53,53 +52,73 @@ function BlockBindingsPanelDropdown( { fieldsList, addConnection, attribute, + binding, } ) { + const currentKey = binding?.args?.key; return ( - + <> { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( - 1 ? label : null } > { Object.entries( fields ).map( ( [ key, value ] ) => ( - addConnection( key, attribute ) } + name={ attribute + '-binding' } + value={ key } + checked={ key === currentKey } + hideOnClick > - - { key } - - { value } - - - + + { key } + + + { value } + + ) ) } - + ) ) } - + ); } -function BlockBindingsAttribute( { toggleProps, attribute, binding } ) { +function BlockBindingsAttribute( { + fieldsList, + addConnection, + attribute, + binding, +} ) { const { source: sourceName, args } = binding || {}; const sourceProps = unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); return ( - - - { attribute } - { !! binding && ( - - { args?.key || sourceProps?.label || sourceName } - - ) } - - + + { attribute } + { !! binding && ( + + { args?.key || sourceProps?.label || sourceName } + + ) } + + } + > + + ); } @@ -227,32 +246,11 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { removeConnection( attribute ); } } > - { - const toggleProps = { - onClick: onToggle, - className: isOpen ? 'is-open' : '', - 'aria-expanded': isOpen, - }; - return ( - - ); - } } - renderContent={ () => ( - - ) } + ) ) } diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index f24e6b93f562d3..28467db18e24fe 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -4,24 +4,6 @@ font-size: $helptext-font-size; grid-column: 1/-1; } - .block-editor-bindings__dropdown { - width: 100%; - button { - width: 100%; - &.is-open { - background-color: $gray-100; - } - } - } -} -.block-editor-bindings__popover { - width: 360px; -} -.block-editor-bindings__panel, -.block-editor-bindings__popover { - .block-editor-bindings__item-explanation { - color: $gray-700; - } button:hover .block-editor-bindings__item-explanation { color: inherit; } From c9ea7c756bc75a514ffa9aedf911093f7795f6ca Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 58/81] Add button to remove the binding --- .../block-editor/src/hooks/block-bindings.js | 20 +++++++++++++++++-- .../src/hooks/block-bindings.scss | 11 ++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 63f5a4b3806e30..53397c98a29a4d 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -4,6 +4,8 @@ import { __ } from '@wordpress/i18n'; import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; import { + Button, + ButtonGroup, __experimentalItemGroup as ItemGroup, __experimentalItem as Item, __experimentalText as Text, @@ -51,6 +53,7 @@ const useToolsPanelDropdownMenuProps = () => { function BlockBindingsPanelDropdown( { fieldsList, addConnection, + removeConnection, attribute, binding, } ) { @@ -71,7 +74,6 @@ function BlockBindingsPanelDropdown( { name={ attribute + '-binding' } value={ key } checked={ key === currentKey } - hideOnClick > { key } @@ -83,6 +85,17 @@ function BlockBindingsPanelDropdown( { ) ) } ) ) } + + + ); } @@ -90,6 +103,7 @@ function BlockBindingsPanelDropdown( { function BlockBindingsAttribute( { fieldsList, addConnection, + removeConnection, attribute, binding, } ) { @@ -100,7 +114,7 @@ function BlockBindingsAttribute( { { attribute } @@ -115,6 +129,7 @@ function BlockBindingsAttribute( { @@ -249,6 +264,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 28467db18e24fe..8e77fd477259e4 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -8,3 +8,14 @@ color: inherit; } } + +.block-editor-bindings__popover { + .block-editor-bindings__clear-binding { + button { + box-shadow: none; + } + padding-right: 4px; + justify-self: end; + grid-column: 1/-1; + } +} From 436c97fff9a1a1e0008b5f9552bec0d3ae7ae989 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 59/81] Reduce truncate lines to 1 --- packages/block-editor/src/hooks/block-bindings.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 53397c98a29a4d..ac038a97b5c16d 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -75,10 +75,10 @@ function BlockBindingsPanelDropdown( { value={ key } checked={ key === currentKey } > - + { key } - + { value } @@ -117,9 +117,14 @@ function BlockBindingsAttribute( { className="block-editor-bindings__popover" trigger={ - { attribute } + + { attribute } + { !! binding && ( - + { args?.key || sourceProps?.label || sourceName } ) } From 9896dbf287b312a25c41d8ed99af25e884caa873 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 60/81] Fix labels when multiple sources --- .../block-editor/src/hooks/block-bindings.js | 56 +++++++++++-------- .../src/hooks/block-bindings.scss | 4 ++ 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index ac038a97b5c16d..8b6ea728b42d72 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -35,6 +35,7 @@ const { DropdownMenuCheckboxItemV2: DropdownMenuCheckboxItem, DropdownMenuItemLabelV2: DropdownMenuItemLabel, DropdownMenuItemHelpTextV2: DropdownMenuItemHelpText, + DropdownMenuSeparatorV2: DropdownMenuSeparator, } = unlock( componentsPrivateApis ); const useToolsPanelDropdownMenuProps = () => { @@ -61,29 +62,38 @@ function BlockBindingsPanelDropdown( { return ( <> { Object.entries( fieldsList ).map( ( [ label, fields ] ) => ( - 1 ? label : null - } - > - { Object.entries( fields ).map( ( [ key, value ] ) => ( - addConnection( key, attribute ) } - name={ attribute + '-binding' } - value={ key } - checked={ key === currentKey } - > - - { key } - - - { value } - - - ) ) } - + <> + + { Object.keys( fieldsList ).length > 1 && ( + + { label } + + ) } + { Object.entries( fields ).map( ( [ key, value ] ) => ( + + addConnection( key, attribute ) + } + name={ attribute + '-binding' } + value={ key } + checked={ key === currentKey } + > + + { key } + + + { value } + + + ) ) } + + + ) ) } - ); } @@ -182,7 +170,6 @@ function EditableBlockBindingsPanelItems( { From 22e10204b972756c37e756d877c424ddb9e1c1fb Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 64/81] Remove clear button CSS --- packages/block-editor/src/hooks/block-bindings.scss | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.scss b/packages/block-editor/src/hooks/block-bindings.scss index 074d3915367081..ccc99561b1c538 100644 --- a/packages/block-editor/src/hooks/block-bindings.scss +++ b/packages/block-editor/src/hooks/block-bindings.scss @@ -18,12 +18,4 @@ grid-column: 2; margin: $grid-unit-10 0; } - .block-editor-bindings__clear-binding { - button { - box-shadow: none; - } - padding-right: 4px; - justify-self: end; - grid-column: 1/-1; - } } From cabd3d84c964a49018fb275650f5fb1c28cbede1 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 65/81] Don't use DropdownItems outside Dropdown --- .../block-editor/src/hooks/block-bindings.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 08f0e93b0e379c..011b6d9a3f014b 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -9,6 +9,8 @@ import { __experimentalText as Text, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, + __experimentalTruncate as Truncate, + __experimentalVStack as VStack, privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; @@ -103,19 +105,19 @@ function BlockBindingsAttribute( { attribute, binding } ) { const sourceProps = unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName ); return ( - <> - - { attribute } - + + { attribute } { !! binding && ( - - { args?.key || sourceProps?.label || sourceName } - + + { args?.key || sourceProps?.label || sourceName } + + ) } - + ); } From b81472507fb9fd30e003005c400984401b2dd9d3 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:23 +0200 Subject: [PATCH 66/81] Move separator inside menu group --- .../block-editor/src/hooks/block-bindings.js | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 011b6d9a3f014b..b42e23586a9462 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -61,40 +61,36 @@ function BlockBindingsPanelDropdown( { return ( <> { Object.entries( fieldsList ).map( ( [ label, fields ], i ) => ( - <> - - { Object.keys( fieldsList ).length > 1 && ( - - { label } - - ) } - { Object.entries( fields ).map( ( [ key, value ] ) => ( - - addConnection( key, attribute ) - } - name={ attribute + '-binding' } - value={ key } - checked={ key === currentKey } - > - - { key } - - - { value } - - - ) ) } - + + { Object.keys( fieldsList ).length > 1 && ( + + { label } + + ) } + { Object.entries( fields ).map( ( [ key, value ] ) => ( + addConnection( key, attribute ) } + name={ attribute + '-binding' } + value={ key } + checked={ key === currentKey } + > + + { key } + + + { value } + + + ) ) } { i !== Object.keys( fieldsList ).length - 1 && ( ) } - + ) ) } ); From 591bd724fd0387ca29d9d64c6e1138203ddf4341 Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Thu, 25 Jul 2024 12:35:24 +0200 Subject: [PATCH 67/81] Use onChange to better align with radio behavior --- packages/block-editor/src/hooks/block-bindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index b42e23586a9462..2b7d28960214a0 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -74,7 +74,7 @@ function BlockBindingsPanelDropdown( { { Object.entries( fields ).map( ( [ key, value ] ) => ( addConnection( key, attribute ) } + onChange={ () => addConnection( key, attribute ) } name={ attribute + '-binding' } value={ key } checked={ key === currentKey } From 8ffc7f41c1e353514b1d0e1d130a095e3f941b8e Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Thu, 25 Jul 2024 12:35:24 +0200 Subject: [PATCH 68/81] Add aria-hiddden to group heading --- packages/block-editor/src/hooks/block-bindings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 2b7d28960214a0..08d5583bfcce44 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -67,6 +67,7 @@ function BlockBindingsPanelDropdown( { className="block-editor-bindings__source-label" upperCase variant="muted" + aria-hidden > { label } From 13cd09e5ddc3b22a30dc4dc4724ca816259eba9f Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Thu, 25 Jul 2024 12:35:24 +0200 Subject: [PATCH 69/81] Update tests --- test/e2e/specs/editor/various/block-bindings.spec.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 9663775681d3ce..c15b8ece3ad358 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1527,6 +1527,10 @@ test.describe( 'Block bindings', () => { .click(); await page.getByRole( 'button', { name: 'content' } ).click(); await page.keyboard.press( 'Enter' ); + await page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'Value of the text_custom_field' } ) + .click(); const paragraphBlock = editor.canvas.getByRole( 'document', { name: 'Block: Paragraph', } ); @@ -2353,7 +2357,7 @@ test.describe( 'Block bindings', () => { } ); const bindingLabel = page.locator( - '.components-item__block-bindings-source' + '.block-editor-bindings__item-explanation .components-truncate' ); await expect( bindingLabel ).toHaveText( 'Server Source' ); } ); From 3a086ab9e9b750990437ee41b5e592b1ebf598eb Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:24 +0200 Subject: [PATCH 70/81] Reduce custom styles --- packages/block-editor/src/hooks/block-bindings.js | 3 +-- packages/block-editor/src/hooks/block-bindings.scss | 13 +++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 08d5583bfcce44..f13ba7fb016b02 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -295,9 +295,8 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } } dropdownMenuProps={ dropdownMenuProps } className="block-editor-bindings__panel" - hasInnerWrapper > - + { readOnly ? ( Date: Thu, 25 Jul 2024 12:35:24 +0200 Subject: [PATCH 71/81] Properly add block context after latest changes --- packages/block-editor/src/hooks/block-bindings.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index f13ba7fb016b02..e8d98f267016cd 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -182,7 +182,7 @@ function EditableBlockBindingsPanelItems( { export const BlockBindingsPanel = ( { name, metadata } ) => { const registry = useRegistry(); - const context = useContext( BlockContext ); + const blockContext = useContext( BlockContext ); const { bindings } = metadata || {}; const bindableAttributes = getBindableAttributes( name ); @@ -264,9 +264,15 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { const { getBlockBindingsSources } = unlock( blocksPrivateApis ); const registeredSources = getBlockBindingsSources(); Object.values( registeredSources ).forEach( - ( { getFieldsList, label } ) => { + ( { getFieldsList, label, usesContext } ) => { if ( getFieldsList ) { - // TODO: Filter only the needed context defined in usesContext. + // Populate context. + const context = {}; + if ( usesContext?.length ) { + for ( const key of usesContext ) { + context[ key ] = blockContext[ key ]; + } + } const sourceList = getFieldsList( { registry, context, From bc05788b6b5046bcc31e62e7e5f50a61553ed7fe Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:35:24 +0200 Subject: [PATCH 72/81] Adapt tests --- packages/blocks/src/api/registration.js | 4 +- packages/blocks/src/api/test/registration.js | 2 +- .../editor/various/block-bindings.spec.js | 100 ++++++++---------- 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 2b7fb3112f1a8d..e109a7e562f00e 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -904,9 +904,7 @@ export const registerBlockBindingsSource = ( source ) => { // Check the `getFieldsList` property is correct. if ( getFieldsList && typeof getFieldsList !== 'function' ) { // eslint-disable-next-line no-console - console.error( - 'Block bindings source getFieldsList must be a function.' - ); + warning( 'Block bindings source getFieldsList must be a function.' ); return; } diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 42272525de1e95..874d664f139047 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1663,7 +1663,7 @@ describe( 'blocks', () => { label: 'testing', getFieldsList: 'should be a function', } ); - expect( console ).toHaveErroredWith( + expect( console ).toHaveWarnedWith( 'Block bindings source getFieldsList must be a function.' ); expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index c15b8ece3ad358..519a718684fc96 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1408,6 +1408,42 @@ test.describe( 'Block bindings', () => { } ); await expect( contentAttribute ).toBeVisible(); } ); + test( 'should use a selector to update the content', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/paragraph', + attributes: { + content: 'fallback value', + metadata: { + bindings: { + content: { + source: 'core/post-meta', + args: { key: 'undefined_field' }, + }, + }, + }, + }, + } ); + await page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByRole( 'button', { name: 'content' } ) + .click(); + + await page + .getByRole( 'menuitemradio' ) + .filter( { hasText: 'text_custom_field' } ) + .click(); + const paragraphBlock = editor.canvas.getByRole( 'document', { + name: 'Block: Paragraph', + } ); + await expect( paragraphBlock ).toHaveText( + 'Value of the text_custom_field' + ); + } ); } ); test.describe( 'Heading', () => { @@ -1494,7 +1530,7 @@ test.describe( 'Block bindings', () => { page, } ) => { await editor.insertBlock( { - name: 'core/paragraph', + name: 'core/heading', } ); await page .getByRole( 'tabpanel', { @@ -1507,37 +1543,6 @@ test.describe( 'Block bindings', () => { } ); await expect( contentAttribute ).toBeVisible(); } ); - test( 'should use a selector to update the content', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - } ); - await page - .getByRole( 'tabpanel', { - name: 'Settings', - } ) - .getByLabel( 'Attributes options' ) - .click(); - await page - .getByRole( 'menuitemcheckbox', { - name: 'Show content', - } ) - .click(); - await page.getByRole( 'button', { name: 'content' } ).click(); - await page.keyboard.press( 'Enter' ); - await page - .getByRole( 'menuitemradio' ) - .filter( { hasText: 'Value of the text_custom_field' } ) - .click(); - const paragraphBlock = editor.canvas.getByRole( 'document', { - name: 'Block: Paragraph', - } ); - await expect( paragraphBlock ).toHaveText( - 'Value of the text_custom_field' - ); - } ); } ); test.describe( 'Button', () => { @@ -1724,19 +1729,6 @@ test.describe( 'Block bindings', () => { innerBlocks: [ { name: 'core/button', - attributes: { - anchor: 'button-text-binding', - text: 'button default text', - url: '#default-url', - metadata: { - bindings: { - text: { - source: 'core/post-meta', - args: { key: 'text_custom_field' }, - }, - }, - }, - }, }, ], } ); @@ -1758,7 +1750,7 @@ test.describe( 'Block bindings', () => { } ); await expect( urlAttribute ).toBeVisible(); const textAttribute = page.getByRole( 'menuitemcheckbox', { - name: 'Hide and reset text', + name: 'Show text', } ); await expect( textAttribute ).toBeVisible(); const linkTargetAttribute = page.getByRole( @@ -2064,12 +2056,6 @@ test.describe( 'Block bindings', () => { } ) => { await editor.insertBlock( { name: 'core/image', - attributes: { - anchor: 'image-multiple-bindings', - url: imagePlaceholderSrc, - alt: 'default alt value', - title: 'default title value', - }, } ); await page .getByRole( 'tabpanel', { @@ -2356,10 +2342,12 @@ test.describe( 'Block bindings', () => { }, } ); - const bindingLabel = page.locator( - '.block-editor-bindings__item-explanation .components-truncate' - ); - await expect( bindingLabel ).toHaveText( 'Server Source' ); + const bindingLabel = page + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByRole( 'button', { name: 'Server Source' } ); + await expect( bindingLabel ).toBeVisible(); } ); } ); } ); From a9b347f8a6884142068ec740f9368a29d126d4d5 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 12:36:12 +0200 Subject: [PATCH 73/81] Remove `numberOfLines` prop --- packages/block-editor/src/hooks/block-bindings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index e8d98f267016cd..e23a18963761eb 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -80,10 +80,10 @@ function BlockBindingsPanelDropdown( { value={ key } checked={ key === currentKey } > - + { key } - + { value } From 839b37ae54de38098c3a1589735dd85e73116853 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 13:12:00 +0200 Subject: [PATCH 74/81] Remove unused class --- packages/block-editor/src/hooks/block-bindings.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index e23a18963761eb..d0a7a29b36392d 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -317,8 +317,7 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { /> ) } - { /* TODO: Add a helper to ToolPanel item */ } - + { __( 'Attributes connected to various sources.' ) } From 01fcf7d0fadac0959d97491172cfc33300d1d0d0 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 14:32:30 +0200 Subject: [PATCH 75/81] Fix mobile popover --- packages/block-editor/src/hooks/block-bindings.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index d0a7a29b36392d..4cab09244f9862 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -140,6 +140,7 @@ function EditableBlockBindingsPanelItems( { addConnection, removeConnection, } ) { + const isMobile = useViewportMatch( 'medium', '<' ); return ( <> { attributes.map( ( attribute ) => { @@ -154,8 +155,10 @@ function EditableBlockBindingsPanelItems( { } } > From d14d50feb969794728c7bc6244c3af33e18b3a06 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 25 Jul 2024 14:54:48 +0200 Subject: [PATCH 76/81] Move Separator outside of `DropdownMenuGroup` --- .../block-editor/src/hooks/block-bindings.js | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 4cab09244f9862..d92457b68dd79e 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -14,7 +14,7 @@ import { privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; -import { useContext } from '@wordpress/element'; +import { useContext, Fragment } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; /** @@ -61,37 +61,41 @@ function BlockBindingsPanelDropdown( { return ( <> { Object.entries( fieldsList ).map( ( [ label, fields ], i ) => ( - - { Object.keys( fieldsList ).length > 1 && ( - - { label } - - ) } - { Object.entries( fields ).map( ( [ key, value ] ) => ( - addConnection( key, attribute ) } - name={ attribute + '-binding' } - value={ key } - checked={ key === currentKey } - > - - { key } - - - { value } - - - ) ) } + + + { Object.keys( fieldsList ).length > 1 && ( + + { label } + + ) } + { Object.entries( fields ).map( ( [ key, value ] ) => ( + + addConnection( key, attribute ) + } + name={ attribute + '-binding' } + value={ key } + checked={ key === currentKey } + > + + { key } + + + { value } + + + ) ) } + { i !== Object.keys( fieldsList ).length - 1 && ( ) } - + ) ) } ); From 2dff252c23fb4f6b204d7d950523d69e3be7d0b0 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 29 Jul 2024 08:17:26 +0200 Subject: [PATCH 77/81] Remove empty sources from `fieldsList` --- packages/block-editor/src/hooks/block-bindings.js | 6 ++++++ packages/editor/src/bindings/post-meta.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index d92457b68dd79e..2f2a36be9f50db 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -291,6 +291,12 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } } ); + // Remove empty sources. + Object.entries( fieldsList ).forEach( ( [ key, value ] ) => { + if ( ! Object.keys( value ).length ) { + delete fieldsList[ key ]; + } + } ); // At this moment, the UI can be locked when there are no fields to connect to. const readOnly = ! Object.keys( fieldsList ).length; diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 9fb1bf63de08b3..298ec4d8ba1535 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -84,7 +84,7 @@ export default { context?.postId ).meta; - if ( ! metaFields ) { + if ( ! metaFields || ! Object.keys( metaFields ).length ) { return null; } From 50f6f1ef174fb15ba7aaf288e620faf1cf664718 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 30 Jul 2024 08:19:54 +0200 Subject: [PATCH 78/81] Move UI under experimental flag --- lib/experimental/editor-settings.php | 3 +++ lib/experiments-page.php | 12 ++++++++++++ packages/block-editor/src/hooks/block-bindings.js | 6 ++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 09ac4b6990d919..065264fd124e8c 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -34,6 +34,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-bindings-ui', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalBlockBindingsUI = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 7cc4198c14ef91..acb095b47fde30 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -163,6 +163,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-block-bindings-ui', + __( 'UI to create block bindings', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Add UI to create and update block bindings in block inspector controls.', 'gutenberg' ), + 'id' => 'gutenberg-block-bindings-ui', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 2f2a36be9f50db..ce3fdd2f327c40 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -298,8 +298,10 @@ export const BlockBindingsPanel = ( { name, metadata } ) => { } } ); - // At this moment, the UI can be locked when there are no fields to connect to. - const readOnly = ! Object.keys( fieldsList ).length; + // Lock the UI when the experiment is not enabled or there are no fields to connect to. + const readOnly = + ! window.__experimentalBlockBindingsUI || + ! Object.keys( fieldsList ).length; if ( readOnly && Object.keys( filteredBindings ).length === 0 ) { return null; From 3bf117ce229ebae03e94ffe727c38e89bdfa9a03 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 30 Jul 2024 10:54:33 +0200 Subject: [PATCH 79/81] Adapt e2e changes to experimental flag --- .../editor/various/block-bindings.spec.js | 25 +++++++++++++++++++ .../editor/various/change-detection.spec.js | 1 - .../editor/various/content-only-lock.spec.js | 1 - .../specs/editor/various/editor-modes.spec.js | 11 +++----- .../various/font-appearance-control.spec.js | 4 --- .../editor/various/font-size-picker.spec.js | 8 ------ 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 519a718684fc96..bc2ed78cffd31c 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -1394,6 +1394,11 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + await editor.insertBlock( { name: 'core/paragraph', } ); @@ -1412,6 +1417,11 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + await editor.insertBlock( { name: 'core/paragraph', attributes: { @@ -1529,6 +1539,11 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + await editor.insertBlock( { name: 'core/heading', } ); @@ -1724,6 +1739,11 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + await editor.insertBlock( { name: 'core/buttons', innerBlocks: [ @@ -2054,6 +2074,11 @@ test.describe( 'Block bindings', () => { editor, page, } ) => { + // Activate the block bindings UI experiment. + await page.evaluate( () => { + window.__experimentalBlockBindingsUI = true; + } ); + await editor.insertBlock( { name: 'core/image', } ); diff --git a/test/e2e/specs/editor/various/change-detection.spec.js b/test/e2e/specs/editor/various/change-detection.spec.js index e87d81ca7e3d0a..4ac262f4c1348d 100644 --- a/test/e2e/specs/editor/various/change-detection.spec.js +++ b/test/e2e/specs/editor/various/change-detection.spec.js @@ -451,7 +451,6 @@ test.describe( 'Change detection', () => { ] ); // Change the paragraph's `drop cap`. - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'region', { name: 'Editor settings' } ) .getByRole( 'button', { name: 'Typography options' } ) diff --git a/test/e2e/specs/editor/various/content-only-lock.spec.js b/test/e2e/specs/editor/various/content-only-lock.spec.js index a9fef883615b06..9784aea1ee068f 100644 --- a/test/e2e/specs/editor/various/content-only-lock.spec.js +++ b/test/e2e/specs/editor/various/content-only-lock.spec.js @@ -113,7 +113,6 @@ test.describe( 'Content-only lock', () => { .locator( 'role=document[name="Block: Paragraph"i]' ) .first() .click(); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await expect( page.locator( '.color-block-support-panel' ) ).toBeAttached(); diff --git a/test/e2e/specs/editor/various/editor-modes.spec.js b/test/e2e/specs/editor/various/editor-modes.spec.js index 3ef05c721dc80b..95c409f0589e31 100644 --- a/test/e2e/specs/editor/various/editor-modes.spec.js +++ b/test/e2e/specs/editor/various/editor-modes.spec.js @@ -39,7 +39,6 @@ test.describe( 'Editing modes (visual/HTML)', () => { await editor.clickBlockOptionsMenuItem( 'Edit as HTML' ); await editor.openDocumentSettingsSidebar(); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); // The `drop cap` toggle for the paragraph block should appear, even in // HTML editing mode. await page @@ -70,7 +69,6 @@ test.describe( 'Editing modes (visual/HTML)', () => { // Make sure the paragraph content is rendered as expected. await expect( paragraphHTML ).toHaveValue( '

Hello world!

' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); // Change the `drop cap` using the sidebar. await page .getByRole( 'button', { name: 'Typography options' } ) @@ -95,11 +93,10 @@ test.describe( 'Editing modes (visual/HTML)', () => { const editorSettings = page.getByRole( 'region', { name: 'Editor settings', } ); - - const blockTab = editorSettings.getByRole( 'tab', { name: 'Block' } ); + const activeTab = editorSettings.getByRole( 'tab', { selected: true } ); // The Block inspector should be active. - await expect( blockTab ).toHaveAttribute( 'data-active-item' ); + await expect( activeTab ).toHaveText( 'Block' ); await expect( editorSettings.locator( '.block-editor-block-card__title' ) ).toHaveText( 'Paragraph' ); @@ -108,9 +105,9 @@ test.describe( 'Editing modes (visual/HTML)', () => { await pageUtils.pressKeys( 'secondary+M' ); // The Block inspector should not be active anymore. - await expect( blockTab ).not.toHaveAttribute( 'data-active-item' ); + await expect( activeTab ).not.toHaveText( 'Block' ); - await blockTab.click(); + await editorSettings.getByRole( 'tab', { name: 'Block' } ).click(); await expect( editorSettings.locator( '.block-editor-block-inspector__no-blocks' ) ).toHaveText( 'No block selected.' ); diff --git a/test/e2e/specs/editor/various/font-appearance-control.spec.js b/test/e2e/specs/editor/various/font-appearance-control.spec.js index df76019dab06f2..4b148b6dd8587c 100644 --- a/test/e2e/specs/editor/various/font-appearance-control.spec.js +++ b/test/e2e/specs/editor/various/font-appearance-control.spec.js @@ -21,7 +21,6 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); @@ -38,7 +37,6 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); @@ -55,7 +53,6 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); @@ -80,7 +77,6 @@ test.describe( 'Font Appearance Control dropdown menu', () => { }, }, } ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Typography options' } ) .click(); diff --git a/test/e2e/specs/editor/various/font-size-picker.spec.js b/test/e2e/specs/editor/various/font-size-picker.spec.js index 8616f1f6a66090..597b458d682e84 100644 --- a/test/e2e/specs/editor/various/font-size-picker.spec.js +++ b/test/e2e/specs/editor/various/font-size-picker.spec.js @@ -28,7 +28,6 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph to be made "small"' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=region[name="Editor settings"i] >> role=button[name="Set custom size"i]' ); @@ -52,7 +51,6 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph reset - custom size' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=region[name="Editor settings"i] >> role=button[name="Set custom size"i]' ); @@ -145,7 +143,6 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph to be made "large"' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=group[name="Font size"i] >> role=combobox[name="Font size"i]' ); @@ -170,7 +167,6 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using tools panel menu' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=group[name="Font size"i] >> role=combobox[name="Font size"i]' ); @@ -204,7 +200,6 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using input field' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=group[name="Font size"i] >> role=combobox[name="Font size"i]' ); @@ -240,7 +235,6 @@ test.describe( 'Font Size Picker', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Paragraph to be made "large"' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radiogroup[name="Font size"i] >> role=radio[name="Large"i]' ); @@ -262,7 +256,6 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using tools panel menu' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radiogroup[name="Font size"i] >> role=radio[name="Small"i]' ); @@ -294,7 +287,6 @@ test.describe( 'Font Size Picker', () => { await page.keyboard.type( 'Paragraph with font size reset using input field' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radiogroup[name="Font size"i] >> role=radio[name="Small"i]' ); From 6fb7d89aeb857b483c67e5351cb3deeb14dbb649 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 30 Jul 2024 10:58:51 +0200 Subject: [PATCH 80/81] Remove missing clicks in tests --- test/e2e/specs/editor/blocks/heading.spec.js | 4 ---- .../editor/various/keep-styles-on-block-transforms.spec.js | 3 --- 2 files changed, 7 deletions(-) diff --git a/test/e2e/specs/editor/blocks/heading.spec.js b/test/e2e/specs/editor/blocks/heading.spec.js index 0d1957a1048c7b..4670196c485f5f 100644 --- a/test/e2e/specs/editor/blocks/heading.spec.js +++ b/test/e2e/specs/editor/blocks/heading.spec.js @@ -176,8 +176,6 @@ test.describe( 'Heading', () => { await page.keyboard.type( '### Heading' ); await editor.openDocumentSettingsSidebar(); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); - const textColor = page .getByRole( 'region', { name: 'Editor settings', @@ -212,8 +210,6 @@ test.describe( 'Heading', () => { await page.keyboard.type( '## Heading' ); await editor.openDocumentSettingsSidebar(); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); - const textColor = page .getByRole( 'region', { name: 'Editor settings', diff --git a/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js b/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js index b24af6fca8f69d..57b958fdfc4b44 100644 --- a/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js +++ b/test/e2e/specs/editor/various/keep-styles-on-block-transforms.spec.js @@ -17,7 +17,6 @@ test.describe( 'Keep styles on block transforms', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( '## Heading' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=button[name="Color Text styles"i]' ); await page.click( 'role=option[name="Color: Luminous vivid orange"i]' ); @@ -51,7 +50,6 @@ test.describe( 'Keep styles on block transforms', () => { await page.keyboard.type( 'Line 3 to be made large' ); await pageUtils.pressKeys( 'shift+ArrowUp' ); await pageUtils.pressKeys( 'shift+ArrowUp' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radio[name="Large"i]' ); await page.click( 'role=button[name="Multiple blocks selected"i]' ); await page.click( 'role=menuitem[name="Heading"i]' ); @@ -81,7 +79,6 @@ test.describe( 'Keep styles on block transforms', () => { .locator( 'role=button[name="Add default block"i]' ) .click(); await page.keyboard.type( 'Line 1 to be made large' ); - await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page.click( 'role=radio[name="Large"i]' ); await editor.showBlockToolbar(); await page.click( 'role=button[name="Paragraph"i]' ); From d091c343ea2841bc1e1b24659203a49628ea96eb Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 30 Jul 2024 11:42:09 +0200 Subject: [PATCH 81/81] Adapt another test --- test/e2e/specs/editor/various/block-bindings.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index bc2ed78cffd31c..d0e1f079ce8439 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -2367,12 +2367,12 @@ test.describe( 'Block bindings', () => { }, } ); - const bindingLabel = page + const bindingsPanel = page .getByRole( 'tabpanel', { name: 'Settings', } ) - .getByRole( 'button', { name: 'Server Source' } ); - await expect( bindingLabel ).toBeVisible(); + .locator( '.block-editor-bindings__panel' ); + await expect( bindingsPanel ).toContainText( 'Server Source' ); } ); } ); } );