diff --git a/docs/reference-guides/data/data-core-blocks.md b/docs/reference-guides/data/data-core-blocks.md
index a25a521931e25a..084c9c1d7a5fbc 100644
--- a/docs/reference-guides/data/data-core-blocks.md
+++ b/docs/reference-guides/data/data-core-blocks.md
@@ -504,54 +504,6 @@ _Returns_
- `string?`: Name of the block for handling the grouping of blocks.
-### getHookedBlocks
-
-Returns the hooked blocks for a given anchor block.
-
-Given an anchor block name, returns an object whose keys are relative positions, and whose values are arrays of block names that are hooked to the anchor block at that relative position.
-
-_Usage_
-
-```js
-import { store as blocksStore } from '@wordpress/blocks';
-import { useSelect } from '@wordpress/data';
-
-const ExampleComponent = () => {
- const hookedBlockNames = useSelect(
- ( select ) =>
- select( blocksStore ).getHookedBlocks( 'core/navigation' ),
- []
- );
-
- return (
-
diff --git a/packages/edit-post/src/components/editor-initialization/listener-hooks.js b/packages/edit-post/src/components/editor-initialization/listener-hooks.js
index 57f5f67721ba72..73872b4d7110e4 100644
--- a/packages/edit-post/src/components/editor-initialization/listener-hooks.js
+++ b/packages/edit-post/src/components/editor-initialization/listener-hooks.js
@@ -5,6 +5,7 @@ import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useRef } from '@wordpress/element';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as editorStore } from '@wordpress/editor';
+import { store as preferencesStore } from '@wordpress/preferences';
/**
* Internal dependencies
@@ -22,19 +23,25 @@ import {
* @param {number} postId The current post id.
*/
export const useBlockSelectionListener = ( postId ) => {
- const { hasBlockSelection, isEditorSidebarOpened } = useSelect(
- ( select ) => ( {
- hasBlockSelection:
- !! select( blockEditorStore ).getBlockSelectionStart(),
- isEditorSidebarOpened: select( STORE_NAME ).isEditorSidebarOpened(),
- } ),
- [ postId ]
- );
+ const { hasBlockSelection, isEditorSidebarOpened, isDistractionFree } =
+ useSelect(
+ ( select ) => {
+ const { get } = select( preferencesStore );
+ return {
+ hasBlockSelection:
+ !! select( blockEditorStore ).getBlockSelectionStart(),
+ isEditorSidebarOpened:
+ select( STORE_NAME ).isEditorSidebarOpened(),
+ isDistractionFree: get( 'core', 'distractionFree' ),
+ };
+ },
+ [ postId ]
+ );
const { openGeneralSidebar } = useDispatch( STORE_NAME );
useEffect( () => {
- if ( ! isEditorSidebarOpened ) {
+ if ( ! isEditorSidebarOpened || isDistractionFree ) {
return;
}
if ( hasBlockSelection ) {
diff --git a/packages/edit-post/src/components/editor-initialization/test/listener-hooks.js b/packages/edit-post/src/components/editor-initialization/test/listener-hooks.js
index c263d993982978..5087d303fafe1e 100644
--- a/packages/edit-post/src/components/editor-initialization/test/listener-hooks.js
+++ b/packages/edit-post/src/components/editor-initialization/test/listener-hooks.js
@@ -44,6 +44,12 @@ describe( 'listener hook tests', () => {
isViewportMatch: jest.fn(),
},
},
+ 'core/preferences': {
+ ...storeConfig,
+ selectors: {
+ get: jest.fn(),
+ },
+ },
[ STORE_NAME ]: {
...storeConfig,
actions: {
@@ -112,6 +118,7 @@ describe( 'listener hook tests', () => {
'getBlockSelectionStart',
true
);
+ setMockReturnValue( 'core/preferences', 'get', false );
render(
);
@@ -120,12 +127,14 @@ describe( 'listener hook tests', () => {
).toHaveBeenCalledWith( 'edit-post/block' );
} );
it( 'opens document sidebar if block is not selected', () => {
+ setMockReturnValue( STORE_NAME, 'isEditorSidebarOpened', true );
setMockReturnValue( STORE_NAME, 'isEditorSidebarOpened', true );
setMockReturnValue(
'core/block-editor',
'getBlockSelectionStart',
false
);
+ setMockReturnValue( 'core/preferences', 'get', false );
render(
);
@@ -133,6 +142,37 @@ describe( 'listener hook tests', () => {
getSpyedAction( STORE_NAME, 'openGeneralSidebar' )
).toHaveBeenCalledWith( 'edit-post/document' );
} );
+ it( 'does not open block sidebar if block is selected and distraction free mode is on', () => {
+ setMockReturnValue( STORE_NAME, 'isEditorSidebarOpened', true );
+ setMockReturnValue(
+ 'core/block-editor',
+ 'getBlockSelectionStart',
+ true
+ );
+ setMockReturnValue( 'core/preferences', 'get', true );
+
+ render(
);
+
+ expect(
+ getSpyedAction( STORE_NAME, 'openGeneralSidebar' )
+ ).toHaveBeenCalledTimes( 0 );
+ } );
+ it( 'does not open document sidebar if block is not selected and distraction free is on', () => {
+ setMockReturnValue( STORE_NAME, 'isEditorSidebarOpened', true );
+ setMockReturnValue( STORE_NAME, 'isEditorSidebarOpened', true );
+ setMockReturnValue(
+ 'core/block-editor',
+ 'getBlockSelectionStart',
+ false
+ );
+ setMockReturnValue( 'core/preferences', 'get', true );
+
+ render(
);
+
+ expect(
+ getSpyedAction( STORE_NAME, 'openGeneralSidebar' )
+ ).toHaveBeenCalledTimes( 0 );
+ } );
} );
describe( 'useUpdatePostLinkListener', () => {
diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js
index 9dd7314357e043..eb2b696fa39706 100644
--- a/packages/edit-post/src/components/layout/index.js
+++ b/packages/edit-post/src/components/layout/index.js
@@ -385,7 +385,7 @@ function Layout( { initialPost } ) {
-
+ { ! isDistractionFree &&
}
>
);
}
diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js
index 08bc7c5aa7002c..527818018ad5c9 100644
--- a/packages/edit-post/src/index.js
+++ b/packages/edit-post/src/index.js
@@ -49,6 +49,7 @@ export function initializeEditor(
settings,
initialEdits
) {
+ const isMediumOrBigger = window.matchMedia( '(min-width: 782px)' ).matches;
const target = document.getElementById( id );
const root = createRoot( target );
@@ -77,7 +78,9 @@ export function initializeEditor(
// Check if the block list view should be open by default.
// If `distractionFree` mode is enabled, the block list view should not be open.
+ // This behavior is disabled for small viewports.
if (
+ isMediumOrBigger &&
select( preferencesStore ).get( 'core', 'showListViewByDefault' ) &&
! select( preferencesStore ).get( 'core', 'distractionFree' )
) {
diff --git a/packages/edit-site/src/components/add-new-pattern/index.js b/packages/edit-site/src/components/add-new-pattern/index.js
index 014ac6165aaef2..0d25ff67bf4482 100644
--- a/packages/edit-site/src/components/add-new-pattern/index.js
+++ b/packages/edit-site/src/components/add-new-pattern/index.js
@@ -25,10 +25,11 @@ import {
PATTERN_DEFAULT_CATEGORY,
TEMPLATE_PART_POST_TYPE,
} from '../../utils/constants';
-import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories';
const { useHistory, useLocation } = unlock( routerPrivateApis );
-const { CreatePatternModal } = unlock( editPatternsPrivateApis );
+const { CreatePatternModal, useAddPatternCategory } = unlock(
+ editPatternsPrivateApis
+);
export default function AddNewPattern() {
const history = useHistory();
@@ -43,7 +44,6 @@ export default function AddNewPattern() {
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
const patternUploadInputRef = useRef();
- const { patternCategories } = usePatternCategories();
function handleCreatePattern( { pattern, categoryId } ) {
setShowPatternModal( false );
@@ -97,6 +97,7 @@ export default function AddNewPattern() {
title: __( 'Import pattern from JSON' ),
} );
+ const { categoryMap, findOrCreateTerm } = useAddPatternCategory();
return (
<>
- category.name === params.categoryId
- )?.id;
+ let currentCategoryId;
+ // When we're not handling template parts, we should
+ // add or create the proper pattern category.
+ if ( params.categoryType !== TEMPLATE_PART_POST_TYPE ) {
+ const currentCategory = categoryMap
+ .values()
+ .find(
+ ( term ) => term.name === params.categoryId
+ );
+ if ( !! currentCategory ) {
+ currentCategoryId =
+ currentCategory.id ||
+ ( await findOrCreateTerm(
+ currentCategory.label
+ ) );
+ }
+ }
const pattern = await createPatternFromFile(
file,
currentCategoryId
@@ -146,8 +158,12 @@ export default function AddNewPattern() {
);
// Navigate to the All patterns category for the newly created pattern
- // if we're not on that page already.
- if ( ! currentCategoryId ) {
+ // if we're not on that page already and if we're not in the `my-patterns`
+ // category.
+ if (
+ ! currentCategoryId &&
+ params.categoryId !== 'my-patterns'
+ ) {
history.push( {
path: `/patterns`,
categoryType: PATTERN_TYPES.theme,
diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js
index 9c95755db28031..6563374858a37f 100644
--- a/packages/edit-site/src/components/editor/index.js
+++ b/packages/edit-site/src/components/editor/index.js
@@ -263,6 +263,7 @@ export default function Editor( { isLoading } ) {
( shouldShowListView && ) )
}
sidebar={
+ ! isDistractionFree &&
isEditMode &&
isRightSidebarOpen && (
<>
diff --git a/packages/edit-site/src/components/global-styles/block-preview-panel.js b/packages/edit-site/src/components/global-styles/block-preview-panel.js
index 24bd2e666eab3e..787d8c6d47e500 100644
--- a/packages/edit-site/src/components/global-styles/block-preview-panel.js
+++ b/packages/edit-site/src/components/global-styles/block-preview-panel.js
@@ -28,7 +28,7 @@ const BlockPreviewPanel = ( { name, variation = '' } ) => {
}, [ name, blockExample, variation ] );
const viewportWidth = blockExample?.viewportWidth ?? null;
- const previewHeight = '150px';
+ const previewHeight = 150;
if ( ! blockExample ) {
return null;
@@ -48,7 +48,7 @@ const BlockPreviewPanel = ( { name, variation = '' } ) => {
{
css: `
body{
- min-height:${ previewHeight };
+ min-height:${ previewHeight }px;
display:flex;align-items:center;justify-content:center;
}
`,
diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js b/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js
index de0c1cfa16ec6e..a6962952661939 100644
--- a/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js
+++ b/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js
@@ -48,7 +48,7 @@ function CollectionFontDetails( {
/>
) ) }
-
+
>
);
}
diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js
index 4a14ee245694b8..6236ea8fe3f246 100644
--- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js
+++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js
@@ -1,11 +1,18 @@
/**
* WordPress dependencies
*/
-import { useContext, useEffect, useState, useMemo } from '@wordpress/element';
+import {
+ useContext,
+ useEffect,
+ useState,
+ useMemo,
+ createInterpolateElement,
+} from '@wordpress/element';
import {
__experimentalSpacer as Spacer,
__experimentalInputControl as InputControl,
__experimentalText as Text,
+ __experimentalHStack as HStack,
SelectControl,
Spinner,
Icon,
@@ -14,7 +21,7 @@ import {
Button,
} from '@wordpress/components';
import { debounce } from '@wordpress/compose';
-import { __, _x } from '@wordpress/i18n';
+import { sprintf, __, _x } from '@wordpress/i18n';
import { search, closeSmall } from '@wordpress/icons';
/**
@@ -22,7 +29,6 @@ import { search, closeSmall } from '@wordpress/icons';
*/
import TabPanelLayout from './tab-panel-layout';
import { FontLibraryContext } from './context';
-import FontsGrid from './fonts-grid';
import FontCard from './font-card';
import filterFonts from './utils/filter-fonts';
import CollectionFontDetails from './collection-font-details';
@@ -48,6 +54,7 @@ function FontCollection( { slug } ) {
const [ selectedFont, setSelectedFont ] = useState( null );
const [ fontsToInstall, setFontsToInstall ] = useState( [] );
+ const [ page, setPage ] = useState( 1 );
const [ filters, setFilters ] = useState( {} );
const [ renderConfirmDialog, setRenderConfirmDialog ] = useState(
requiresPermission && ! getGoogleFontsPermissionFromStorage()
@@ -109,22 +116,34 @@ function FontCollection( { slug } ) {
[ collectionFonts, filters ]
);
+ // NOTE: The height of the font library modal unavailable to use for rendering font family items is roughly 417px
+ // The height of each font family item is 61px.
+ const pageSize = Math.floor( ( window.innerHeight - 417 ) / 61 );
+ const totalPages = Math.ceil( fonts.length / pageSize );
+ const itemsStart = ( page - 1 ) * pageSize;
+ const itemsLimit = page * pageSize;
+ const items = fonts.slice( itemsStart, itemsLimit );
+
const handleCategoryFilter = ( category ) => {
setFilters( { ...filters, category } );
+ setPage( 1 );
};
const handleUpdateSearchInput = ( value ) => {
setFilters( { ...filters, search: value } );
+ setPage( 1 );
};
const debouncedUpdateSearchInput = debounce( handleUpdateSearchInput, 300 );
const resetFilters = () => {
setFilters( {} );
+ setPage( 1 );
};
const resetSearch = () => {
setFilters( { ...filters, search: '' } );
+ setPage( 1 );
};
const handleUnselectFont = () => {
@@ -186,6 +205,24 @@ function FontCollection( { slug } ) {
resetFontsToInstall();
};
+ let footerComponent = null;
+ if ( selectedFont ) {
+ footerComponent = (
+
+ );
+ } else if ( ! renderConfirmDialog && totalPages > 1 ) {
+ footerComponent = (
+
+ );
+ }
+
return (
- }
+ footer={ footerComponent }
>
{ renderConfirmDialog && (
<>
@@ -275,8 +307,8 @@ function FontCollection( { slug } ) {
) }
{ ! renderConfirmDialog && ! selectedFont && (
-
- { fonts.map( ( font ) => (
+
+ { items.map( ( font ) => (
) ) }
-
+
) }
);
}
-function Footer( { handleInstall, isDisabled } ) {
+function PaginationFooter( { page, totalPages, setPage } ) {
+ return (
+
+ setPage( 1 ) }
+ disabled={ page === 1 }
+ __experimentalIsFocusable
+ >
+ «
+
+ setPage( page - 1 ) }
+ disabled={ page === 1 }
+ __experimentalIsFocusable
+ >
+ ‹
+
+
+ { createInterpolateElement(
+ sprintf(
+ // translators: %s: Total number of pages.
+ _x( 'Page of %s', 'paging' ),
+ totalPages
+ ),
+ {
+ CurrenPageControl: (
+ {
+ return {
+ label: i + 1,
+ value: i + 1,
+ };
+ }
+ ) }
+ onChange={ ( newPage ) =>
+ setPage( parseInt( newPage ) )
+ }
+ size={ 'compact' }
+ __nextHasNoMarginBottom
+ />
+ ),
+ }
+ ) }
+
+ setPage( page + 1 ) }
+ disabled={ page === totalPages }
+ __experimentalIsFocusable
+ >
+ ›
+
+ setPage( totalPages ) }
+ disabled={ page === totalPages }
+ __experimentalIsFocusable
+ >
+ »
+
+
+ );
+}
+
+function InstallFooter( { handleInstall, isDisabled } ) {
const { isInstalling } = useContext( FontLibraryContext );
return (
diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js b/packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js
deleted file mode 100644
index 9700831a7adef1..00000000000000
--- a/packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * WordPress dependencies
- */
-import {
- __experimentalVStack as VStack,
- __experimentalText as Text,
- __experimentalSpacer as Spacer,
-} from '@wordpress/components';
-import { useState, useEffect } from '@wordpress/element';
-
-function FontsGrid( { title, children, pageSize = 32 } ) {
- const [ lastItem, setLastItem ] = useState( null );
- const [ page, setPage ] = useState( 1 );
- const itemsLimit = page * pageSize;
- const items = children.slice( 0, itemsLimit );
-
- useEffect( () => {
- if ( lastItem ) {
- const observer = new window.IntersectionObserver( ( [ entry ] ) => {
- if ( entry.isIntersecting ) {
- setPage( ( prevPage ) => prevPage + 1 );
- }
- } );
-
- observer.observe( lastItem );
-
- return () => observer.disconnect();
- }
- }, [ lastItem ] );
-
- return (
-
-
- { title && (
- <>
-
- { title }
-
-
- >
- ) }
-
- { items.map( ( child, i ) => {
- if ( i === itemsLimit - 1 ) {
- return (
-
- { child }
-
- );
- }
- return
{ child }
;
- } ) }
-
-
-
- );
-}
-
-export default FontsGrid;
diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js b/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js
index 67140fbe4d0d93..dde6dc87c858ac 100644
--- a/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js
+++ b/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js
@@ -24,7 +24,7 @@ function GoogleFontsConfirmDialog() {
- Connect to Google Fonts
+ { __( 'Connect to Google Fonts' ) }
{ __(
diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js
index 73ff17f25b9a66..99c99e44a43afc 100644
--- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js
+++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js
@@ -7,6 +7,7 @@ import {
privateApis as componentsPrivateApis,
__experimentalHStack as HStack,
__experimentalSpacer as Spacer,
+ __experimentalText as Text,
Button,
Spinner,
FlexItem,
@@ -17,7 +18,6 @@ import {
*/
import TabPanelLayout from './tab-panel-layout';
import { FontLibraryContext } from './context';
-import FontsGrid from './fonts-grid';
import LibraryFontDetails from './library-font-details';
import LibraryFontCard from './library-font-card';
import ConfirmDeleteDialog from './confirm-delete-dialog';
@@ -123,36 +123,38 @@ function InstalledFonts() {
) }
{ baseCustomFonts.length > 0 && (
<>
-
- { baseCustomFonts.map( ( font ) => (
- {
- handleSelectFont( font );
- } }
- />
- ) ) }
-
+ { baseCustomFonts.map( ( font ) => (
+ {
+ handleSelectFont( font );
+ } }
+ />
+ ) ) }
>
) }
{ baseThemeFonts.length > 0 && (
<>
-
- { baseThemeFonts.map( ( font ) => (
- {
- handleSelectFont( font );
- } }
- />
- ) ) }
-
+
+ { __( 'Theme Fonts' ) }
+
+
+
+ { baseThemeFonts.map( ( font ) => (
+ {
+ handleSelectFont( font );
+ } }
+ />
+ ) ) }
>
) }
+
>
) }
diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss
index beb1ba46714ff7..544e3ed63c9883 100644
--- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss
+++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss
@@ -36,11 +36,8 @@
}
}
-.font-library-modal__fonts-grid {
- .font-library-modal__fonts-grid__main {
- display: flex;
- flex-direction: column;
- }
+.font-library-modal__tabpanel-layout .components-base-control__field {
+ margin-bottom: 0;
}
.font-library-modal__font-card {
diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js
index 163d4fe6e938ff..65dfb71949a7f5 100644
--- a/packages/edit-site/src/components/layout/index.js
+++ b/packages/edit-site/src/components/layout/index.js
@@ -251,47 +251,64 @@ export default function Layout() {
The NavigableRegion must always be rendered and not use
`inert` otherwise `useNavigateRegions` will fail.
*/ }
-
-
- { canvasMode === 'view' && (
-
-
-
- ) }
-
-
+ { ( ! isMobileViewport ||
+ ( isMobileViewport && ! areas.mobile ) ) && (
+
+
+ { canvasMode === 'view' && (
+
+
+
+ ) }
+
+
+ ) }
- { areas.content && canvasMode !== 'edit' && (
+ { isMobileViewport && areas.mobile && (
- { areas.content }
+ { areas.mobile }
) }
- { areas.preview && (
+ { ! isMobileViewport &&
+ areas.content &&
+ canvasMode !== 'edit' && (
+
+ { areas.content }
+
+ ) }
+
+ { ! isMobileViewport && areas.preview && (
{ canvasResizer }
{ !! canvasSize.width && (
diff --git a/packages/edit-site/src/components/layout/router.js b/packages/edit-site/src/components/layout/router.js
index aeb124bf76fe5f..02f7e7b25594ae 100644
--- a/packages/edit-site/src/components/layout/router.js
+++ b/packages/edit-site/src/components/layout/router.js
@@ -23,13 +23,21 @@ const { useLocation } = unlock( routerPrivateApis );
export default function useLayoutAreas() {
const isSiteEditorLoading = useIsSiteEditorLoading();
const { params } = useLocation();
- const { postType, postId, path, layout, isCustom } = params ?? {};
+ const { postType, postId, path, layout, isCustom, canvas } = params ?? {};
+
+ // Note: Since "sidebar" is not yet supported here,
+ // returning undefined from "mobile" means show the sidebar.
+
// Regular page
if ( path === '/page' ) {
return {
areas: {
content: undefined,
preview:
,
+ mobile:
+ canvas === 'edit' ? (
+
+ ) : undefined,
},
widths: {
content: undefined,
@@ -63,6 +71,10 @@ export default function useLayoutAreas() {
return {
areas: {
preview:
,
+ mobile:
+ canvas === 'edit' ? (
+
+ ) : undefined,
},
};
}
@@ -79,6 +91,11 @@ export default function useLayoutAreas() {
preview: isListLayout && (
),
+ mobile: (
+
+ ),
},
widths: {
content: isListLayout ? 380 : undefined,
@@ -98,6 +115,11 @@ export default function useLayoutAreas() {
preview: isListLayout && (
),
+ mobile: (
+
+ ),
},
widths: {
content: isListLayout ? 380 : undefined,
@@ -110,12 +132,19 @@ export default function useLayoutAreas() {
return {
areas: {
content:
,
+ mobile:
,
},
};
}
// Fallback shows the home page preview
return {
- areas: { preview:
},
+ areas: {
+ preview:
,
+ mobile:
+ canvas === 'edit' ? (
+
+ ) : undefined,
+ },
};
}
diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss
index 9be0b001ed9e25..ad33768989a81b 100644
--- a/packages/edit-site/src/components/layout/style.scss
+++ b/packages/edit-site/src/components/layout/style.scss
@@ -83,6 +83,12 @@
flex-direction: column;
}
+.edit-site-layout__mobile {
+ position: relative;
+ width: 100%;
+ z-index: z-index(".edit-site-layout__canvas-container");
+}
+
.edit-site-layout__canvas-container {
position: relative;
flex-grow: 1;
@@ -147,6 +153,7 @@
}
// This shouldn't be necessary (we should have a way to say that a skeletton is relative
+.edit-site-layout__mobile .interface-interface-skeleton,
.edit-site-layout__canvas .interface-interface-skeleton,
.edit-site-template-pages-preview .interface-interface-skeleton {
position: relative !important;
diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss
index e5bd44956b2629..dd32818edd614b 100644
--- a/packages/edit-site/src/components/page-patterns/style.scss
+++ b/packages/edit-site/src/components/page-patterns/style.scss
@@ -225,6 +225,12 @@
* TODO: when this becomes stable, consolidate styles with the above.
*/
.edit-site-page-patterns-dataviews {
+ margin-top: 60px;
+
+ @include break-medium {
+ margin-top: 0;
+ }
+
.page-patterns-preview-field {
display: flex;
flex-direction: column;
@@ -283,6 +289,10 @@
text-overflow: ellipsis;
color: inherit;
}
+
+ .dataviews-pagination {
+ z-index: z-index(".edit-site-patterns__dataviews-list-pagination");
+ }
}
.dataviews-action-modal__duplicate-pattern {
diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js
index a0b82247c85a6d..b099b70b36fe1a 100644
--- a/packages/edit-site/src/components/page-patterns/use-patterns.js
+++ b/packages/edit-site/src/components/page-patterns/use-patterns.js
@@ -111,6 +111,7 @@ const selectTemplatePartsAsPatterns = createSelector(
const selectThemePatterns = createSelector(
( select ) => {
const { getSettings } = unlock( select( editSiteStore ) );
+ const { getIsResolving } = select( coreStore );
const settings = getSettings();
const blockPatterns =
settings.__experimentalAdditionalBlockPatterns ??
@@ -136,19 +137,23 @@ const selectThemePatterns = createSelector(
__unstableSkipMigrationLogs: true,
} ),
} ) );
-
- return { patterns, isResolving: false };
+ return { patterns, isResolving: getIsResolving( 'getBlockPatterns' ) };
},
( select ) => [
select( coreStore ).getBlockPatterns(),
+ select( coreStore ).getIsResolving( 'getBlockPatterns' ),
unlock( select( editSiteStore ) ).getSettings(),
]
);
const selectPatterns = createSelector(
( select, categoryId, syncStatus, search = '' ) => {
- const { patterns: themePatterns } = selectThemePatterns( select );
- const { patterns: userPatterns } = selectUserPatterns( select );
+ const {
+ patterns: themePatterns,
+ isResolving: isResolvingThemePatterns,
+ } = selectThemePatterns( select );
+ const { patterns: userPatterns, isResolving: isResolvingUserPatterns } =
+ selectUserPatterns( select );
let patterns = [
...( themePatterns || [] ),
@@ -176,7 +181,10 @@ const selectPatterns = createSelector(
hasCategory: ( item ) => ! item.hasOwnProperty( 'categories' ),
} );
}
- return { patterns, isResolving: false };
+ return {
+ patterns,
+ isResolving: isResolvingThemePatterns || isResolvingUserPatterns,
+ };
},
( select ) => [
selectThemePatterns( select ),
diff --git a/packages/edit-site/src/components/page-templates-template-parts/index.js b/packages/edit-site/src/components/page-templates-template-parts/index.js
index 514ff148071955..9089d31cd66e0a 100644
--- a/packages/edit-site/src/components/page-templates-template-parts/index.js
+++ b/packages/edit-site/src/components/page-templates-template-parts/index.js
@@ -429,6 +429,7 @@ export default function PageTemplatesTemplateParts( { postType } ) {
return (
{
};
export default function SidebarNavigationScreenPages() {
+ const isMobileViewport = useViewportMatch( 'medium', '<' );
const { records: pages, isResolving: isLoadingPages } = useEntityRecords(
'postType',
'page',
@@ -220,12 +222,14 @@ export default function SidebarNavigationScreenPages() {
) ) }
-
- { __( 'Manage all pages' ) }
-
+ { ! isMobileViewport && (
+
+ { __( 'Manage all pages' ) }
+
+ ) }
}
/>
diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js
index 84a89957b475d5..56107edc63c863 100644
--- a/packages/edit-site/src/components/sidebar/index.js
+++ b/packages/edit-site/src/components/sidebar/index.js
@@ -13,6 +13,7 @@ import {
} from '@wordpress/components';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { __ } from '@wordpress/i18n';
+import { useViewportMatch } from '@wordpress/compose';
/**
* Internal dependencies
@@ -52,6 +53,7 @@ function SidebarScreenWrapper( { className, ...props } ) {
function SidebarScreens() {
useSyncPathWithURL();
+ const isMobileViewport = useViewportMatch( 'medium', '<' );
return (
<>
@@ -82,9 +84,11 @@ function SidebarScreens() {
-
-
-
+ { ! isMobileViewport && (
+
+
+
+ ) }
diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js
index 930e89c6254102..fd23903a6a05e4 100644
--- a/packages/edit-site/src/store/private-actions.js
+++ b/packages/edit-site/src/store/private-actions.js
@@ -22,6 +22,8 @@ import { TEMPLATE_POST_TYPE } from '../utils/constants';
export const setCanvasMode =
( mode ) =>
( { registry, dispatch } ) => {
+ const isMediumOrBigger =
+ window.matchMedia( '(min-width: 782px)' ).matches;
registry.dispatch( blockEditorStore ).__unstableSetEditorMode( 'edit' );
dispatch( {
type: 'SET_CANVAS_MODE',
@@ -29,7 +31,9 @@ export const setCanvasMode =
} );
// Check if the block list view should be open by default.
// If `distractionFree` mode is enabled, the block list view should not be open.
+ // This behavior is disabled for small viewports.
if (
+ isMediumOrBigger &&
mode === 'edit' &&
registry
.select( preferencesStore )
diff --git a/packages/editor/src/components/document-tools/index.js b/packages/editor/src/components/document-tools/index.js
index 05907654fa9b84..26adcb1bb725a7 100644
--- a/packages/editor/src/components/document-tools/index.js
+++ b/packages/editor/src/components/document-tools/index.js
@@ -46,6 +46,7 @@ function DocumentTools( {
const { setIsInserterOpened, setIsListViewOpened } =
useDispatch( editorStore );
const {
+ isDistractionFree,
isInserterOpened,
isListViewOpen,
listViewShortcut,
@@ -69,6 +70,7 @@ function DocumentTools( {
listViewToggleRef: getListViewToggleRef(),
hasFixedToolbar: getSettings().hasFixedToolbar,
showIconLabels: get( 'core', 'showIconLabels' ),
+ isDistractionFree: get( 'core', 'distractionFree' ),
};
}, [] );
@@ -158,22 +160,26 @@ function DocumentTools( {
variant={ showIconLabels ? 'tertiary' : undefined }
size="compact"
/>
-
+ { ! isDistractionFree && (
+
+ ) }
>
) }
{ children }
diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js
index 164f925743522c..d8973850111d1b 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -7,12 +7,12 @@ import {
store as coreStore,
__experimentalFetchLinkSuggestions as fetchLinkSuggestions,
__experimentalFetchUrlData as fetchUrlData,
- fetchBlockPatterns,
} from '@wordpress/core-data';
import { __ } from '@wordpress/i18n';
import { store as preferencesStore } from '@wordpress/preferences';
import { useViewportMatch } from '@wordpress/compose';
import { store as blocksStore } from '@wordpress/blocks';
+import { privateApis } from '@wordpress/block-editor';
/**
* Internal dependencies
@@ -20,6 +20,7 @@ import { store as blocksStore } from '@wordpress/blocks';
import inserterMediaCategories from '../media-categories';
import { mediaUpload } from '../../utils';
import { store as editorStore } from '../../store';
+import { unlock } from '../../lock-unlock';
const EMPTY_BLOCKS_LIST = [];
@@ -247,17 +248,10 @@ function useBlockEditorSettings( settings, postType, postId ) {
keepCaretInsideBlock,
mediaUpload: hasUploadPermissions ? mediaUpload : undefined,
__experimentalBlockPatterns: blockPatterns,
- __experimentalFetchBlockPatterns: async () => {
- return ( await fetchBlockPatterns() ).filter(
- ( { postTypes } ) => {
- return (
- ! postTypes ||
- ( Array.isArray( postTypes ) &&
- postTypes.includes( postType ) )
- );
- }
- );
- },
+ [ unlock( privateApis ).selectBlockPatternsKey ]: ( select ) =>
+ unlock( select( coreStore ) ).getBlockPatternsForPostType(
+ postType
+ ),
__experimentalReusableBlocks: reusableBlocks,
__experimentalBlockPatternCategories: blockPatternCategories,
__experimentalUserPatternCategories: userPatternCategories,
diff --git a/packages/patterns/src/components/create-pattern-modal.js b/packages/patterns/src/components/create-pattern-modal.js
index 137c14222ced34..9576e50309e237 100644
--- a/packages/patterns/src/components/create-pattern-modal.js
+++ b/packages/patterns/src/components/create-pattern-modal.js
@@ -10,21 +10,17 @@ import {
ToggleControl,
} from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';
-import { useState, useMemo } from '@wordpress/element';
-import { useDispatch, useSelect } from '@wordpress/data';
+import { useState } from '@wordpress/element';
+import { useDispatch } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
-import { store as coreStore } from '@wordpress/core-data';
/**
* Internal dependencies
*/
import { PATTERN_DEFAULT_CATEGORY, PATTERN_SYNC_TYPES } from '../constants';
-
-/**
- * Internal dependencies
- */
import { store as patternsStore } from '../store';
-import CategorySelector, { CATEGORY_SLUG } from './category-selector';
+import CategorySelector from './category-selector';
+import { useAddPatternCategory } from '../private-hooks';
import { unlock } from '../lock-unlock';
export default function CreatePatternModal( {
@@ -59,47 +55,9 @@ export function CreatePatternModalContents( {
const [ isSaving, setIsSaving ] = useState( false );
const { createPattern } = unlock( useDispatch( patternsStore ) );
- const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore );
const { createErrorNotice } = useDispatch( noticesStore );
- const { corePatternCategories, userPatternCategories } = useSelect(
- ( select ) => {
- const { getUserPatternCategories, getBlockPatternCategories } =
- select( coreStore );
-
- return {
- corePatternCategories: getBlockPatternCategories(),
- userPatternCategories: getUserPatternCategories(),
- };
- }
- );
-
- const categoryMap = useMemo( () => {
- // Merge the user and core pattern categories and remove any duplicates.
- const uniqueCategories = new Map();
- userPatternCategories.forEach( ( category ) => {
- uniqueCategories.set( category.label.toLowerCase(), {
- label: category.label,
- name: category.name,
- id: category.id,
- } );
- } );
-
- corePatternCategories.forEach( ( category ) => {
- if (
- ! uniqueCategories.has( category.label.toLowerCase() ) &&
- // There are two core categories with `Post` label so explicitly remove the one with
- // the `query` slug to avoid any confusion.
- category.name !== 'query'
- ) {
- uniqueCategories.set( category.label.toLowerCase(), {
- label: category.label,
- name: category.name,
- } );
- }
- } );
- return uniqueCategories;
- }, [ userPatternCategories, corePatternCategories ] );
+ const { categoryMap, findOrCreateTerm } = useAddPatternCategory();
async function onCreate( patternTitle, sync ) {
if ( ! title || isSaving ) {
@@ -137,38 +95,6 @@ export function CreatePatternModalContents( {
}
}
- /**
- * @param {string} term
- * @return {Promise} The pattern category id.
- */
- async function findOrCreateTerm( term ) {
- try {
- const existingTerm = categoryMap.get( term.toLowerCase() );
- if ( existingTerm && existingTerm.id ) {
- return existingTerm.id;
- }
- // If we have an existing core category we need to match the new user category to the
- // correct slug rather than autogenerating it to prevent duplicates, eg. the core `Headers`
- // category uses the singular `header` as the slug.
- const termData = existingTerm
- ? { name: existingTerm.label, slug: existingTerm.name }
- : { name: term };
- const newTerm = await saveEntityRecord(
- 'taxonomy',
- CATEGORY_SLUG,
- termData,
- { throwOnError: true }
- );
- invalidateResolution( 'getUserPatternCategories' );
- return newTerm.id;
- } catch ( error ) {
- if ( error.code !== 'term_exists' ) {
- throw error;
- }
-
- return error.data.term_id;
- }
- }
return (