diff --git a/packages/editor/src/hooks/index.js b/packages/editor/src/hooks/index.js index 6001d53f65c103..e79a9207e48f58 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 './navigation-link-view-button'; diff --git a/packages/editor/src/hooks/navigation-link-view-button.js b/packages/editor/src/hooks/navigation-link-view-button.js new file mode 100644 index 00000000000000..d1bf2f4e81726b --- /dev/null +++ b/packages/editor/src/hooks/navigation-link-view-button.js @@ -0,0 +1,100 @@ +/** + * WordPress dependencies + */ +import { addFilter } from '@wordpress/hooks'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { useCallback } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { + __unstableBlockToolbarLastItem as BlockToolbarLastItem, + store as blockEditorStore, + useBlockEditingMode, +} from '@wordpress/block-editor'; +import { ToolbarButton, ToolbarGroup } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; + +// Target blocks that should have the View button. +const SUPPORTED_BLOCKS = [ 'core/navigation-link', 'core/navigation-submenu' ]; + +/** + * Component that renders the View button for navigation blocks. + * + * @param {Object} props Component props. + * @param {Object} props.attributes Block attributes. + * @return {JSX.Element|null} The View button component or null if not applicable. + */ +function NavigationViewButton( { attributes } ) { + const { kind, id, type } = attributes; + const blockEditingMode = useBlockEditingMode(); + + const onNavigateToEntityRecord = useSelect( + ( select ) => + select( blockEditorStore ).getSettings().onNavigateToEntityRecord, + [] + ); + + const onViewPage = useCallback( () => { + if ( + kind === 'post-type' && + type === 'page' && + id && + onNavigateToEntityRecord + ) { + onNavigateToEntityRecord( { + postId: id, + postType: type, + } ); + } + }, [ kind, id, type, onNavigateToEntityRecord ] ); + + // Only show for page-type links, when navigation is available, and when in contentOnly mode. + if ( + kind !== 'post-type' || + type !== 'page' || + ! id || + ! onNavigateToEntityRecord || + blockEditingMode !== 'contentOnly' + ) { + return null; + } + + return ( + + + + { __( 'View' ) } + + + + ); +} + +/** + * Higher-order component that adds the View button to navigation blocks. + */ +const withNavigationViewButton = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const isSupportedBlock = SUPPORTED_BLOCKS.includes( props.name ); + + return ( + <> + + { props.isSelected && isSupportedBlock && ( + + ) } + + ); + }, + 'withNavigationViewButton' +); + +// Register the filter. +addFilter( + 'editor.BlockEdit', + 'core/editor/with-navigation-view-button', + withNavigationViewButton +);