diff --git a/package-lock.json b/package-lock.json index 2b506b15ae9a0..004a666df5ad3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15958,6 +15958,7 @@ "@wordpress/plugins": "file:packages/plugins", "@wordpress/primitives": "file:packages/primitives", "@wordpress/url": "file:packages/url", + "classnames": "^2.2.5", "downloadjs": "^1.4.7", "file-saver": "^2.0.2", "jszip": "^3.2.2", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 7e90f03aafaa4..034609ad9f025 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -50,6 +50,7 @@ "@wordpress/plugins": "file:../plugins", "@wordpress/primitives": "file:../primitives", "@wordpress/url": "file:../url", + "classnames": "^2.2.5", "downloadjs": "^1.4.7", "file-saver": "^2.0.2", "jszip": "^3.2.2", diff --git a/packages/edit-site/src/components/header/document-actions/index.js b/packages/edit-site/src/components/header/document-actions/index.js new file mode 100644 index 0000000000000..65d33f2147800 --- /dev/null +++ b/packages/edit-site/src/components/header/document-actions/index.js @@ -0,0 +1,152 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Button, Dropdown } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { + __experimentalGetBlockLabel as getBlockLabel, + getBlockType, +} from '@wordpress/blocks'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { DOWN } from '@wordpress/keycodes'; + +function useSecondaryText() { + const selectedBlock = useSelect( ( select ) => { + return select( 'core/block-editor' ).getSelectedBlock(); + } ); + + // TODO: Handle if parent is template part too. + const selectedBlockLabel = + selectedBlock?.name === 'core/template-part' + ? getBlockLabel( + getBlockType( selectedBlock?.name ), + selectedBlock?.attributes + ) + : null; + + if ( selectedBlockLabel ) { + return { + label: selectedBlockLabel, + isActive: true, + }; + } + return {}; +} + +export default function DocumentActions( { documentTitle } ) { + const { label, isActive } = useSecondaryText(); + // Title is active when there is no secondary item, or when the secondary + // item is inactive. + const isTitleActive = ! label?.length || ! isActive; + + const { page } = useSelect( ( select ) => { + const { getPage } = select( 'core/edit-site' ); + const { getEntityRecord } = select( 'core' ); + const _page = getPage(); + return { + page: getEntityRecord( 'postType', 'page', _page?.context?.postId ), + }; + } ); + + const { editEntityRecord } = useDispatch( 'core' ); + const editTitle = ( title ) => { + editEntityRecord( 'postType', 'page', page.id, { + title, + slug: title, + } ); + }; + + return ( +
+ { documentTitle ? ( + <> + { + const openOnArrowDown = ( event ) => { + if ( ! isOpen && event.keyCode === DOWN ) { + event.preventDefault(); + event.stopPropagation(); + onToggle(); + } + }; + { + /* TODO: Fix vertical text padding */ + } + return ( + + ); + } } + renderContent={ () => ( +
+ { /* TODO: Replace inline styles */ } + + Name + + { /* TODO: Don't allow input when there is no page context */ } + { + const REGEXP_NEWLINES = /[\r\n]+/g; + const title = event.target.value.replace( + REGEXP_NEWLINES, + ' ' + ); + + editTitle( title ); + } } + /> +
+ ) } + >
+
+ { label ?? '' } +
+ + ) : ( + __( 'Loading…' ) + ) } +
+ ); +} diff --git a/packages/edit-site/src/components/header/document-actions/style.scss b/packages/edit-site/src/components/header/document-actions/style.scss new file mode 100644 index 0000000000000..e17ca10910ea4 --- /dev/null +++ b/packages/edit-site/src/components/header/document-actions/style.scss @@ -0,0 +1,34 @@ +.edit-site-document-actions { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + + .edit-site-document-actions__label { + color: $gray-700; + display: flex; + justify-content: center; + align-items: center; + transition: height 0.25s; + + &.is-active { + color: inherit; + } + + &.edit-site-document-actions__title { + height: 100%; + // Otherwise, the secondary item still takes up space with height 0: + flex-grow: 1; + } + + &.edit-site-document-actions__secondary-item { + height: 0; + } + } + + &.has-secondary-label { + .edit-site-document-actions__label { + height: 50%; + } + } +} diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index 1dcdb84737876..563a60602dae7 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -27,6 +27,7 @@ import SaveButton from '../save-button'; import UndoButton from './undo-redo/undo'; import RedoButton from './undo-redo/redo'; import FullscreenModeClose from './fullscreen-mode-close'; +import DocumentActions from './document-actions'; export default function Header( { openEntitiesSavedStates, @@ -36,6 +37,7 @@ export default function Header( { const { deviceType, hasFixedToolbar, + template, templateId, templatePartId, templateType, @@ -51,14 +53,18 @@ export default function Header( { getPage, } = select( 'core/edit-site' ); - const { show_on_front: _showOnFront } = select( - 'core' - ).getEditedEntityRecord( 'root', 'site' ); + const { getEntityRecord, getEditedEntityRecord } = select( 'core' ); + const { show_on_front: _showOnFront } = getEditedEntityRecord( + 'root', + 'site' + ); + const _templateId = getTemplateId(); return { deviceType: __experimentalGetPreviewDeviceType(), hasFixedToolbar: isFeatureActive( 'fixedToolbar' ), - templateId: getTemplateId(), + templateId: _templateId, + template: getEntityRecord( 'postType', 'wp_template', _templateId ), templatePartId: getTemplatePartId(), templateType: getTemplateType(), page: getPage(), @@ -81,62 +87,73 @@ export default function Header( { return (
- - - -
-