diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index a97104b5b438b..ad92c523174d1 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -60,6 +60,8 @@ export { default as withColorContext } from './color-palette/with-color-context' export { default as __experimentalBlockSettingsMenuFirstItem } from './block-settings-menu/block-settings-menu-first-item'; export { default as __experimentalInserterMenuExtension } from './inserter-menu-extension'; +export { default as __experimentalPreviewOptions } from './preview-options'; +export { default as __experimentalUseResizeCanvas } from './resize-canvas'; export { default as BlockInspector } from './block-inspector'; export { default as BlockList } from './block-list'; export { Block as __experimentalBlock } from './block-list/block-wrapper'; diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js new file mode 100644 index 0000000000000..8a3563fbc11a9 --- /dev/null +++ b/packages/block-editor/src/components/preview-options/index.js @@ -0,0 +1,70 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Button, Dropdown, MenuGroup, MenuItem } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { Icon, check, chevronDown } from '@wordpress/icons'; + +export default function PreviewOptions( { + children, + className, + isEnabled = true, + deviceType, + setDeviceType, +} ) { + return ( + ( + + ) } + renderContent={ () => ( + <> + + setDeviceType( 'Desktop' ) } + icon={ deviceType === 'Desktop' && check } + > + { __( 'Desktop' ) } + + setDeviceType( 'Tablet' ) } + icon={ deviceType === 'Tablet' && check } + > + { __( 'Tablet' ) } + + setDeviceType( 'Mobile' ) } + icon={ deviceType === 'Mobile' && check } + > + { __( 'Mobile' ) } + + + { children } + + ) } + /> + ); +} diff --git a/packages/edit-post/src/components/preview-options/style.scss b/packages/block-editor/src/components/preview-options/style.scss similarity index 60% rename from packages/edit-post/src/components/preview-options/style.scss rename to packages/block-editor/src/components/preview-options/style.scss index de88a83faa7b2..48b44bfa09151 100644 --- a/packages/edit-post/src/components/preview-options/style.scss +++ b/packages/block-editor/src/components/preview-options/style.scss @@ -1,10 +1,10 @@ -.editor-post-preview__dropdown { +.block-editor-post-preview__dropdown { display: none; margin-right: $grid-unit-15; padding: 0; } -.editor-post-preview__button-toggle { +.block-editor-post-preview__button-toggle { display: flex; justify-content: space-between; padding: 0 $grid-unit-10 0 $grid-unit-15; @@ -18,7 +18,7 @@ } } -.editor-post-preview__button-resize.editor-post-preview__button-resize { +.block-editor-post-preview__button-resize.block-editor-post-preview__button-resize { padding-left: $button-size-small + $grid-unit-10 + $grid-unit-10; &.has-icon { @@ -26,10 +26,9 @@ } } -.editor-post-preview__dropdown-content { +.block-editor-post-preview__dropdown-content { .components-popover__content { overflow-y: visible; - padding-bottom: 0; } .components-menu-group + .components-menu-group { @@ -40,29 +39,12 @@ } } -.editor-post-preview__grouping-external { - display: flex; - position: relative; -} - -.editor-post-preview__button-external { - padding-left: $grid-unit-10; - margin-right: auto; - width: 100%; - display: flex; - justify-content: flex-start; - - svg { - margin-right: $grid-unit-10; - } -} - @include break-small() { .editor-post-preview { display: none; } - .editor-post-preview__dropdown { + .block-editor-post-preview__dropdown { display: flex; } } diff --git a/packages/edit-post/src/components/resize-canvas/index.js b/packages/block-editor/src/components/resize-canvas/index.js similarity index 82% rename from packages/edit-post/src/components/resize-canvas/index.js rename to packages/block-editor/src/components/resize-canvas/index.js index f09214edc8f10..2f9723d08a355 100644 --- a/packages/edit-post/src/components/resize-canvas/index.js +++ b/packages/block-editor/src/components/resize-canvas/index.js @@ -1,20 +1,21 @@ /** * WordPress dependencies */ -import { useSimulatedMediaQuery } from '@wordpress/block-editor'; -import { useSelect } from '@wordpress/data'; import { useEffect, useState } from '@wordpress/element'; +/** + * Internal dependencies + */ +import { default as useSimulatedMediaQuery } from '../../components/use-simulated-media-query'; + /** * Function to resize the editor window. * + * @param {string} deviceType Used for determining the size of the container (e.g. Desktop, Tablet, Mobile) + * * @return {Object} Inline styles to be added to resizable container. */ -export function useResizeCanvas() { - const deviceType = useSelect( ( select ) => { - return select( 'core/edit-post' ).__experimentalGetPreviewDeviceType(); - }, [] ); - +export default function useResizeCanvas( deviceType ) { const [ actualWidth, updateActualWidth ] = useState( window.innerWidth ); useEffect( () => { diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index ba14cf1e346cb..a04b2cc8cd26b 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -55,4 +55,4 @@ @import "./components/block-toolbar/style.scss"; @import "./components/inserter/style.scss"; - +@import "./components/preview-options/style.scss"; diff --git a/packages/e2e-tests/specs/editor/plugins/block-context.test.js b/packages/e2e-tests/specs/editor/plugins/block-context.test.js index 8f287bbb59add..d7536b20f7166 100644 --- a/packages/e2e-tests/specs/editor/plugins/block-context.test.js +++ b/packages/e2e-tests/specs/editor/plugins/block-context.test.js @@ -17,9 +17,9 @@ import { async function openPreviewPage( editorPage ) { let openTabs = await browser.pages(); const expectedTabsCount = openTabs.length + 1; - await editorPage.click( '.editor-post-preview__button-toggle' ); - await editorPage.waitFor( '.editor-post-preview__button-external' ); - await editorPage.click( '.editor-post-preview__button-external' ); + await editorPage.click( '.block-editor-post-preview__button-toggle' ); + await editorPage.waitFor( '.edit-post-header-preview__button-external' ); + await editorPage.click( '.edit-post-header-preview__button-external' ); // Wait for the new tab to open. while ( openTabs.length < expectedTabsCount ) { diff --git a/packages/e2e-tests/specs/editor/various/preview.test.js b/packages/e2e-tests/specs/editor/various/preview.test.js index c45e7cced2e7b..e53cc7f742426 100644 --- a/packages/e2e-tests/specs/editor/various/preview.test.js +++ b/packages/e2e-tests/specs/editor/various/preview.test.js @@ -22,9 +22,9 @@ import { async function openPreviewPage( editorPage ) { let openTabs = await browser.pages(); const expectedTabsCount = openTabs.length + 1; - await editorPage.click( '.editor-post-preview__button-toggle' ); - await editorPage.waitFor( '.editor-post-preview__button-external' ); - await editorPage.click( '.editor-post-preview__button-external' ); + await editorPage.click( '.block-editor-post-preview__button-toggle' ); + await editorPage.waitFor( '.edit-post-header-preview__button-external' ); + await editorPage.click( '.edit-post-header-preview__button-external' ); // Wait for the new tab to open. while ( openTabs.length < expectedTabsCount ) { @@ -49,9 +49,9 @@ async function openPreviewPage( editorPage ) { * @return {Promise} Promise resolving once selector is visible on page. */ async function waitForPreviewDropdownOpen( editorPage ) { - await editorPage.click( '.editor-post-preview__button-toggle' ); + await editorPage.click( '.block-editor-post-preview__button-toggle' ); return editorPage.waitForSelector( - '.editor-post-preview__button-external' + '.edit-post-header-preview__button-external' ); } @@ -64,7 +64,7 @@ async function waitForPreviewDropdownOpen( editorPage ) { * @return {Promise} Promise resolving once navigation completes. */ async function waitForPreviewNavigation( previewPage ) { - await page.click( '.editor-post-preview__button-external' ); + await page.click( '.edit-post-header-preview__button-external' ); return previewPage.waitForNavigation(); } @@ -115,7 +115,7 @@ describe( 'Preview', () => { // Disabled until content present. const isPreviewDisabled = await editorPage.$$eval( - '.editor-post-preview__button-toggle:not( :disabled ):not( [aria-disabled="true"] )', + '.block-editor-post-preview__button-toggle:not( :disabled ):not( [aria-disabled="true"] )', ( enabledButtons ) => ! enabledButtons.length ); expect( isPreviewDisabled ).toBe( true ); @@ -342,10 +342,10 @@ describe( 'Preview with private custom post type', () => { await page.keyboard.press( 'Tab' ); // Open the preview menu. - await page.click( '.editor-post-preview__button-toggle' ); + await page.click( '.block-editor-post-preview__button-toggle' ); const previewDropdownContents = await page.$( - '.editor-post-preview__dropdown-content' + '.block-editor-post-preview__dropdown-content' ); // Expect the Preview Externally link not to be present. diff --git a/packages/edit-post/src/components/device-preview/index.js b/packages/edit-post/src/components/device-preview/index.js new file mode 100644 index 0000000000000..bc482905e7336 --- /dev/null +++ b/packages/edit-post/src/components/device-preview/index.js @@ -0,0 +1,58 @@ +/** + * WordPress dependencies + */ +import { Icon, MenuGroup } from '@wordpress/components'; +import { PostPreviewButton } from '@wordpress/editor'; +import { external } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import { __experimentalPreviewOptions as PreviewOptions } from '@wordpress/block-editor'; +import { useDispatch, useSelect } from '@wordpress/data'; + +export default function DevicePreview() { + const { + hasActiveMetaboxes, + isPostSaveable, + isSaving, + deviceType, + } = useSelect( + ( select ) => ( { + hasActiveMetaboxes: select( 'core/edit-post' ).hasMetaBoxes(), + isSaving: select( 'core/edit-post' ).isSavingMetaBoxes(), + isPostSaveable: select( 'core/editor' ).isEditedPostSaveable(), + deviceType: select( + 'core/edit-post' + ).__experimentalGetPreviewDeviceType(), + } ), + [] + ); + const { + __experimentalSetPreviewDeviceType: setPreviewDeviceType, + } = useDispatch( 'core/edit-post' ); + + return ( + + +
+ + + { __( 'Preview in new tab' ) } + + } + /> +
+
+
+ ); +} diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js index d8e28f31486b6..4ffbe107c5f87 100644 --- a/packages/edit-post/src/components/header/index.js +++ b/packages/edit-post/src/components/header/index.js @@ -3,7 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; -import { PostPreviewButton, PostSavedState } from '@wordpress/editor'; +import { PostSavedState, PostPreviewButton } from '@wordpress/editor'; import { useSelect, useDispatch } from '@wordpress/data'; import { cog } from '@wordpress/icons'; import { PinnedItems, AdminMenuToggle } from '@wordpress/interface'; @@ -14,7 +14,7 @@ import { PinnedItems, AdminMenuToggle } from '@wordpress/interface'; import HeaderToolbar from './header-toolbar'; import MoreMenu from './more-menu'; import PostPublishButtonOrToggle from './post-publish-button-or-toggle'; -import PreviewOptions from '../preview-options'; +import { default as DevicePreview } from '../device-preview'; function Header( { onToggleInserter, isInserterOpen } ) { const { @@ -40,9 +40,13 @@ function Header( { onToggleInserter, isInserterOpen } ) { isSaving: select( 'core/edit-post' ).isSavingMetaBoxes(), getBlockSelectionStart: select( 'core/block-editor' ) .getBlockSelectionStart, + isPostSaveable: select( 'core/editor' ).isEditedPostSaveable(), isFullscreenActive: select( 'core/edit-post' ).isFeatureActive( 'fullscreenMode' ), + deviceType: select( + 'core/edit-post' + ).__experimentalGetPreviewDeviceType(), } ), [] ); @@ -80,10 +84,7 @@ function Header( { onToggleInserter, isInserterOpen } ) { forceIsSaving={ isSaving } /> ) } - + - - -); - -export default function PreviewOptions( { - forceIsAutosaveable, - forcePreviewLink, -} ) { - const { - __experimentalSetPreviewDeviceType: setPreviewDeviceType, - } = useDispatch( 'core/edit-post' ); - - const deviceType = useSelect( ( select ) => { - return select( 'core/edit-post' ).__experimentalGetPreviewDeviceType(); - }, [] ); - - const isSaveable = useSelect( ( select ) => { - return select( 'core/editor' ).isEditedPostSaveable(); - }, [] ); - - const isViewable = useSelect( ( select ) => { - const { getEditedPostAttribute } = select( 'core/editor' ); - const { getPostType } = select( 'core' ); - const postType = getPostType( getEditedPostAttribute( 'type' ) ); - return get( postType, [ 'viewable' ], false ); - }, [] ); - - return ( - ( - - ) } - renderContent={ () => ( - <> - - setPreviewDeviceType( 'Desktop' ) } - icon={ deviceType === 'Desktop' && check } - > - { __( 'Desktop' ) } - - setPreviewDeviceType( 'Tablet' ) } - icon={ deviceType === 'Tablet' && check } - > - { __( 'Tablet' ) } - - setPreviewDeviceType( 'Mobile' ) } - icon={ deviceType === 'Mobile' && check } - > - { __( 'Mobile' ) } - - - { isViewable && ( - -
- - - { __( 'Preview in new tab' ) } - - } - /> -
-
- ) } - - ) } - /> - ); -} diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js index 9929a6699674f..ee5a8c62359f0 100644 --- a/packages/edit-post/src/components/visual-editor/index.js +++ b/packages/edit-post/src/components/visual-editor/index.js @@ -14,6 +14,7 @@ import { BlockSelectionClearer, MultiSelectScrollIntoView, __experimentalBlockSettingsMenuFirstItem, + __experimentalUseResizeCanvas as useResizeCanvas, } from '@wordpress/block-editor'; import { Popover } from '@wordpress/components'; @@ -21,10 +22,14 @@ import { Popover } from '@wordpress/components'; * Internal dependencies */ import BlockInspectorButton from './block-inspector-button'; -import { useResizeCanvas } from '../resize-canvas'; +import { useSelect } from '@wordpress/data'; function VisualEditor() { - const inlineStyles = useResizeCanvas(); + const deviceType = useSelect( ( select ) => { + return select( 'core/edit-post' ).__experimentalGetPreviewDeviceType(); + }, [] ); + + const inlineStyles = useResizeCanvas( deviceType ); return ( { + return select( 'core/edit-site' ).__experimentalGetPreviewDeviceType(); + }, [] ); + + const inlineStyles = useResizeCanvas( deviceType ); + return template ? ( <> @@ -78,11 +86,13 @@ function Editor( { settings: _settings } ) { sidebar={ ! isMobile && } header={
} content={ - <> + - + } footer={ } /> diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index 1fc21c8440a9c..ecfbbca87857b 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -6,8 +6,9 @@ import { BlockNavigationDropdown, ToolSelector, Inserter, + __experimentalPreviewOptions as PreviewOptions, } from '@wordpress/block-editor'; -import { useSelect } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { PinnedItems, AdminMenuToggle } from '@wordpress/interface'; /** @@ -59,6 +60,14 @@ export default function Header() { [] ); + const deviceType = useSelect( ( select ) => { + return select( 'core/edit-site' ).__experimentalGetPreviewDeviceType(); + }, [] ); + + const { + __experimentalSetPreviewDeviceType: setPreviewDeviceType, + } = useDispatch( 'core/edit-site' ); + return (
{ isFullscreenActive && } @@ -83,6 +92,10 @@ export default function Header() {
+ diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index d2f2692f19479..ad3aa0ca273ea 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -11,3 +11,17 @@ export function toggleFeature( feature ) { feature, }; } + +/** + * Returns an action object used to toggle the width of the editing canvas. + * + * @param {string} deviceType + * + * @return {Object} Action object. + */ +export function __experimentalSetPreviewDeviceType( deviceType ) { + return { + type: 'SET_PREVIEW_DEVICE_TYPE', + deviceType, + }; +} diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index d8fd6157e6e59..229f88f6eb092 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -48,6 +48,24 @@ export const preferences = flow( [ }, } ); +/** + * Reducer returning the editing canvas device type. + * + * @param {Object} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Object} Updated state. + */ +export function deviceType( state = 'Desktop', action ) { + switch ( action.type ) { + case 'SET_PREVIEW_DEVICE_TYPE': + return action.deviceType; + } + + return state; +} + export default combineReducers( { preferences, + deviceType, } ); diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 0cc6f860f87c5..496a9c65151b9 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -14,3 +14,14 @@ import { get } from 'lodash'; export function isFeatureActive( state, feature ) { return get( state.preferences.features, [ feature ], false ); } + +/** + * Returns the current editing canvas device type. + * + * @param {Object} state Global application state. + * + * @return {string} Device type. + */ +export function __experimentalGetPreviewDeviceType( state ) { + return state.deviceType; +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 6f5f71693dbf2..5525a1f0263f2 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -49,6 +49,10 @@ body.toplevel_page_gutenberg-edit-site { .interface-complementary-area__pin-unpin-item.components-button { display: none; } + + .interface-interface-skeleton__content { + background-color: $light-gray-700; + } } /**