diff --git a/lib/blocks.php b/lib/blocks.php index aff9e254edf1c6..1ba9e37e1b84be 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -26,6 +26,7 @@ function gutenberg_reregister_core_block_types() { 'group', 'heading', 'html', + 'home-link', 'image', 'list', 'media-text', @@ -59,6 +60,7 @@ function gutenberg_reregister_core_block_types() { 'loginout.php' => 'core/loginout', 'navigation.php' => 'core/navigation', 'navigation-link.php' => 'core/navigation-link', + 'home-link.php' => 'core/home-link', 'rss.php' => 'core/rss', 'search.php' => 'core/search', 'shortcode.php' => 'core/shortcode', diff --git a/packages/block-library/src/home-link/block.json b/packages/block-library/src/home-link/block.json new file mode 100644 index 00000000000000..42cea69c7aaf7f --- /dev/null +++ b/packages/block-library/src/home-link/block.json @@ -0,0 +1,29 @@ +{ + "apiVersion": 2, + "name": "core/home-link", + "category": "design", + "parent": [ "core/navigation" ], + "title": "Home Link", + "description": "Create a link that always points to the homepage of the site. Usually not necessary if there is already a site title link present in the header.", + "textdomain": "default", + "attributes": { + "label": { + "type": "string" + } + }, + "usesContext": [ + "textColor", + "customTextColor", + "backgroundColor", + "customBackgroundColor", + "fontSize", + "customFontSize", + "style" + ], + "supports": { + "reusable": false, + "html": false + }, + "editorStyle": "wp-block-home-link-editor", + "style": "wp-block-home-link" +} diff --git a/packages/block-library/src/home-link/edit.js b/packages/block-library/src/home-link/edit.js new file mode 100644 index 00000000000000..85571c518c8621 --- /dev/null +++ b/packages/block-library/src/home-link/edit.js @@ -0,0 +1,86 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { RichText, useBlockProps } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { useEffect } from '@wordpress/element'; + +const preventDefault = ( event ) => event.preventDefault(); + +export default function HomeEdit( { + attributes, + setAttributes, + context, + clientId, +} ) { + const { homeUrl } = useSelect( + ( select ) => { + const { + getUnstableBase, //site index + } = select( coreStore ); + return { + homeUrl: getUnstableBase()?.home, + }; + }, + [ clientId ] + ); + + const { textColor, backgroundColor, style } = context; + const blockProps = useBlockProps( { + className: classnames( { + 'has-text-color': !! textColor || !! style?.color?.text, + [ `has-${ textColor }-color` ]: !! textColor, + 'has-background': !! backgroundColor || !! style?.color?.background, + [ `has-${ backgroundColor }-background-color` ]: !! backgroundColor, + } ), + style: { + color: style?.color?.text, + backgroundColor: style?.color?.background, + }, + } ); + + const { label } = attributes; + + useEffect( () => { + if ( label === undefined ) { + setAttributes( { label: __( 'Home' ) } ); + } + }, [ clientId, label ] ); + + return ( + <> +
  • + + { + setAttributes( { label: labelValue } ); + } } + aria-label={ __( 'Home link text' ) } + placeholder={ __( 'Add home link' ) } + withoutInteractiveFormatting + allowedFormats={ [ + 'core/bold', + 'core/italic', + 'core/image', + 'core/strikethrough', + ] } + /> + +
  • + + ); +} diff --git a/packages/block-library/src/home-link/index.js b/packages/block-library/src/home-link/index.js new file mode 100644 index 00000000000000..5bb3914bb1bf33 --- /dev/null +++ b/packages/block-library/src/home-link/index.js @@ -0,0 +1,30 @@ +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; +import { home } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import metadata from './block.json'; +import edit from './edit'; +import save from './save'; + +const { name } = metadata; + +export { metadata, name }; + +export const settings = { + icon: home, + + edit, + + save, + + example: { + attributes: { + label: _x( 'Home Link', 'block example' ), + }, + }, +}; diff --git a/packages/block-library/src/home-link/index.php b/packages/block-library/src/home-link/index.php new file mode 100644 index 00000000000000..eafd27461c0972 --- /dev/null +++ b/packages/block-library/src/home-link/index.php @@ -0,0 +1,178 @@ + array(), + 'inline_styles' => '', + ); + + // Text color. + $has_named_text_color = array_key_exists( 'textColor', $context ); + $has_custom_text_color = isset( $context['style']['color']['text'] ); + + // If has text color. + if ( $has_custom_text_color || $has_named_text_color ) { + // Add has-text-color class. + $colors['css_classes'][] = 'has-text-color'; + } + + if ( $has_named_text_color ) { + // Add the color class. + $colors['css_classes'][] = sprintf( 'has-%s-color', $context['textColor'] ); + } elseif ( $has_custom_text_color ) { + // Add the custom color inline style. + $colors['inline_styles'] .= sprintf( 'color: %s;', $context['style']['color']['text'] ); + } + + // Background color. + $has_named_background_color = array_key_exists( 'backgroundColor', $context ); + $has_custom_background_color = isset( $context['style']['color']['background'] ); + + // If has background color. + if ( $has_custom_background_color || $has_named_background_color ) { + // Add has-background class. + $colors['css_classes'][] = 'has-background'; + } + + if ( $has_named_background_color ) { + // Add the background-color class. + $colors['css_classes'][] = sprintf( 'has-%s-background-color', $context['backgroundColor'] ); + } elseif ( $has_custom_background_color ) { + // Add the custom background-color inline style. + $colors['inline_styles'] .= sprintf( 'background-color: %s;', $context['style']['color']['background'] ); + } + + return $colors; +} + +/** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the home link markup in the front-end. + * + * @param array $context Home link block context. + * @return array Font size CSS classes and inline styles. + */ +function block_core_home_link_build_css_font_sizes( $context ) { + // CSS classes. + $font_sizes = array( + 'css_classes' => array(), + 'inline_styles' => '', + ); + + $has_named_font_size = array_key_exists( 'fontSize', $context ); + $has_custom_font_size = isset( $context['style']['typography']['fontSize'] ); + + if ( $has_named_font_size ) { + // Add the font size class. + $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] ); + } elseif ( $has_custom_font_size ) { + // Add the custom font size inline style. + $font_sizes['inline_styles'] = sprintf( 'font-size: %spx;', $context['style']['typography']['fontSize'] ); + } + + return $font_sizes; +} + +/** + * Builds an array with classes and style for the li wrapper + * + * @param array $context Home link block context. + * @return array The li wrapper attributes. + */ +function block_core_home_link_build_li_wrapper_attributes( $context ) { + $colors = block_core_home_link_build_css_colors( $context ); + $font_sizes = block_core_home_link_build_css_font_sizes( $context ); + $classes = array_merge( + $colors['css_classes'], + $font_sizes['css_classes'] + ); + $style_attribute = ( $colors['inline_styles'] . $font_sizes['inline_styles'] ); + $css_classes = trim( implode( ' ', $classes ) ); + + $wrapper_attributes = get_block_wrapper_attributes( + array( + 'class' => $css_classes, + 'style' => $style_attribute, + ) + ); + + return $wrapper_attributes; +} + +/** + * Renders the `core/home-link` block. + * + * @param array $attributes The block attributes. + * @param array $content The saved content. + * @param array $block The parsed block. + * + * @return string Returns the post content with the home url added. + */ +function render_block_core_home_link( $attributes, $content, $block ) { + if ( empty( $attributes['label'] ) ) { + return ''; + } + + $wrapper_attributes = block_core_home_link_build_li_wrapper_attributes( $block->context ); + + $html = '
  • array(), + 'em' => array(), + 'img' => array( + 'scale' => array(), + 'class' => array(), + 'style' => array(), + 'src' => array(), + 'alt' => array(), + ), + 's' => array(), + 'span' => array( + 'style' => array(), + ), + 'strong' => array(), + ) + ); + } + + $html .= '
  • '; + return $html; +} + +/** + * Register the home block + * + * @uses render_block_core_home_link() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ +function register_block_core_home_link() { + register_block_type_from_metadata( + __DIR__ . '/home-link', + array( + 'render_callback' => 'render_block_core_home_link', + ) + ); +} +add_action( 'init', 'register_block_core_home_link' ); diff --git a/packages/block-library/src/home-link/save.js b/packages/block-library/src/home-link/save.js new file mode 100644 index 00000000000000..17571d8f30d2de --- /dev/null +++ b/packages/block-library/src/home-link/save.js @@ -0,0 +1,8 @@ +/** + * WordPress dependencies + */ +import { InnerBlocks } from '@wordpress/block-editor'; + +export default function save() { + return ; +} diff --git a/packages/block-library/src/home-link/style.scss b/packages/block-library/src/home-link/style.scss new file mode 100644 index 00000000000000..76f91efc581122 --- /dev/null +++ b/packages/block-library/src/home-link/style.scss @@ -0,0 +1,52 @@ +.wp-block-navigation { + + .wp-block-home-link__content { + // Inherit colors set by the block color definition. + color: inherit; + display: block; + padding: 0.5em 1em; + } + + // Force links to inherit text decoration applied to navigation block. + // The extra selector adds specificity to ensure it works when user-set. + &[style*="text-decoration"] { + .wp-block-home-link { + text-decoration: inherit; + } + + .wp-block-home-link__content { + text-decoration: inherit; + + &:focus, + &:active { + text-decoration: inherit; + } + } + } + + &:not([style*="text-decoration"]) { + .wp-block-home-link__content { + text-decoration: none; + + &:focus, + &:active { + text-decoration: none; + } + } + } +} + +// Default background and font color. +.wp-block-navigation:not(.has-background) { + .wp-block-navigation__container .wp-block-home-link__container { + // Set a background color for submenus so that they're not transparent. + background-color: #fff; + color: #000; + border: 1px solid rgba(0, 0, 0, 0.15); + + .wp-block-home-link__container { + top: -1px; + } + } +} + diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 26e22c76af314f..a4ec8243c4e74c 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -35,6 +35,7 @@ import * as html from './html'; import * as mediaText from './media-text'; import * as navigation from './navigation'; import * as navigationLink from './navigation-link'; +import * as homeLink from './home-link'; import * as latestComments from './latest-comments'; import * as latestPosts from './latest-posts'; import * as legacyWidget from './legacy-widget'; @@ -233,6 +234,7 @@ export const __experimentalRegisterExperimentalCoreBlocks = [ navigation, navigationLink, + homeLink, // Register Legacy Widget block. ...( enableLegacyWidgetBlock ? [ legacyWidget ] : [] ), diff --git a/packages/block-library/src/navigation/edit.js b/packages/block-library/src/navigation/edit.js index 18d9da732015c9..b086931cb8bece 100644 --- a/packages/block-library/src/navigation/edit.js +++ b/packages/block-library/src/navigation/edit.js @@ -35,6 +35,7 @@ const ALLOWED_BLOCKS = [ 'core/social-links', 'core/page-list', 'core/spacer', + 'core/home-link', ]; const LAYOUT = { diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 03098c0a6b1521..6cab6d6a71f25e 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -23,6 +23,7 @@ @import "./media-text/style.scss"; @import "./navigation/style.scss"; @import "./navigation-link/style.scss"; +@import "./home-link/style.scss"; @import "./page-list/style.scss"; @import "./paragraph/style.scss"; @import "./post-author/style.scss"; diff --git a/packages/e2e-tests/fixtures/blocks/core__home-link.html b/packages/e2e-tests/fixtures/blocks/core__home-link.html new file mode 100644 index 00000000000000..e1564a33298ae6 --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__home-link.html @@ -0,0 +1 @@ + diff --git a/packages/e2e-tests/fixtures/blocks/core__home-link.json b/packages/e2e-tests/fixtures/blocks/core__home-link.json new file mode 100644 index 00000000000000..1a2c5fc0c6c5d5 --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__home-link.json @@ -0,0 +1,12 @@ +[ + { + "clientId": "_clientId_0", + "name": "core/home-link", + "isValid": true, + "attributes": { + "label": "Home" + }, + "innerBlocks": [], + "originalContent": "" + } +] diff --git a/packages/e2e-tests/fixtures/blocks/core__home-link.parsed.json b/packages/e2e-tests/fixtures/blocks/core__home-link.parsed.json new file mode 100644 index 00000000000000..7dee324f4fd40e --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__home-link.parsed.json @@ -0,0 +1,11 @@ +[ + { + "blockName": "core/home-link", + "attrs": { + "label": "Home" + }, + "innerBlocks": [], + "innerHTML": "", + "innerContent": [] + } +] diff --git a/packages/e2e-tests/fixtures/blocks/core__home-link.serialized.html b/packages/e2e-tests/fixtures/blocks/core__home-link.serialized.html new file mode 100644 index 00000000000000..e1564a33298ae6 --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__home-link.serialized.html @@ -0,0 +1 @@ +