diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js
new file mode 100644
index 0000000000000..eab6dbca32833
--- /dev/null
+++ b/packages/edit-site/src/components/page-patterns/fields.js
@@ -0,0 +1,251 @@
+/**
+ * External dependencies
+ */
+import clsx from 'clsx';
+
+/**
+ * WordPress dependencies
+ */
+import {
+ __experimentalHStack as HStack,
+ Button,
+ Tooltip,
+ Flex,
+} from '@wordpress/components';
+import { __, _x } from '@wordpress/i18n';
+import { useState, useMemo, useId } from '@wordpress/element';
+import {
+ BlockPreview,
+ privateApis as blockEditorPrivateApis,
+} from '@wordpress/block-editor';
+import { Icon, lockSmall } from '@wordpress/icons';
+import { parse } from '@wordpress/blocks';
+import { decodeEntities } from '@wordpress/html-entities';
+
+/**
+ * Internal dependencies
+ */
+import { Async } from '../async';
+import {
+ PATTERN_TYPES,
+ TEMPLATE_PART_POST_TYPE,
+ PATTERN_SYNC_TYPES,
+ OPERATOR_IS,
+} from '../../utils/constants';
+import { unlock } from '../../lock-unlock';
+import { useLink } from '../routes/link';
+import { useAddedBy } from '../page-templates/hooks';
+import { defaultGetTitle } from './search-items';
+
+const { useGlobalStyle } = unlock( blockEditorPrivateApis );
+
+function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) {
+ return (
+
+ );
+}
+
+function PreviewField( { item } ) {
+ const descriptionId = useId();
+ const description = item.description || item?.excerpt?.raw;
+ const isUserPattern = item.type === PATTERN_TYPES.user;
+ const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
+ const [ backgroundColor ] = useGlobalStyle( 'color.background' );
+ const { onClick } = useLink( {
+ postType: item.type,
+ postId: isUserPattern || isTemplatePart ? item.id : item.name,
+ canvas: 'edit',
+ } );
+ const blocks = useMemo( () => {
+ return (
+ item.blocks ??
+ parse( item.content.raw, {
+ __unstableSkipMigrationLogs: true,
+ } )
+ );
+ }, [ item?.content?.raw, item.blocks ] );
+ const isEmpty = ! blocks?.length;
+
+ return (
+
+
+ { isEmpty && isTemplatePart && __( 'Empty template part' ) }
+ { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) }
+ { ! isEmpty && (
+
+
+
+ ) }
+
+ { !! description && (
+
+ { description }
+
+ ) }
+
+ );
+}
+
+export const previewField = {
+ label: __( 'Preview' ),
+ id: 'preview',
+ render: PreviewField,
+ enableSorting: false,
+};
+
+function TitleField( { item } ) {
+ const isUserPattern = item.type === PATTERN_TYPES.user;
+ const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
+ const { onClick } = useLink( {
+ postType: item.type,
+ postId: isUserPattern || isTemplatePart ? item.id : item.name,
+ canvas: 'edit',
+ } );
+ const title = decodeEntities( defaultGetTitle( item ) );
+ return (
+
+
+ { item.type === PATTERN_TYPES.theme ? (
+ title
+ ) : (
+
+ ) }
+
+ { item.type === PATTERN_TYPES.theme && (
+
+
+
+ ) }
+
+ );
+}
+
+export const titleField = {
+ label: __( 'Title' ),
+ id: 'title',
+ getValue: ( { item } ) => item.title?.raw || item.title,
+ render: TitleField,
+ enableHiding: false,
+};
+
+const SYNC_FILTERS = [
+ {
+ value: PATTERN_SYNC_TYPES.full,
+ label: _x( 'Synced', 'pattern (singular)' ),
+ description: __( 'Patterns that are kept in sync across the site.' ),
+ },
+ {
+ value: PATTERN_SYNC_TYPES.unsynced,
+ label: _x( 'Not synced', 'pattern (singular)' ),
+ description: __(
+ 'Patterns that can be changed freely without affecting the site.'
+ ),
+ },
+];
+
+export const patternStatusField = {
+ label: __( 'Sync status' ),
+ id: 'sync-status',
+ render: ( { item } ) => {
+ const syncStatus =
+ 'wp_pattern_sync_status' in item
+ ? item.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full
+ : PATTERN_SYNC_TYPES.unsynced;
+ // User patterns can have their sync statuses checked directly.
+ // Non-user patterns are all unsynced for the time being.
+ return (
+
+ {
+ SYNC_FILTERS.find( ( { value } ) => value === syncStatus )
+ .label
+ }
+
+ );
+ },
+ elements: SYNC_FILTERS,
+ filterBy: {
+ operators: [ OPERATOR_IS ],
+ isPrimary: true,
+ },
+ enableSorting: false,
+};
+
+function AuthorField( { item } ) {
+ const [ isImageLoaded, setIsImageLoaded ] = useState( false );
+ const { text, icon, imageUrl } = useAddedBy( item.type, item.id );
+
+ return (
+
+ { imageUrl && (
+
+
setIsImageLoaded( true ) }
+ alt=""
+ src={ imageUrl }
+ />
+
+ ) }
+ { ! imageUrl && (
+
+
+
+ ) }
+ { text }
+
+ );
+}
+
+export const templatePartAuthorField = {
+ label: __( 'Author' ),
+ id: 'author',
+ getValue: ( { item } ) => item.author_text,
+ render: AuthorField,
+ filterBy: {
+ isPrimary: true,
+ },
+};
diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js
index a0f107e91601b..a8db73272c0ce 100644
--- a/packages/edit-site/src/components/page-patterns/index.js
+++ b/packages/edit-site/src/components/page-patterns/index.js
@@ -1,59 +1,39 @@
-/**
- * External dependencies
- */
-import clsx from 'clsx';
-
/**
* WordPress dependencies
*/
-import {
- __experimentalHStack as HStack,
- Button,
- Tooltip,
- Flex,
-} from '@wordpress/components';
-import { __, _x } from '@wordpress/i18n';
+import { __ } from '@wordpress/i18n';
import { useState, useMemo, useId, useEffect } from '@wordpress/element';
-import {
- BlockPreview,
- privateApis as blockEditorPrivateApis,
-} from '@wordpress/block-editor';
+import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews';
-import { Icon, lockSmall } from '@wordpress/icons';
import { usePrevious } from '@wordpress/compose';
import { useEntityRecords } from '@wordpress/core-data';
import { privateApis as editorPrivateApis } from '@wordpress/editor';
import { privateApis as routerPrivateApis } from '@wordpress/router';
-import { parse } from '@wordpress/blocks';
-import { decodeEntities } from '@wordpress/html-entities';
/**
* Internal dependencies
*/
-import { Async } from '../async';
import Page from '../page';
import {
LAYOUT_GRID,
LAYOUT_TABLE,
- LAYOUT_LIST,
PATTERN_TYPES,
TEMPLATE_PART_POST_TYPE,
- PATTERN_SYNC_TYPES,
PATTERN_DEFAULT_CATEGORY,
- OPERATOR_IS,
} from '../../utils/constants';
import usePatternSettings from './use-pattern-settings';
import { unlock } from '../../lock-unlock';
import usePatterns from './use-patterns';
import PatternsHeader from './header';
-import { useLink } from '../routes/link';
-import { useAddedBy } from '../page-templates/hooks';
import { useEditPostAction } from '../dataviews-actions';
-import { defaultGetTitle } from './search-items';
+import {
+ patternStatusField,
+ previewField,
+ titleField,
+ templatePartAuthorField,
+} from './fields';
-const { ExperimentalBlockEditorProvider, useGlobalStyle } = unlock(
- blockEditorPrivateApis
-);
+const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis );
const { usePostActions } = unlock( editorPrivateApis );
const { useLocation } = unlock( routerPrivateApis );
@@ -90,164 +70,6 @@ const DEFAULT_VIEW = {
filters: [],
};
-const SYNC_FILTERS = [
- {
- value: PATTERN_SYNC_TYPES.full,
- label: _x( 'Synced', 'pattern (singular)' ),
- description: __( 'Patterns that are kept in sync across the site.' ),
- },
- {
- value: PATTERN_SYNC_TYPES.unsynced,
- label: _x( 'Not synced', 'pattern (singular)' ),
- description: __(
- 'Patterns that can be changed freely without affecting the site.'
- ),
- },
-];
-
-function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) {
- return (
-
- );
-}
-
-function Preview( { item, viewType } ) {
- const descriptionId = useId();
- const description = item.description || item?.excerpt?.raw;
- const isUserPattern = item.type === PATTERN_TYPES.user;
- const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
- const [ backgroundColor ] = useGlobalStyle( 'color.background' );
- const { onClick } = useLink( {
- postType: item.type,
- postId: isUserPattern || isTemplatePart ? item.id : item.name,
- canvas: 'edit',
- } );
- const blocks = useMemo( () => {
- return (
- item.blocks ??
- parse( item.content.raw, {
- __unstableSkipMigrationLogs: true,
- } )
- );
- }, [ item?.content?.raw, item.blocks ] );
- const isEmpty = ! blocks?.length;
-
- return (
-
-
- { isEmpty && isTemplatePart && __( 'Empty template part' ) }
- { isEmpty && ! isTemplatePart && __( 'Empty pattern' ) }
- { ! isEmpty && (
-
-
-
- ) }
-
- { !! description && (
-
- { description }
-
- ) }
-
- );
-}
-
-function Author( { item, viewType } ) {
- const [ isImageLoaded, setIsImageLoaded ] = useState( false );
- const { text, icon, imageUrl } = useAddedBy( item.type, item.id );
- const withIcon = viewType !== LAYOUT_LIST;
-
- return (
-
- { withIcon && imageUrl && (
-
-
setIsImageLoaded( true ) }
- alt=""
- src={ imageUrl }
- />
-
- ) }
- { withIcon && ! imageUrl && (
-
-
-
- ) }
- { text }
-
- );
-}
-
-function Title( { item } ) {
- const isUserPattern = item.type === PATTERN_TYPES.user;
- const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
- const { onClick } = useLink( {
- postType: item.type,
- postId: isUserPattern || isTemplatePart ? item.id : item.name,
- canvas: 'edit',
- } );
- const title = decodeEntities( defaultGetTitle( item ) );
- return (
-
-
- { item.type === PATTERN_TYPES.theme ? (
- title
- ) : (
-
- ) }
-
- { item.type === PATTERN_TYPES.theme && (
-
-
-
- ) }
-
- );
-}
-
export default function DataviewsPatterns() {
const {
params: { postType, categoryId: categoryIdFromURL },
@@ -267,6 +89,7 @@ export default function DataviewsPatterns() {
const { records } = useEntityRecords( 'postType', TEMPLATE_PART_POST_TYPE, {
per_page: -1,
} );
+
const authors = useMemo( () => {
if ( ! records ) {
return EMPTY_ARRAY;
@@ -282,72 +105,19 @@ export default function DataviewsPatterns() {
}, [ records ] );
const fields = useMemo( () => {
- const _fields = [
- {
- label: __( 'Preview' ),
- id: 'preview',
- render: ( { item } ) => (
-
- ),
- enableSorting: false,
- },
- {
- label: __( 'Title' ),
- id: 'title',
- getValue: ( { item } ) => item.title?.raw || item.title,
- render: ( { item } ) => ,
- enableHiding: false,
- },
- ];
+ const _fields = [ previewField, titleField ];
if ( type === PATTERN_TYPES.user ) {
- _fields.push( {
- label: __( 'Sync status' ),
- id: 'sync-status',
- render: ( { item } ) => {
- const syncStatus =
- 'wp_pattern_sync_status' in item
- ? item.wp_pattern_sync_status ||
- PATTERN_SYNC_TYPES.full
- : PATTERN_SYNC_TYPES.unsynced;
- // User patterns can have their sync statuses checked directly.
- // Non-user patterns are all unsynced for the time being.
- return (
-
- {
- SYNC_FILTERS.find(
- ( { value } ) => value === syncStatus
- ).label
- }
-
- );
- },
- elements: SYNC_FILTERS,
- filterBy: {
- operators: [ OPERATOR_IS ],
- isPrimary: true,
- },
- enableSorting: false,
- } );
+ _fields.push( patternStatusField );
} else if ( type === TEMPLATE_PART_POST_TYPE ) {
_fields.push( {
- label: __( 'Author' ),
- id: 'author',
- getValue: ( { item } ) => item.author_text,
- render: ( { item } ) => {
- return ;
- },
+ ...templatePartAuthorField,
elements: authors,
- filterBy: {
- isPrimary: true,
- },
} );
}
return _fields;
- }, [ view.type, type, authors ] );
+ }, [ type, authors ] );
// Reset the page number when the category changes.
useEffect( () => {
diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss
index 2014d3b94fdae..f457624d100c1 100644
--- a/packages/edit-site/src/components/page-patterns/style.scss
+++ b/packages/edit-site/src/components/page-patterns/style.scss
@@ -1,118 +1,114 @@
-.edit-site-patterns__section-header {
- .screen-reader-shortcut:focus {
- top: 0;
- }
+.edit-site-patterns__delete-modal {
+ width: $modal-width-small;
}
-.edit-site-patterns__pattern-title {
- .is-link {
- text-decoration: none;
- color: $gray-200;
+.page-patterns-preview-field {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
- &:hover,
- &:focus {
- color: $white;
+ .dataviews-view-table & {
+ width: 96px;
+ flex-grow: 0;
+ border-radius: 2px;
+
+ .page-patterns-preview-field__button {
+ border-radius: 2px;
}
}
- .edit-site-patterns__pattern-icon {
+ .page-patterns-preview-field__button {
+ box-shadow: none;
+ border: none;
+ padding: 0;
+ background-color: unset;
+ box-sizing: border-box;
+ cursor: pointer;
+ overflow: hidden;
+ height: 100%;
border-radius: $grid-unit-05;
- background: var(--wp-block-synced-color);
- fill: $white;
- }
- .edit-site-patterns__pattern-lock-icon {
- fill: currentcolor;
+ &:focus-visible {
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
+ // Windows High Contrast mode will show this outline, but not the box-shadow.
+ outline: 2px solid transparent;
+ }
+
+ &[aria-disabled="true"] {
+ cursor: default;
+ }
}
}
-.edit-site-patterns__delete-modal {
- width: $modal-width-small;
+.edit-site-patterns__pattern-icon {
+ fill: var(--wp-block-synced-color);
+ flex-shrink: 0;
}
-.edit-site-page-patterns-dataviews {
- .page-patterns-preview-field {
- display: flex;
- flex-direction: column;
- height: 100%;
-
- &.is-viewtype-table {
- width: 96px;
- flex-grow: 0;
- border-radius: 2px;
+.edit-site-patterns__pattern-lock-icon {
+ min-width: min-content;
+}
- .page-patterns-preview-field__button {
- border-radius: 2px;
- }
- }
+.edit-site-patterns__section-header {
+ border-bottom: 1px solid #f0f0f0;
+ padding: $grid-unit-20 $grid-unit-60;
+ position: sticky;
+ top: 0;
+ z-index: 2;
+ flex-shrink: 0;
+ transition: padding ease-out 0.1s;
+ @include reduce-motion("transition");
+ min-height: $grid-unit-50;
+
+ .edit-site-patterns__title {
+ min-height: $grid-unit-50;
- .page-patterns-preview-field__button {
- box-shadow: none;
- border: none;
- padding: 0;
- background-color: unset;
- box-sizing: border-box;
- cursor: pointer;
- overflow: hidden;
- height: 100%;
- border-radius: $grid-unit-05;
-
- &:focus-visible {
- box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
- // Windows High Contrast mode will show this outline, but not the box-shadow.
- outline: 2px solid transparent;
- }
-
- &[aria-disabled="true"] {
- cursor: default;
- }
+ .components-heading {
+ flex-grow: 1;
+ flex-basis: 0;
+ white-space: nowrap;
}
}
- .edit-site-patterns__pattern-icon {
- fill: var(--wp-block-synced-color);
- flex-shrink: 0;
+ .edit-site-patterns__sub-title {
+ margin-bottom: $grid-unit-10;
}
- .edit-site-patterns__pattern-lock-icon {
- min-width: min-content;
+ .screen-reader-shortcut:focus {
+ top: 0;
}
+}
- .edit-site-patterns__section-header {
- border-bottom: 1px solid #f0f0f0;
- padding: $grid-unit-20 $grid-unit-60;
- position: sticky;
- top: 0;
- z-index: 2;
- flex-shrink: 0;
- transition: padding ease-out 0.1s;
- @include reduce-motion("transition");
- min-height: $grid-unit-50;
+.edit-site-patterns__pattern-title {
+ display: block;
+ width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: inherit;
- .edit-site-patterns__title {
- min-height: $grid-unit-50;
+ .is-link {
+ text-decoration: none;
+ color: $gray-200;
- .components-heading {
- flex-grow: 1;
- flex-basis: 0;
- white-space: nowrap;
- }
+ &:hover,
+ &:focus {
+ color: $white;
}
+ }
- .edit-site-patterns__sub-title {
- margin-bottom: $grid-unit-10;
- }
+ .edit-site-patterns__pattern-icon {
+ border-radius: $grid-unit-05;
+ background: var(--wp-block-synced-color);
+ fill: $white;
}
- .edit-site-patterns__pattern-title {
- display: block;
- width: 100%;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- color: inherit;
+ .edit-site-patterns__pattern-lock-icon {
+ fill: currentcolor;
}
+}
+.edit-site-page-patterns-dataviews {
.dataviews-pagination {
z-index: z-index(".edit-site-patterns__dataviews-list-pagination");
}