From 32543c0205016ce86b90c1a49d5f650fa77fec18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Tue, 28 Apr 2020 14:20:55 +0200 Subject: [PATCH] First stab at editable menu items in navigator Use Slot/Fill instead of hardcoded components Disable slots/fills in global editor block navigator Grab clientId from context instead of requiring a prop Improve readability of block-navigation/list.js Use context to determine whether or not given BlockNavigation may be customized with slots Restore default value for selectBlock in navigation-structure-panel.js Remove obsolete onChange passed to NavigationStructurePanel Use constant value for BlockNavigationContext Use memo() in BlockStyles Remove performance changes from BlockStyles Generalize BlockNavigationListItem and remove the BlockNavigationListItemFill for now Rename useBlockNavigationSlots to withBlockNavigationSlots Restore RichText in the navigator Sort out BlockNavigationListItem and BlockNavigationListItemWrapper Rename BlockNavigationListItemWrapper to BlockNavigationBranch --- .../components/block-navigation/list-item.js | 58 ++++++++++++ .../src/components/block-navigation/list.js | 91 +++++++++++++------ packages/block-editor/src/components/index.js | 7 +- .../block-library/src/navigation-link/edit.js | 57 ++++++++---- .../components/header/header-toolbar/index.js | 7 +- 5 files changed, 170 insertions(+), 50 deletions(-) create mode 100644 packages/block-editor/src/components/block-navigation/list-item.js diff --git a/packages/block-editor/src/components/block-navigation/list-item.js b/packages/block-editor/src/components/block-navigation/list-item.js new file mode 100644 index 0000000000000..c34f4dc3fe985 --- /dev/null +++ b/packages/block-editor/src/components/block-navigation/list-item.js @@ -0,0 +1,58 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Button, VisuallyHidden } from '@wordpress/components'; +import { + __experimentalGetBlockLabel as getBlockLabel, + getBlockType, +} from '@wordpress/blocks'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import BlockIcon from '../block-icon'; + +export default function BlockNavigationListItem( { + block, + onClick, + isSelected, + wrapperComponent: WrapperComponent, + children, +} ) { + const blockType = getBlockType( block.name ); + + return ( +
+ + + { children + ? children + : getBlockLabel( blockType, block.attributes ) } + { isSelected && ( + + { __( '(selected block)' ) } + + ) } + +
+ ); +} + +BlockNavigationListItem.defaultProps = { + onClick: () => {}, + wrapperComponent: ( props ) => - + selectBlock( block.clientId ) } + > { showNestedBlocks && !! block.innerBlocks && !! block.innerBlocks.length && ( @@ -78,7 +69,7 @@ export default function BlockNavigationList( { showNestedBlocks /> ) } - + ); } ) } { shouldShowAppender && ( @@ -95,3 +86,43 @@ export default function BlockNavigationList( { /* eslint-enable jsx-a11y/no-redundant-roles */ ); } + +BlockNavigationList.defaultProps = { + selectBlock: () => {}, +}; + +const BlockNavigationBranch = ( { withSlot, children, ...props } ) => { + if ( ! withSlot ) { + return ; + } + + return ( +
  • + + { ( fills ) => { + if ( ! fills.length ) { + return ; + } + + return Children.map( fills, ( fill ) => + cloneElement( fill, { + ...props, + ...fill.props, + } ) + ); + } } + + { children } +
  • + ); +}; + +const listItemSlotName = ( blockId ) => `BlockNavigationList-item-${ blockId }`; + +export const BlockNavigationListItemSlot = ( { blockId, ...props } ) => ( + +); +export const BlockNavigationListItemFill = ( props ) => { + const { clientId } = useContext( BlockListBlockContext ); + return ; +}; diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 2e9230b150f70..8154f8ba29148 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -16,7 +16,12 @@ export { default as BlockEdit, useBlockEditContext } from './block-edit'; export { default as BlockFormatControls } from './block-format-controls'; export { default as BlockIcon } from './block-icon'; export { default as BlockNavigationDropdown } from './block-navigation/dropdown'; -export { default as __experimentalBlockNavigationList } from './block-navigation/list'; +export { + default as __experimentalBlockNavigationList, + BlockNavigationContext as __experimentalBlockNavigationContext, + BlockNavigationListItemFill as __experimentalBlockNavigationListItemFill, +} from './block-navigation/list'; +export { default as __experimentalBlockNavigationListItem } from './block-navigation/list-item'; export { default as __experimentalBlockVariationPicker } from './block-variation-picker'; export { default as BlockVerticalAlignmentToolbar } from './block-vertical-alignment-toolbar'; export { default as ButtonBlockerAppender } from './button-block-appender'; diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index 60ebdb45a68c7..d9cc963e82d9e 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -29,9 +29,17 @@ import { RichText, __experimentalLinkControl as LinkControl, __experimentalBlock as Block, + __experimentalBlockNavigationListItemFill as BlockNavigationListItemFill, + __experimentalBlockNavigationListItem as BlockNavigationListItem, } from '@wordpress/block-editor'; import { isURL, prependHTTP } from '@wordpress/url'; -import { Fragment, useState, useEffect, useRef } from '@wordpress/element'; +import { + Fragment, + useState, + useEffect, + useRef, + cloneElement, +} from '@wordpress/element'; import { placeCaretAtHorizontalEdge } from '@wordpress/dom'; import { link as linkIcon } from '@wordpress/icons'; @@ -40,6 +48,8 @@ import { link as linkIcon } from '@wordpress/icons'; */ import { ToolbarSubmenuIcon, ItemSubmenuIcon } from './icons'; +const noop = () => {}; + function NavigationLinkEdit( { attributes, hasDescendants, @@ -129,6 +139,25 @@ function NavigationLinkEdit( { }; } + const editField = ( + + setAttributes( { label: labelValue } ) + } + placeholder={ itemLabelPlaceholder } + keepPlaceholderOnFocus + withoutInteractiveFormatting + allowedFormats={ [ + 'core/bold', + 'core/italic', + 'core/image', + 'core/strikethrough', + ] } + /> + ); + return ( @@ -193,6 +222,14 @@ function NavigationLinkEdit( { /> + + + { editField } + +
    - - setAttributes( { label: labelValue } ) - } - placeholder={ itemLabelPlaceholder } - keepPlaceholderOnFocus - withoutInteractiveFormatting - allowedFormats={ [ - 'core/bold', - 'core/italic', - 'core/image', - 'core/strikethrough', - ] } - /> + { cloneElement( editField, { ref } ) } { isLinkOpen && ( - + + + { displayBlockToolbar && (