From 8b5de5df4b1dd2bcbb2aa3d193ba61298ebb2b5a Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 5 Feb 2018 15:57:37 -0800 Subject: [PATCH 01/19] Start work --- blocks/library/index.js | 2 + blocks/library/navigation-menu/block.js | 114 +++++++++++++++++++++ blocks/library/navigation-menu/editor.scss | 0 blocks/library/navigation-menu/index.js | 42 ++++++++ blocks/library/navigation-menu/style.scss | 0 5 files changed, 158 insertions(+) create mode 100644 blocks/library/navigation-menu/block.js create mode 100644 blocks/library/navigation-menu/editor.scss create mode 100644 blocks/library/navigation-menu/index.js create mode 100644 blocks/library/navigation-menu/style.scss diff --git a/blocks/library/index.js b/blocks/library/index.js index 26920e6d3d9ec..3747a87d75ade 100644 --- a/blocks/library/index.js +++ b/blocks/library/index.js @@ -23,6 +23,7 @@ import * as html from './html'; import * as latestPosts from './latest-posts'; import * as list from './list'; import * as more from './more'; +import * as navigationMenu from './navigation-menu'; import * as preformatted from './preformatted'; import * as pullquote from './pullquote'; import * as reusableBlock from './block'; @@ -79,6 +80,7 @@ export const registerCoreBlocks = () => { html, latestPosts, more, + navigationMenu, preformatted, pullquote, reusableBlock, diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js new file mode 100644 index 0000000000000..a0a7aa115d4ea --- /dev/null +++ b/blocks/library/navigation-menu/block.js @@ -0,0 +1,114 @@ +/** + * External dependencies + */ +import { isUndefined, pickBy } from 'lodash'; +import moment from 'moment'; +import classnames from 'classnames'; +import { stringify } from 'querystringify'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { decodeEntities } from '@wordpress/utils'; + +/** + * Internal dependencies + */ +import './editor.scss'; +import './style.scss'; +import QueryPanel from '../../query-panel'; +import InspectorControls from '../../inspector-controls'; +import ToggleControl from '../../inspector-controls/toggle-control'; +import RangeControl from '../../inspector-controls/range-control'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; + +const MAX_POSTS_COLUMNS = 6; + +class NavigationMenuBlock extends Component { + constructor() { + super( ...arguments ); + + this.toggleDisplayPostDate = this.toggleDisplayPostDate.bind( this ); + } + + toggleDisplayPostDate() { + const { displayPostDate } = this.props.attributes; + const { setAttributes } = this.props; + + setAttributes( { displayPostDate: ! displayPostDate } ); + } + + render() { + const { attributes, focus, setAttributes } = this.props; + const { align, layout } = attributes; + const menus = this.props.menus.data; + + const inspectorControls = focus && ( + +

{ __( 'Menu Settings' ) }

+
+ ); + + const hasPosts = Array.isArray( menus ) && menus.length; + if ( ! hasPosts ) { + return [ + inspectorControls, + + { ! Array.isArray( menus ) ? + : + __( 'No posts found.' ) + } + , + ]; + } + + const layoutControls = [ + { + icon: 'list-view', + title: __( 'Vertical View' ), + onClick: () => setAttributes( { layout: 'vertical' } ), + isActive: layout === 'vertical', + }, + { + icon: 'grid-view', + title: __( 'Horizontal View' ), + onClick: () => setAttributes( { layout: 'horizontal' } ), + isActive: layout === 'horizontal', + }, + ]; + + return [ + inspectorControls, + focus && ( + + { + setAttributes( { align: nextAlign } ); + } } + controls={ [ 'center', 'wide', 'full' ] } + /> + + + ), + + Test child + , + ]; + } +} + +export default withAPIData( () => ( { + menus: '/wp/v2/menus', +} ) )( NavigationMenuBlock ); diff --git a/blocks/library/navigation-menu/editor.scss b/blocks/library/navigation-menu/editor.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/blocks/library/navigation-menu/index.js b/blocks/library/navigation-menu/index.js new file mode 100644 index 0000000000000..447f4f26be100 --- /dev/null +++ b/blocks/library/navigation-menu/index.js @@ -0,0 +1,42 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import './editor.scss'; +import './style.scss'; +import NavMenuBlock from './block'; + +export const name = 'core/navigation-menu'; + +export const settings = { + title: __( 'Navigation Menu' ), + + description: __( 'Display your site pages.' ), + + icon: 'menu', + + category: 'widgets', + + keywords: [ __( 'navigation menu' ) ], + + supports: { + html: false, + }, + + getEditWrapperProps( attributes ) { + const { align } = attributes; + if ( 'left' === align || 'right' === align || 'wide' === align || 'full' === align ) { + return { 'data-align': align }; + } + }, + + edit: NavMenuBlock, + + save() { + return null; + }, +}; diff --git a/blocks/library/navigation-menu/style.scss b/blocks/library/navigation-menu/style.scss new file mode 100644 index 0000000000000..e69de29bb2d1d From 1b737f2d25e84bab6fe253599501124862cbab7c Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 5 Feb 2018 23:03:13 -0800 Subject: [PATCH 02/19] =?UTF-8?q?Add=20a=20=E2=80=9Cplaceholder=E2=80=9D?= =?UTF-8?q?=20component=20to=20hold=20the=20menu=20selection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blocks/library/navigation-menu/block.js | 55 +++++++------------ blocks/library/navigation-menu/placeholder.js | 51 +++++++++++++++++ 2 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 blocks/library/navigation-menu/placeholder.js diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index a0a7aa115d4ea..df31f2bb3ef7f 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -10,7 +10,7 @@ import { stringify } from 'querystringify'; * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; +import { Toolbar, withAPIData } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/utils'; @@ -19,32 +19,26 @@ import { decodeEntities } from '@wordpress/utils'; */ import './editor.scss'; import './style.scss'; -import QueryPanel from '../../query-panel'; import InspectorControls from '../../inspector-controls'; -import ToggleControl from '../../inspector-controls/toggle-control'; -import RangeControl from '../../inspector-controls/range-control'; import BlockControls from '../../block-controls'; import BlockAlignmentToolbar from '../../block-alignment-toolbar'; - -const MAX_POSTS_COLUMNS = 6; +import MenuPlaceholder from './placeholder'; class NavigationMenuBlock extends Component { constructor() { super( ...arguments ); - this.toggleDisplayPostDate = this.toggleDisplayPostDate.bind( this ); + this.setMenu = this.setMenu.bind( this ); } - toggleDisplayPostDate() { - const { displayPostDate } = this.props.attributes; + setMenu( value ) { const { setAttributes } = this.props; - - setAttributes( { displayPostDate: ! displayPostDate } ); + setAttributes( { selected: value } ); } render() { const { attributes, focus, setAttributes } = this.props; - const { align, layout } = attributes; + const { align, layout, selected } = attributes; const menus = this.props.menus.data; const inspectorControls = focus && ( @@ -53,22 +47,6 @@ class NavigationMenuBlock extends Component { ); - const hasPosts = Array.isArray( menus ) && menus.length; - if ( ! hasPosts ) { - return [ - inspectorControls, - - { ! Array.isArray( menus ) ? - : - __( 'No posts found.' ) - } - , - ]; - } - const layoutControls = [ { icon: 'list-view', @@ -84,6 +62,19 @@ class NavigationMenuBlock extends Component { }, ]; + let displayBlock = ( + + ); + + if ( !! selected ) { + displayBlock = selected; + } + return [ inspectorControls, focus && ( @@ -98,13 +89,7 @@ class NavigationMenuBlock extends Component { ), - - Test child - , + displayBlock, ]; } } diff --git a/blocks/library/navigation-menu/placeholder.js b/blocks/library/navigation-menu/placeholder.js new file mode 100644 index 0000000000000..f9f429b05e7e7 --- /dev/null +++ b/blocks/library/navigation-menu/placeholder.js @@ -0,0 +1,51 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Component } from '@wordpress/element'; +import { Placeholder, Spinner } from '@wordpress/components'; +import SelectControl from '../../inspector-controls/select-control'; + +class MenuPlaceholder extends Component { + getOptionsFromMenu( menu ) { + return { + value: menu.id, + label: menu.name, + }; + } + + render() { + const { menus, selected, setMenu } = this.props; + const hasMenus = Array.isArray( menus ) && menus.length; + + if ( ! hasMenus ) { + return ( + + { ! Array.isArray( menus ) ? + : + __( 'No menus found.' ) + } + + ); + } + + return ( + + + + ); + } +} + +export default MenuPlaceholder; From a9910504f7e3a8986982850a4bd60f39206dfe30 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 5 Feb 2018 23:18:40 -0800 Subject: [PATCH 03/19] Display menu items when a menu is selected --- blocks/library/navigation-menu/block.js | 56 ++++++++++++++----- blocks/library/navigation-menu/placeholder.js | 2 +- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index df31f2bb3ef7f..c078f9ae70b29 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -1,16 +1,8 @@ -/** - * External dependencies - */ -import { isUndefined, pickBy } from 'lodash'; -import moment from 'moment'; -import classnames from 'classnames'; -import { stringify } from 'querystringify'; - /** * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { Toolbar, withAPIData } from '@wordpress/components'; +import { Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/utils'; @@ -29,6 +21,7 @@ class NavigationMenuBlock extends Component { super( ...arguments ); this.setMenu = this.setMenu.bind( this ); + this.renderMenu = this.renderMenu.bind( this ); } setMenu( value ) { @@ -36,6 +29,36 @@ class NavigationMenuBlock extends Component { setAttributes( { selected: value } ); } + renderMenu() { + const { data, isLoading } = this.props.items; + if ( ! data || isLoading ) { + return ( + + { ! Array.isArray( data ) ? + : + __( 'No items found in this menu.' ) + } + + ); + } + + return ( +
    + { data.map( ( item, i ) => { + return ( +
  • + { decodeEntities( item.title.trim() ) || __( '(Untitled)' ) } +
  • + ); + } ) } +
+ ); + } + render() { const { attributes, focus, setAttributes } = this.props; const { align, layout, selected } = attributes; @@ -72,7 +95,7 @@ class NavigationMenuBlock extends Component { ); if ( !! selected ) { - displayBlock = selected; + displayBlock = this.renderMenu(); } return [ @@ -94,6 +117,13 @@ class NavigationMenuBlock extends Component { } } -export default withAPIData( () => ( { - menus: '/wp/v2/menus', -} ) )( NavigationMenuBlock ); +export default withAPIData( props => { + const { selected } = props.attributes; + const queryString = selected ? `menus=${ selected }` : ''; + const itemsUrl = selected ? `/wp/v2/menu-items?${ queryString }` : false; + + return { + menus: '/wp/v2/menus', + items: itemsUrl, + }; +} )( NavigationMenuBlock ); diff --git a/blocks/library/navigation-menu/placeholder.js b/blocks/library/navigation-menu/placeholder.js index f9f429b05e7e7..d341aa680781b 100644 --- a/blocks/library/navigation-menu/placeholder.js +++ b/blocks/library/navigation-menu/placeholder.js @@ -21,7 +21,7 @@ class MenuPlaceholder extends Component { if ( ! hasMenus ) { return ( { ! Array.isArray( menus ) ? From adecbd7497e02d43c3a3e141842ea1d82603f944 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Tue, 6 Feb 2018 08:16:34 -0800 Subject: [PATCH 04/19] Extract select control back into parent component to reuse it in Inspector --- blocks/library/navigation-menu/block.js | 39 ++++++++++++++++--- blocks/library/navigation-menu/placeholder.js | 17 +------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index c078f9ae70b29..d1b502aa2e236 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -11,10 +11,26 @@ import { decodeEntities } from '@wordpress/utils'; */ import './editor.scss'; import './style.scss'; -import InspectorControls from '../../inspector-controls'; import BlockControls from '../../block-controls'; import BlockAlignmentToolbar from '../../block-alignment-toolbar'; +import InspectorControls from '../../inspector-controls'; import MenuPlaceholder from './placeholder'; +import SelectControl from '../../inspector-controls/select-control'; + +function getOptionsFromMenu( menus, selected ) { + if ( ! menus ) { + return []; + } + + const options = menus.map( item => ( { + value: item.id, + label: item.name, + } ) ); + if ( ! selected ) { + options.unshift( { value: '', label: __( 'Select' ) } ); + } + return options; +} class NavigationMenuBlock extends Component { constructor() { @@ -26,7 +42,9 @@ class NavigationMenuBlock extends Component { setMenu( value ) { const { setAttributes } = this.props; - setAttributes( { selected: value } ); + if ( value ) { + setAttributes( { selected: value } ); + } } renderMenu() { @@ -62,11 +80,21 @@ class NavigationMenuBlock extends Component { render() { const { attributes, focus, setAttributes } = this.props; const { align, layout, selected } = attributes; - const menus = this.props.menus.data; + const { data: menus, isLoading } = this.props.menus; + + const menuSelectControl = ( + + ); const inspectorControls = focus && (

{ __( 'Menu Settings' ) }

+ { ! isLoading && menuSelectControl }
); @@ -90,8 +118,9 @@ class NavigationMenuBlock extends Component { key="navigation-menu" menus={ menus } selected={ false } - setMenu={ this.setMenu } - /> + setMenu={ this.setMenu } > + { menuSelectControl } +
); if ( !! selected ) { diff --git a/blocks/library/navigation-menu/placeholder.js b/blocks/library/navigation-menu/placeholder.js index d341aa680781b..bcf7eca37fc1a 100644 --- a/blocks/library/navigation-menu/placeholder.js +++ b/blocks/library/navigation-menu/placeholder.js @@ -4,18 +4,10 @@ import { __ } from '@wordpress/i18n'; import { Component } from '@wordpress/element'; import { Placeholder, Spinner } from '@wordpress/components'; -import SelectControl from '../../inspector-controls/select-control'; class MenuPlaceholder extends Component { - getOptionsFromMenu( menu ) { - return { - value: menu.id, - label: menu.name, - }; - } - render() { - const { menus, selected, setMenu } = this.props; + const { children, menus } = this.props; const hasMenus = Array.isArray( menus ) && menus.length; if ( ! hasMenus ) { @@ -37,12 +29,7 @@ class MenuPlaceholder extends Component { key="block-placeholder" icon={ 'menu' } label={ __( 'Navigation Menu' ) } > - + { children } ); } From 2b409fe1804c30885a731f8a162e8038dc9be67b Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Tue, 6 Feb 2018 08:47:45 -0800 Subject: [PATCH 05/19] Add php registration to set the stage for dynamic rendering --- blocks/library/navigation-menu/index.php | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 blocks/library/navigation-menu/index.php diff --git a/blocks/library/navigation-menu/index.php b/blocks/library/navigation-menu/index.php new file mode 100644 index 0000000000000..a1b19cf8e8eee --- /dev/null +++ b/blocks/library/navigation-menu/index.php @@ -0,0 +1,46 @@ +%2$s', + esc_attr( $class ), + '' + ); + + return $block_content; +} + +register_block_type( 'core/navigation-menu', array( + 'attributes' => array( + 'selected' => array( + 'type' => 'string', + ), + 'layout' => array( + 'type' => 'string', + 'default' => 'vertical', + ), + 'align' => array( + 'type' => 'string', + 'default' => 'center', + ), + ), + 'render_callback' => 'gutenberg_render_block_core_navigation_menu', +) ); From 3186275118d8cdb2c39a89965e6d7adc23d4aad3 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Tue, 6 Feb 2018 08:47:54 -0800 Subject: [PATCH 06/19] Add styling for the list view --- blocks/library/navigation-menu/block.js | 13 ++++++++++++- blocks/library/navigation-menu/editor.scss | 6 ++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index d1b502aa2e236..13608bf473d31 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -48,6 +53,7 @@ class NavigationMenuBlock extends Component { } renderMenu() { + const { layout } = this.props.attributes; const { data, isLoading } = this.props.items; if ( ! data || isLoading ) { return ( @@ -65,7 +71,12 @@ class NavigationMenuBlock extends Component { } return ( -
    +
      { data.map( ( item, i ) => { return (
    • diff --git a/blocks/library/navigation-menu/editor.scss b/blocks/library/navigation-menu/editor.scss index e69de29bb2d1d..c5bba439026fa 100644 --- a/blocks/library/navigation-menu/editor.scss +++ b/blocks/library/navigation-menu/editor.scss @@ -0,0 +1,6 @@ +.gutenberg .wp-block-navigation-menu { + padding-left: 2.5em; + &.is-horizontal { + padding-left: 0; + } +} From 7f32e11b1f10abdd638e3c20679ca040246cf268 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Tue, 6 Feb 2018 10:48:21 -0800 Subject: [PATCH 07/19] Add a button-link to the customizer for empty menus --- blocks/library/navigation-menu/block.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index 13608bf473d31..838de7c50318d 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -2,12 +2,13 @@ * External dependencies */ import classnames from 'classnames'; +import { isEmpty, isUndefined } from 'lodash'; /** * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; +import { Button, Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/utils'; @@ -55,7 +56,9 @@ class NavigationMenuBlock extends Component { renderMenu() { const { layout } = this.props.attributes; const { data, isLoading } = this.props.items; - if ( ! data || isLoading ) { + const customizerUrl = ''; + + if ( isUndefined( data ) || isEmpty( data ) || isLoading ) { return ( { ! Array.isArray( data ) ? : - __( 'No items found in this menu.' ) + } ); From 0d267d1859087b735f2a44993d4ee2855d1c7bef Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Wed, 7 Feb 2018 18:14:47 -0800 Subject: [PATCH 08/19] Support horizontal nested menu --- blocks/library/navigation-menu/block.js | 69 +++++++++++++++++------ blocks/library/navigation-menu/item.js | 23 ++++++++ blocks/library/navigation-menu/style.scss | 50 ++++++++++++++++ 3 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 blocks/library/navigation-menu/item.js diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index 838de7c50318d..1bf7e5bdaa283 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import { isEmpty, isUndefined } from 'lodash'; +import { filter, forEach, isEmpty, isUndefined } from 'lodash'; /** * WordPress dependencies @@ -10,7 +10,6 @@ import { isEmpty, isUndefined } from 'lodash'; import { Component } from '@wordpress/element'; import { Button, Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { decodeEntities } from '@wordpress/utils'; /** * Internal dependencies @@ -20,6 +19,7 @@ import './style.scss'; import BlockControls from '../../block-controls'; import BlockAlignmentToolbar from '../../block-alignment-toolbar'; import InspectorControls from '../../inspector-controls'; +import MenuItem from './item'; import MenuPlaceholder from './placeholder'; import SelectControl from '../../inspector-controls/select-control'; @@ -38,12 +38,28 @@ function getOptionsFromMenu( menus, selected ) { return options; } +function getMenuChildren( list, data ) { + forEach( list, function( item, i ) { + list[ i ].children = filter( data, { menu_item_parent: item.id } ); + list[ i ].children = getMenuChildren( list[ i ].children, data ); + } ); + // return sortBy( list, 'menu_order' ); + return list; +} + +function getMenuWithChildren( data ) { + const sorted = filter( data, { menu_item_parent: 0 } ); + getMenuChildren( sorted, data ); + return sorted; +} + class NavigationMenuBlock extends Component { constructor() { super( ...arguments ); this.setMenu = this.setMenu.bind( this ); this.renderMenu = this.renderMenu.bind( this ); + this.renderMenuLevel = this.renderMenuLevel.bind( this ); } setMenu( value ) { @@ -53,6 +69,33 @@ class NavigationMenuBlock extends Component { } } + renderMenuLevel( items ) { + if ( ! items || items.length < 1 ) { + return null; + } + + const { layout } = this.props.attributes; + const isTopLevel = items[ 0 ].menu_item_parent === 0; + const className = classnames( this.props.className, { + 'is-horizontal': layout === 'horizontal', + } ); + + return ( +
        + { items.map( ( item, i ) => { + return ( + + { item.children && this.renderMenuLevel( item.children ) } + + ); + } ) } +
      + ); + } + renderMenu() { const { layout } = this.props.attributes; const { data, isLoading } = this.props.items; @@ -75,22 +118,12 @@ class NavigationMenuBlock extends Component { ); } - return ( -
        - { data.map( ( item, i ) => { - return ( -
      • - { decodeEntities( item.title.trim() ) || __( '(Untitled)' ) } -
      • - ); - } ) } -
      - ); + if ( 'horizontal' === layout ) { + const nestedData = getMenuWithChildren( data ); + return this.renderMenuLevel( nestedData ); + } + + return this.renderMenuLevel( data ); } render() { diff --git a/blocks/library/navigation-menu/item.js b/blocks/library/navigation-menu/item.js new file mode 100644 index 0000000000000..8c87888e4f310 --- /dev/null +++ b/blocks/library/navigation-menu/item.js @@ -0,0 +1,23 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Component } from '@wordpress/element'; +import { decodeEntities } from '@wordpress/utils'; + +class MenuItem extends Component { + render() { + const { children, item } = this.props; + + return ( +
    • + + { decodeEntities( item.title.trim() ) || __( '(Untitled)' ) } + + { children } +
    • + ); + } +} + +export default MenuItem; diff --git a/blocks/library/navigation-menu/style.scss b/blocks/library/navigation-menu/style.scss index e69de29bb2d1d..115c9c4680391 100644 --- a/blocks/library/navigation-menu/style.scss +++ b/blocks/library/navigation-menu/style.scss @@ -0,0 +1,50 @@ +.wp-block-navigation-menu { + &.is-horizontal { + display: flex; + flex-wrap: wrap; + padding: 0; + + ul { + float: left; + position: absolute; + top: 100%; + left: -999em; + z-index: 99999; + + ul { + left: -999em; + top: 0; + } + + li { + &:hover > ul, + &.focus > ul { + left: 100%; + } + } + + a { + width: 200px; + } + } + + li { + float: left; + position: relative; + margin: 0 16px 16px 0; + list-style: none; + width: auto; + + &:hover > ul, + &.focus > ul { + left: auto; + display: block; + } + } + + a { + display: block; + text-decoration: none; + } + } +} From 01ad1a36232038278bf120f49aed095635f75742 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 8 Feb 2018 17:15:07 -0800 Subject: [PATCH 09/19] Sort menus by the defined order --- blocks/library/navigation-menu/block.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index 1bf7e5bdaa283..fcb51d039dd2c 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import { filter, forEach, isEmpty, isUndefined } from 'lodash'; +import { filter, forEach, isEmpty, isUndefined, sortBy } from 'lodash'; /** * WordPress dependencies @@ -43,12 +43,11 @@ function getMenuChildren( list, data ) { list[ i ].children = filter( data, { menu_item_parent: item.id } ); list[ i ].children = getMenuChildren( list[ i ].children, data ); } ); - // return sortBy( list, 'menu_order' ); - return list; + return sortBy( list, 'menu_order' ); } function getMenuWithChildren( data ) { - const sorted = filter( data, { menu_item_parent: 0 } ); + const sorted = sortBy( filter( data, { menu_item_parent: 0 } ), 'menu_order' ); getMenuChildren( sorted, data ); return sorted; } From 38f28d838727abdf054aad3ee0b585e365f3eee4 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 8 Feb 2018 17:39:31 -0800 Subject: [PATCH 10/19] Both horizontal & vertical should support nesting --- blocks/library/navigation-menu/block.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index fcb51d039dd2c..fd0f63267c4f1 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -40,8 +40,8 @@ function getOptionsFromMenu( menus, selected ) { function getMenuChildren( list, data ) { forEach( list, function( item, i ) { - list[ i ].children = filter( data, { menu_item_parent: item.id } ); - list[ i ].children = getMenuChildren( list[ i ].children, data ); + const children = filter( data, { menu_item_parent: item.id } ); + list[ i ].children = getMenuChildren( children, data ); } ); return sortBy( list, 'menu_order' ); } @@ -75,14 +75,15 @@ class NavigationMenuBlock extends Component { const { layout } = this.props.attributes; const isTopLevel = items[ 0 ].menu_item_parent === 0; + const isHorizontal = layout === 'horizontal'; const className = classnames( this.props.className, { - 'is-horizontal': layout === 'horizontal', + 'is-horizontal': isHorizontal, } ); return (
        { items.map( ( item, i ) => { return ( @@ -96,7 +97,6 @@ class NavigationMenuBlock extends Component { } renderMenu() { - const { layout } = this.props.attributes; const { data, isLoading } = this.props.items; const customizerUrl = ''; @@ -117,12 +117,8 @@ class NavigationMenuBlock extends Component { ); } - if ( 'horizontal' === layout ) { - const nestedData = getMenuWithChildren( data ); - return this.renderMenuLevel( nestedData ); - } - - return this.renderMenuLevel( data ); + const nestedData = getMenuWithChildren( data ); + return this.renderMenuLevel( nestedData ); } render() { From 7b931a62fea8ec55ec805fb503b4501d4528272e Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 8 Feb 2018 18:08:24 -0800 Subject: [PATCH 11/19] Change how classes are applied to the container & child `ul`s --- blocks/library/navigation-menu/block.js | 6 ++++-- blocks/library/navigation-menu/editor.scss | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index fd0f63267c4f1..95de09a5c3e52 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -76,14 +76,16 @@ class NavigationMenuBlock extends Component { const { layout } = this.props.attributes; const isTopLevel = items[ 0 ].menu_item_parent === 0; const isHorizontal = layout === 'horizontal'; - const className = classnames( this.props.className, { + const className = classnames( { + [ this.props.className ]: isTopLevel, 'is-horizontal': isHorizontal, + 'is-vertical': ! isHorizontal, } ); return (
          { items.map( ( item, i ) => { return ( diff --git a/blocks/library/navigation-menu/editor.scss b/blocks/library/navigation-menu/editor.scss index c5bba439026fa..139e328f63b98 100644 --- a/blocks/library/navigation-menu/editor.scss +++ b/blocks/library/navigation-menu/editor.scss @@ -1,5 +1,8 @@ .gutenberg .wp-block-navigation-menu { padding-left: 2.5em; + &.is-vertical ul { + padding-left: 2.5em; + } &.is-horizontal { padding-left: 0; } From 253b21e5ff6d3c70b2cade3ffb48a8e6c40d08dc Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Fri, 9 Feb 2018 09:23:04 -0800 Subject: [PATCH 12/19] Update to new location of SelectControl --- blocks/library/navigation-menu/block.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index 95de09a5c3e52..b5707753bf77b 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -8,7 +8,14 @@ import { filter, forEach, isEmpty, isUndefined, sortBy } from 'lodash'; * WordPress dependencies */ import { Component } from '@wordpress/element'; -import { Button, Placeholder, Toolbar, Spinner, withAPIData } from '@wordpress/components'; +import { + Button, + Placeholder, + Toolbar, + SelectControl, + Spinner, + withAPIData, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** @@ -21,7 +28,6 @@ import BlockAlignmentToolbar from '../../block-alignment-toolbar'; import InspectorControls from '../../inspector-controls'; import MenuItem from './item'; import MenuPlaceholder from './placeholder'; -import SelectControl from '../../inspector-controls/select-control'; function getOptionsFromMenu( menus, selected ) { if ( ! menus ) { From 9b794cba44eb6787e4b6fb4c54159fecc9bb34c9 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Fri, 9 Feb 2018 13:36:10 -0800 Subject: [PATCH 13/19] Add meta data to the editor display --- blocks/library/navigation-menu/item.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/blocks/library/navigation-menu/item.js b/blocks/library/navigation-menu/item.js index 8c87888e4f310..2c4f7bb5faa5e 100644 --- a/blocks/library/navigation-menu/item.js +++ b/blocks/library/navigation-menu/item.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -10,8 +15,8 @@ class MenuItem extends Component { const { children, item } = this.props; return ( -
        • - +
        • + { decodeEntities( item.title.trim() ) || __( '(Untitled)' ) } { children } From 0a8f76e9a4a3f71e5907b8802e50a7bb3bbf4c60 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Fri, 9 Feb 2018 13:39:36 -0800 Subject: [PATCH 14/19] Add dynamic rendering for the menu block front-end display --- blocks/library/navigation-menu/index.php | 27 +++++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/blocks/library/navigation-menu/index.php b/blocks/library/navigation-menu/index.php index a1b19cf8e8eee..3f23b9d4af56a 100644 --- a/blocks/library/navigation-menu/index.php +++ b/blocks/library/navigation-menu/index.php @@ -13,19 +13,30 @@ * @return string Returns the post content with navigtion menu added. */ function gutenberg_render_block_core_navigation_menu( $attributes ) { - // get menu. + + $menu_id = (int) $attributes['selected']; + + if ( ! $menu_id ) { + return ''; + } + + $menu = wp_get_nav_menu_object( $menu_id ); + + if ( ! $menu ) { + return ''; + } + $class = "wp-block-navigation-menu align{$attributes['align']}"; if ( isset( $attributes['layout'] ) && 'horizontal' === $attributes['layout'] ) { $class .= ' is-horizontal'; } - $block_content = sprintf( - '
            %2$s
          ', - esc_attr( $class ), - '' - ); - - return $block_content; + return wp_nav_menu( array( + 'menu' => $menu, + 'menu_class' => $class, + 'fallback_cb' => false, + 'echo' => false, + ) ); } register_block_type( 'core/navigation-menu', array( From 8a8f88cec5bc9308b6e456a430e0cb18f9b54cde Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 12 Feb 2018 17:27:39 -0500 Subject: [PATCH 15/19] Add the has-children class to items --- blocks/library/navigation-menu/item.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/blocks/library/navigation-menu/item.js b/blocks/library/navigation-menu/item.js index 2c4f7bb5faa5e..1ca4829481b35 100644 --- a/blocks/library/navigation-menu/item.js +++ b/blocks/library/navigation-menu/item.js @@ -13,9 +13,12 @@ import { decodeEntities } from '@wordpress/utils'; class MenuItem extends Component { render() { const { children, item } = this.props; + const classes = classnames( item.classes, { + 'menu-item-has-children': !! children, + } ); return ( -
        • +
        • { decodeEntities( item.title.trim() ) || __( '(Untitled)' ) } From 6f18c005e60f708ff9ccf194fe87841c83ded197 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 12 Feb 2018 17:27:49 -0500 Subject: [PATCH 16/19] Style nested menus --- blocks/library/navigation-menu/editor.scss | 11 ++++++- blocks/library/navigation-menu/style.scss | 34 +++++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/blocks/library/navigation-menu/editor.scss b/blocks/library/navigation-menu/editor.scss index 139e328f63b98..e8b24a0c3eb2d 100644 --- a/blocks/library/navigation-menu/editor.scss +++ b/blocks/library/navigation-menu/editor.scss @@ -4,6 +4,15 @@ padding-left: 2.5em; } &.is-horizontal { - padding-left: 0; + ul { + border: 1px solid $light-gray-500; + border-top: none; + background: white; + + ul { + border: none; + } + + } } } diff --git a/blocks/library/navigation-menu/style.scss b/blocks/library/navigation-menu/style.scss index 115c9c4680391..8014fc22590d4 100644 --- a/blocks/library/navigation-menu/style.scss +++ b/blocks/library/navigation-menu/style.scss @@ -2,7 +2,6 @@ &.is-horizontal { display: flex; flex-wrap: wrap; - padding: 0; ul { float: left; @@ -10,21 +9,22 @@ top: 100%; left: -999em; z-index: 99999; + margin: 0; + padding: 0 10px 10px; ul { - left: -999em; + position: static; + left: 0; top: 0; + padding: 0 0 0 10px; } li { - &:hover > ul, - &.focus > ul { - left: 100%; - } + margin: 0; } a { - width: 200px; + width: 160px; } } @@ -42,9 +42,29 @@ } } + .menu-item-has-children > a:after { + content: "\f347"; + display: inline-block; + width: 10px; + height: 10px; + font-size: 10px; + line-height: 1; + font-family: dashicons; + text-decoration: inherit; + vertical-align: baseline; + text-align: center; + padding-left: 6px; + } + a { display: block; text-decoration: none; } } + + [data-align="full"] &, + &.alignfull { + padding-left: 2em; + padding-right: 2em; + } } From eb9f1634cb65d9f8ac074e9387fb138d68806eb9 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 12 Feb 2018 22:52:03 -0500 Subject: [PATCH 17/19] Sort menu items --- blocks/library/navigation-menu/block.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index b5707753bf77b..ca4a59a5277ea 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import { filter, forEach, isEmpty, isUndefined, sortBy } from 'lodash'; +import { filter, forEach, isEmpty, isUndefined } from 'lodash'; /** * WordPress dependencies @@ -44,18 +44,24 @@ function getOptionsFromMenu( menus, selected ) { return options; } +function sortMenuItems( items ) { + return [ ...items ].sort( ( a, b ) => { + return a.menu_order - b.menu_order; + } ); +} + function getMenuChildren( list, data ) { forEach( list, function( item, i ) { const children = filter( data, { menu_item_parent: item.id } ); list[ i ].children = getMenuChildren( children, data ); } ); - return sortBy( list, 'menu_order' ); + return sortMenuItems( list ); } function getMenuWithChildren( data ) { - const sorted = sortBy( filter( data, { menu_item_parent: 0 } ), 'menu_order' ); - getMenuChildren( sorted, data ); - return sorted; + const items = filter( data, { menu_item_parent: 0 } ); + const sorted = sortMenuItems( items ); + return getMenuChildren( sorted, data ); } class NavigationMenuBlock extends Component { From 44ac0dc92b41cda192d73c9ead33b4628d355e05 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 12 Feb 2018 22:52:18 -0500 Subject: [PATCH 18/19] Fix padding around full-width menus --- blocks/library/navigation-menu/editor.scss | 6 ++++++ blocks/library/navigation-menu/style.scss | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/blocks/library/navigation-menu/editor.scss b/blocks/library/navigation-menu/editor.scss index e8b24a0c3eb2d..c70176b6ba119 100644 --- a/blocks/library/navigation-menu/editor.scss +++ b/blocks/library/navigation-menu/editor.scss @@ -4,6 +4,7 @@ padding-left: 2.5em; } &.is-horizontal { + padding-left: 0; ul { border: 1px solid $light-gray-500; border-top: none; @@ -16,3 +17,8 @@ } } } + +.gutenberg [data-align="full"] .wp-block-navigation-menu { + padding-left: 2em; + padding-right: 2em; +} diff --git a/blocks/library/navigation-menu/style.scss b/blocks/library/navigation-menu/style.scss index 8014fc22590d4..2d5bf8d96f2e7 100644 --- a/blocks/library/navigation-menu/style.scss +++ b/blocks/library/navigation-menu/style.scss @@ -62,7 +62,6 @@ } } - [data-align="full"] &, &.alignfull { padding-left: 2em; padding-right: 2em; From 1bf805e13314fa4dd1425de0aca3a4a9e73448b0 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 15 Mar 2018 09:48:12 -0400 Subject: [PATCH 19/19] Address PR feedback --- blocks/library/navigation-menu/block.js | 3 +-- blocks/library/navigation-menu/index.js | 2 +- blocks/library/navigation-menu/index.php | 10 +++---- blocks/library/navigation-menu/placeholder.js | 27 ++++++++++++------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/blocks/library/navigation-menu/block.js b/blocks/library/navigation-menu/block.js index ca4a59a5277ea..bb3f81c21fdb2 100644 --- a/blocks/library/navigation-menu/block.js +++ b/blocks/library/navigation-menu/block.js @@ -112,7 +112,6 @@ class NavigationMenuBlock extends Component { renderMenu() { const { data, isLoading } = this.props.items; - const customizerUrl = ''; if ( isUndefined( data ) || isEmpty( data ) || isLoading ) { return ( @@ -123,7 +122,7 @@ class NavigationMenuBlock extends Component { > { ! Array.isArray( data ) ? : - } diff --git a/blocks/library/navigation-menu/index.js b/blocks/library/navigation-menu/index.js index 447f4f26be100..71a0e22dd5004 100644 --- a/blocks/library/navigation-menu/index.js +++ b/blocks/library/navigation-menu/index.js @@ -15,7 +15,7 @@ export const name = 'core/navigation-menu'; export const settings = { title: __( 'Navigation Menu' ), - description: __( 'Display your site pages.' ), + description: __( 'Show a list of menu items.' ), icon: 'menu', diff --git a/blocks/library/navigation-menu/index.php b/blocks/library/navigation-menu/index.php index 3f23b9d4af56a..5c1e055fd85d0 100644 --- a/blocks/library/navigation-menu/index.php +++ b/blocks/library/navigation-menu/index.php @@ -40,15 +40,15 @@ function gutenberg_render_block_core_navigation_menu( $attributes ) { } register_block_type( 'core/navigation-menu', array( - 'attributes' => array( - 'selected' => array( - 'type' => 'string', + 'attributes' => array( + 'selected' => array( + 'type' => 'int', ), - 'layout' => array( + 'layout' => array( 'type' => 'string', 'default' => 'vertical', ), - 'align' => array( + 'align' => array( 'type' => 'string', 'default' => 'center', ), diff --git a/blocks/library/navigation-menu/placeholder.js b/blocks/library/navigation-menu/placeholder.js index bcf7eca37fc1a..03d70e76fd424 100644 --- a/blocks/library/navigation-menu/placeholder.js +++ b/blocks/library/navigation-menu/placeholder.js @@ -2,8 +2,8 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { Button, Placeholder, Spinner } from '@wordpress/components'; import { Component } from '@wordpress/element'; -import { Placeholder, Spinner } from '@wordpress/components'; class MenuPlaceholder extends Component { render() { @@ -12,14 +12,23 @@ class MenuPlaceholder extends Component { if ( ! hasMenus ) { return ( - - { ! Array.isArray( menus ) ? - : - __( 'No menus found.' ) - } + label={ __( 'Navigation Menu' ) }> + { ! Array.isArray( menus ) ? ( + + ) : ( +
          + { __( 'No menus found.' ) } + { ' ' } + +
          + ) }
          ); } @@ -28,7 +37,7 @@ class MenuPlaceholder extends Component { + label={ __( 'Navigation Menu' ) }> { children } );