From 785085b254e46fc6596a429e89a0e7ba215ae355 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 14 Aug 2024 11:11:21 +0200 Subject: [PATCH 01/59] Page Edit View: Implement Featured image page field --- .../dataform/stories/index.story.tsx | 7 ++ .../dataviews/src/dataform-controls/image.tsx | 71 +++++++++++++++++++ .../dataviews/src/dataform-controls/index.tsx | 2 + packages/dataviews/src/field-types/image.tsx | 9 +++ packages/dataviews/src/field-types/index.tsx | 5 ++ packages/dataviews/src/types.ts | 2 +- .../src/components/post-edit/index.js | 8 ++- .../src/components/post-fields/index.js | 69 +++++++++++------- .../sidebar-dataviews/default-views.js | 6 +- 9 files changed, 148 insertions(+), 31 deletions(-) create mode 100644 packages/dataviews/src/dataform-controls/image.tsx create mode 100644 packages/dataviews/src/field-types/image.tsx diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 7147b9c2342638..101e3e8eccf46b 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -76,6 +76,11 @@ const fields = [ { value: 'published', label: 'Published' }, ], }, + { + id: 'image', + label: 'Image', + type: 'image' as const, + }, ]; export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { @@ -87,6 +92,7 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { reviewer: 'fulano', date: '2021-01-01T12:00:00', birthdate: '1950-02-23T12:00:00', + image: 'https://picsum.photos/200', } ); const form = { @@ -98,6 +104,7 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { 'status', 'date', 'birthdate', + 'image', ], }; diff --git a/packages/dataviews/src/dataform-controls/image.tsx b/packages/dataviews/src/dataform-controls/image.tsx new file mode 100644 index 00000000000000..d13e0dbe87c7f8 --- /dev/null +++ b/packages/dataviews/src/dataform-controls/image.tsx @@ -0,0 +1,71 @@ +/** + * WordPress dependencies + */ +import { + Button, + FormFileUpload, + __experimentalHStack as HStack, +} from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../types'; + +export default function Image< Item >( { + data, + field, + onChange, +}: DataFormControlProps< Item > ) { + const { id } = field; + const value = field.getValue( { item: data } ); + + const onChangeControl = useCallback( + ( newValue: string ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + return ( +
+ { value && ( + + ) } + + { + if ( event.target.files?.length ) { + const objectUrl = URL.createObjectURL( + event.target.files[ 0 ] + ); + onChangeControl( objectUrl ); + } + } } + > + + + { value && ( + + ) } + +
+ ); +} diff --git a/packages/dataviews/src/dataform-controls/index.tsx b/packages/dataviews/src/dataform-controls/index.tsx index 297e73c28f837c..600d7c256314c6 100644 --- a/packages/dataviews/src/dataform-controls/index.tsx +++ b/packages/dataviews/src/dataform-controls/index.tsx @@ -16,6 +16,7 @@ import integer from './integer'; import radio from './radio'; import select from './select'; import text from './text'; +import image from './image'; interface FormControls { [ key: string ]: ComponentType< DataFormControlProps< any > >; @@ -27,6 +28,7 @@ const FORM_CONTROLS: FormControls = { radio, select, text, + image, }; export function getControl< Item >( diff --git a/packages/dataviews/src/field-types/image.tsx b/packages/dataviews/src/field-types/image.tsx new file mode 100644 index 00000000000000..b95a12dde80a9f --- /dev/null +++ b/packages/dataviews/src/field-types/image.tsx @@ -0,0 +1,9 @@ +/** + * Internal dependencies + */ + +export default { + sort: () => 0, + isValid: () => true, + Edit: 'image', +}; diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx index eb9dada479c6bf..360311a24e0cbe 100644 --- a/packages/dataviews/src/field-types/index.tsx +++ b/packages/dataviews/src/field-types/index.tsx @@ -5,6 +5,7 @@ import type { FieldType, SortDirection, ValidationContext } from '../types'; import { default as integer } from './integer'; import { default as text } from './text'; import { default as datetime } from './datetime'; +import { default as image } from './image'; /** * @@ -25,6 +26,10 @@ export default function getFieldTypeDefinition( type?: FieldType ) { return datetime; } + if ( 'image' === type ) { + return image; + } + return { sort: ( a: any, b: any, direction: SortDirection ) => { if ( typeof a === 'number' && typeof b === 'number' ) { diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index fa5cec8d7d0320..dba1ed5c35e1aa 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -42,7 +42,7 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type FieldType = 'text' | 'integer' | 'datetime'; +export type FieldType = 'text' | 'integer' | 'datetime' | 'image'; export type ValidationContext = { elements?: Option[]; diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 0ec63589d97673..2bc789b4bdc7d5 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -60,7 +60,13 @@ function PostEditForm( { postType, postId } ) { ); const form = { type: 'panel', - fields: [ 'title', 'status', 'date', 'author', 'comment_status' ], + fields: [ + 'featured_media', + 'title', + 'author', + 'date', + 'comment_status', + ], }; const onChange = ( edits ) => { for ( const id of ids ) { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 9e59b23d61922d..1c8f2d3a4f89a2 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -33,11 +33,12 @@ import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; import { LAYOUT_GRID, LAYOUT_TABLE, - LAYOUT_LIST, OPERATOR_IS_ANY, } from '../../utils/constants'; import { default as Link, useLink } from '../routes/link'; import Media from '../media'; +import { isBlobURL } from '@wordpress/blob'; +import { PostFeaturedImage } from '@wordpress/editor'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. @@ -88,19 +89,13 @@ function FeaturedImage( { item, viewType } ) { postType: item.type, canvas: 'edit', } ); - const hasMedia = !! item.featured_media; + const size = viewType === LAYOUT_GRID ? [ 'large', 'full', 'medium', 'thumbnail' ] : [ 'thumbnail', 'medium', 'large', 'full' ]; - const media = hasMedia ? ( - - ) : null; - const renderButton = viewType !== LAYOUT_LIST && ! isDisabled; + + const renderButton = viewType === LAYOUT_GRID && ! isDisabled; return (
- { media } + + ; ) : ( - media + ) }
); @@ -179,24 +182,38 @@ function usePostFields( viewType ) { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); - const { frontPageId, postsPageId } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); - return { - frontPageId: siteSettings?.page_on_front, - postsPageId: siteSettings?.page_for_posts, - }; - }, [] ); + const { frontPageId, postsPageId, getFeaturedMediaUrl } = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + return { + frontPageId: siteSettings?.page_on_front, + postsPageId: siteSettings?.page_for_posts, + getFeaturedMediaUrl: ( id ) => + getEntityRecord( 'root', 'media', id ), + }; + }, + [] + ); const fields = useMemo( () => [ { - id: 'featured-image', + id: 'featured_media', label: __( 'Featured Image' ), - getValue: ( { item } ) => item.featured_media, - render: ( { item } ) => ( - - ), + type: 'image', + getValue: ( { item } ) => { + const mediaUrl = isBlobURL( item.featured_media ) + ? item.featured_media + : getFeaturedMediaUrl( item.featured_media ) + ?.source_url; + return mediaUrl; + }, + render: ( { item } ) => { + return ( + + ); + }, enableSorting: false, }, { @@ -396,7 +413,7 @@ function usePostFields( viewType ) { ], }, ], - [ authors, viewType, frontPageId, postsPageId ] + [ authors, getFeaturedMediaUrl, viewType, frontPageId, postsPageId ] ); return { diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index e5db492fce17d0..37a090be07822e 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -31,7 +31,7 @@ export const defaultLayouts = { layout: { primaryField: 'title', styles: { - 'featured-image': { + featured_media: { width: '1%', }, title: { @@ -42,14 +42,14 @@ export const defaultLayouts = { }, [ LAYOUT_GRID ]: { layout: { - mediaField: 'featured-image', + mediaField: 'featured_media', primaryField: 'title', }, }, [ LAYOUT_LIST ]: { layout: { primaryField: 'title', - mediaField: 'featured-image', + mediaField: 'featured_media', }, }, }; From f89096391c3ea7b8ee6e3909791e26b925a82690 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 22 Aug 2024 14:49:48 +0200 Subject: [PATCH 02/59] improve flow and style --- packages/base-styles/_z-index.scss | 3 + .../src/components/post-fields/index.js | 245 +++++++++++++----- .../src/components/post-fields/style.scss | 53 ++++ packages/edit-site/src/style.scss | 1 + 4 files changed, 239 insertions(+), 63 deletions(-) create mode 100644 packages/edit-site/src/components/post-fields/style.scss diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 4d5f22e02fa7d1..99b3e6ea18ffdf 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -213,6 +213,9 @@ $z-layers: ( // Ensure quick actions toolbar appear above pagination ".dataviews-bulk-actions-toolbar": 2, + + // Needs to be below media library (.media-model) that has a z-index of 160000. + ".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown": 160000 - 10, ); @function z-index( $key ) { diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 1c8f2d3a4f89a2..d4558cf863f130 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -12,6 +12,7 @@ import { createInterpolateElement, useMemo, useState, + useCallback, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; import { @@ -22,8 +23,16 @@ import { pending, notAllowed, commentAuthorAvatar as authorIcon, + lineSolid, } from '@wordpress/icons'; -import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + Icon, + Placeholder, + Button, + FlexItem, +} from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; @@ -37,8 +46,7 @@ import { } from '../../utils/constants'; import { default as Link, useLink } from '../routes/link'; import Media from '../media'; -import { isBlobURL } from '@wordpress/blob'; -import { PostFeaturedImage } from '@wordpress/editor'; +import { MediaUpload } from '@wordpress/block-editor'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. @@ -82,48 +90,6 @@ const getFormattedDate = ( dateToDisplay ) => getDate( dateToDisplay ) ); -function FeaturedImage( { item, viewType } ) { - const isDisabled = item.status === 'trash'; - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); - - const size = - viewType === LAYOUT_GRID - ? [ 'large', 'full', 'medium', 'thumbnail' ] - : [ 'thumbnail', 'medium', 'large', 'full' ]; - - const renderButton = viewType === LAYOUT_GRID && ! isDisabled; - return ( -
- { renderButton ? ( - - ) : ( - - ) } -
- ); -} - function PostStatusField( { item } ) { const status = STATUSES.find( ( { value } ) => value === item.status ); const label = status?.label || item.status; @@ -198,24 +164,6 @@ function usePostFields( viewType ) { const fields = useMemo( () => [ - { - id: 'featured_media', - label: __( 'Featured Image' ), - type: 'image', - getValue: ( { item } ) => { - const mediaUrl = isBlobURL( item.featured_media ) - ? item.featured_media - : getFeaturedMediaUrl( item.featured_media ) - ?.source_url; - return mediaUrl; - }, - render: ( { item } ) => { - return ( - - ); - }, - enableSorting: false, - }, { label: __( 'Title' ), id: 'title', @@ -412,6 +360,177 @@ function usePostFields( viewType ) { }, ], }, + { + id: 'featured_media', + label: __( 'Featured Image' ), + type: 'image', + render: ( { item } ) => { + const mediaId = item.featured_media; + + const media = getFeaturedMediaUrl( mediaId ); + + const url = media?.source_url; + const title = media?.title?.rendered; + + // This is a false positive + // eslint-disable-next-line react-hooks/rules-of-hooks + const { onClick } = useLink( { + postId: item.id, + postType: item.type, + canvas: 'edit', + } ); + + if ( viewType === LAYOUT_GRID && item.status !== 'trash' ) { + if ( ! url ) { + return null; + } + return ( + + ); + } + + if ( ! url ) { + return ( +
+ ); + } + + return ( + + + { title } + + ); + }, + Edit: ( { field, onChange, data } ) => { + const { id } = field; + + const value = field.getValue( { item: data } ) ?? ''; + + const onChangeControl = useCallback( + ( newValue ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const media = getFeaturedMediaUrl( value ); + + const url = media?.source_url; + const title = media?.title?.rendered; + const filename = + media?.media_details?.file?.match( '([^/]+$)' )[ 0 ]; + + return ( +
+
+ + + onChangeControl( selectedMedia.id ) + } + allowedTypes={ [ 'image' ] } + render={ ( { open } ) => { + return ( + + ); + } } + /> + + { url && ( +
+
+ ); + }, + enableSorting: false, + }, ], [ authors, getFeaturedMediaUrl, viewType, frontPageId, postsPageId ] ); diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss new file mode 100644 index 00000000000000..97161fb262eb85 --- /dev/null +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -0,0 +1,53 @@ +.edit-site-post-featured-image { + width: 20px; + height: 20px; +} + +.edit-site-dataviews-controls__featured-image { + .edit-side-dataviews-controls__featured-image-container { + border: var(--wp-admin-border-width-focus) solid $gray-300; + &:hover { + background-color: $gray-300; + } + } + + img { + width: 20px; + height: 20px; + } + + span { + text-align: start; + margin-left: $grid-unit-15; + text-overflow: ellipsis; + overflow: hidden; + width: 200px; + white-space: nowrap; + } + + .edit-site-dataviews-controls__featured-image-filename { + color: $gray-700; + font-size: 10px; + } + + .edit-site-dataviews-controls__featured-image-upload-button { + height: fit-content; + &:hover, + &:focus { + border: 0; + color: unset; + } + } + + .edit-site-dataviews-controls__featured-image-element { + align-self: baseline; + } + + .edit-site-dataviews-controls__featured-image-remove-button { + align-self: baseline; + } +} + +.components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown { + z-index: z-index(".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown"); +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 473deaeedc5908..5b57cbeb319807 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -29,6 +29,7 @@ @import "./components/style-book/style.scss"; @import "./components/editor-canvas-container/style.scss"; @import "./components/post-edit/style.scss"; +@import "./components/post-fields/style.scss"; @import "./components/post-list/style.scss"; @import "./components/resizable-frame/style.scss"; @import "./hooks/push-changes-to-global-styles/style.scss"; From c32622e4c1eb7c46d8bf49e16ce93118c73e780f Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 22 Aug 2024 16:19:19 +0200 Subject: [PATCH 03/59] fix list layout --- .../edit-site/src/components/post-fields/index.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index d4558cf863f130..12ff44283f62aa 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -41,6 +41,7 @@ import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; */ import { LAYOUT_GRID, + LAYOUT_LIST, LAYOUT_TABLE, OPERATOR_IS_ANY, } from '../../utils/constants'; @@ -407,6 +408,20 @@ function usePostFields( viewType ) { ); } + if ( viewType === LAYOUT_LIST ) { + if ( ! url ) { + return null; + } + + return ( + + ); + } + if ( ! url ) { return (
Date: Fri, 23 Aug 2024 10:16:11 +0200 Subject: [PATCH 04/59] improve design --- .../src/components/post-fields/index.js | 172 ++++++++++-------- .../src/components/post-fields/style.scss | 38 ++-- 2 files changed, 123 insertions(+), 87 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 12ff44283f62aa..95d116d554163b 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -27,10 +27,11 @@ import { } from '@wordpress/icons'; import { __experimentalHStack as HStack, - __experimentalVStack as VStack, + __experimentalText as Text, + __experimentalGrid as Grid, Icon, - Placeholder, Button, + Flex, FlexItem, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; @@ -424,14 +425,14 @@ function usePostFields( viewType ) { if ( ! url ) { return ( -
+ + + + + + { __( 'Choose an image…' ) } + + ); } @@ -469,77 +470,96 @@ function usePostFields( viewType ) { return (
- - - onChangeControl( selectedMedia.id ) - } - allowedTypes={ [ 'image' ] } - render={ ( { open } ) => { - return ( - - ); - } } - /> - - { url && ( -
+ ); + } } + />
); diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss index 97161fb262eb85..537fcf9dc50df4 100644 --- a/packages/edit-site/src/components/post-fields/style.scss +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -1,36 +1,51 @@ .edit-site-post-featured-image { - width: 20px; - height: 20px; + width: 24px; + height: 24px; + border: $radius-small; +} + +.edit-site-post-featured-image-placeholder { + width: 24px; + height: 24px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + display: inline-block; + padding: 0; + background: + $white + linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); } .edit-site-dataviews-controls__featured-image { .edit-side-dataviews-controls__featured-image-container { - border: var(--wp-admin-border-width-focus) solid $gray-300; + border: $border-width solid $gray-300; + padding: 8px 12px; + cursor: pointer; &:hover { - background-color: $gray-300; + background-color: $gray-100; } } img { - width: 20px; - height: 20px; + width: 24px; + height: 24px; + border: $radius-small; } span { + align-self: center; text-align: start; - margin-left: $grid-unit-15; - text-overflow: ellipsis; - overflow: hidden; - width: 200px; white-space: nowrap; } .edit-site-dataviews-controls__featured-image-filename { color: $gray-700; - font-size: 10px; + grid-area: 2 / 2 / 2 / 4; + line-height: 16px; + font-size: 12px; } .edit-site-dataviews-controls__featured-image-upload-button { + padding: 0; height: fit-content; &:hover, &:focus { @@ -44,6 +59,7 @@ } .edit-site-dataviews-controls__featured-image-remove-button { + place-self: end; align-self: baseline; } } From 5419b0ad21d8d7a432aef13ed31ec05e565933be Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Fri, 23 Aug 2024 10:41:47 +0200 Subject: [PATCH 05/59] remove not necessary style --- .../edit-site/src/components/post-fields/index.js | 1 - .../edit-site/src/components/post-fields/style.scss | 11 ----------- 2 files changed, 12 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 95d116d554163b..8313d8a029e45e 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -504,7 +504,6 @@ function usePostFields( viewType ) { Date: Tue, 27 Aug 2024 10:32:04 +0200 Subject: [PATCH 06/59] improve style --- .../src/components/post-fields/index.js | 23 ++++++++----------- .../src/components/post-fields/style.scss | 12 ++++++++++ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 8313d8a029e45e..9de1d938827be9 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -425,7 +425,7 @@ function usePostFields( viewType ) { if ( ! url ) { return ( - + @@ -480,16 +480,8 @@ function usePostFields( viewType ) {
{ - const element = - event.target.tagName.toLowerCase(); - // Prevent opening the media modal when clicking on the button/icon. - if ( - element !== 'button' && - element !== 'svg' - ) { - open(); - } + onClick={ () => { + open(); } } onKeyDown={ open } > @@ -534,11 +526,14 @@ function usePostFields( viewType ) { icon={ lineSolid } - onClick={ () => + onClick={ ( + event + ) => { + event.stopPropagation(); onChangeControl( 0 - ) - } + ); + } } /> Date: Tue, 27 Aug 2024 12:02:55 +0200 Subject: [PATCH 07/59] improve default image control --- .../dataviews/src/dataform-controls/image.tsx | 78 +++++++++++-------- .../src/dataform-controls/style.scss | 28 +++++++ 2 files changed, 73 insertions(+), 33 deletions(-) diff --git a/packages/dataviews/src/dataform-controls/image.tsx b/packages/dataviews/src/dataform-controls/image.tsx index d13e0dbe87c7f8..c61cbffd997736 100644 --- a/packages/dataviews/src/dataform-controls/image.tsx +++ b/packages/dataviews/src/dataform-controls/image.tsx @@ -5,6 +5,9 @@ import { Button, FormFileUpload, __experimentalHStack as HStack, + __experimentalVStack as VStack, + BaseControl, + VisuallyHidden, } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; @@ -12,13 +15,15 @@ import { useCallback } from '@wordpress/element'; * Internal dependencies */ import type { DataFormControlProps } from '../types'; +import { __ } from '@wordpress/i18n'; export default function Image< Item >( { data, field, onChange, + hideLabelFromVision, }: DataFormControlProps< Item > ) { - const { id } = field; + const { id, label } = field; const value = field.getValue( { item: data } ); const onChangeControl = useCallback( @@ -31,41 +36,48 @@ export default function Image< Item >( { return (
- { value && ( - + { hideLabelFromVision ? ( + { label } + ) : ( + + { label } + ) } - - { - if ( event.target.files?.length ) { - const objectUrl = URL.createObjectURL( - event.target.files[ 0 ] - ); - onChangeControl( objectUrl ); - } - } } - > - - - { value && ( - - ) } - + + + { value && ( + + ) } + +
); } diff --git a/packages/dataviews/src/dataform-controls/style.scss b/packages/dataviews/src/dataform-controls/style.scss index 230826c0adf823..0f53f3c1a6c385 100644 --- a/packages/dataviews/src/dataform-controls/style.scss +++ b/packages/dataviews/src/dataform-controls/style.scss @@ -2,3 +2,31 @@ border: none; padding: 0; } + +.dataviews-controls__image { + border: none; + padding: 0; + .dataviews-controls__image-container { + @include input-control; + margin: 0; + } + + .dataviews-controls__image-placeholder { + width: 200px; + height: 200px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + display: inline-block; + margin: 6px 12px; + background: + $white + linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); + } + + img { + width: 200px; + margin: 6px 12px; + height: 200px; + border: $radius-small; + object-fit: cover; + } +} From baf7a82970a85c6916f30f791effc4a8e6805f0f Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 29 Aug 2024 15:11:24 +0200 Subject: [PATCH 08/59] fix style --- .../src/components/post-fields/index.js | 280 ++++++++++++------ .../src/components/post-fields/style.scss | 22 +- 2 files changed, 213 insertions(+), 89 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 9de1d938827be9..5ae5dd3ad9deff 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -31,8 +31,6 @@ import { __experimentalGrid as Grid, Icon, Button, - Flex, - FlexItem, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; @@ -146,6 +144,75 @@ function PostAuthorField( { item } ) { ); } +function FeaturedImage( { item, viewType, getFeaturedMediaUrl } ) { + const mediaId = item.featured_media; + + const media = getFeaturedMediaUrl( mediaId ); + + const url = media?.source_url; + const title = media?.title?.rendered; + + const { onClick } = useLink( { + postId: item.id, + postType: item.type, + canvas: 'edit', + } ); + + if ( viewType === LAYOUT_GRID && item.status !== 'trash' ) { + if ( ! url ) { + return null; + } + return ( + + + + ); + } + + if ( viewType === LAYOUT_LIST ) { + if ( ! url ) { + return null; + } + + return ( +
+ +
+ ); + } + + if ( ! url ) { + return ( + + + { __( 'Choose an image…' ) } + + ); + } + + return ( + + + { title } + + ); +} + function usePostFields( viewType ) { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); @@ -166,6 +233,131 @@ function usePostFields( viewType ) { const fields = useMemo( () => [ + { + id: 'featured_media', + label: __( 'Featured Image' ), + type: 'image', + render: ( { item } ) => ( + + ), + Edit: ( { field, onChange, data } ) => { + const { id } = field; + + const value = field.getValue( { item: data } ) ?? ''; + + const onChangeControl = useCallback( + ( newValue ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const media = getFeaturedMediaUrl( value ); + + const url = media?.source_url; + const title = media?.title?.rendered; + const filename = + media?.media_details?.file?.match( '([^/]+$)' )[ 0 ]; + + return ( +
+
+ + onChangeControl( selectedMedia.id ) + } + allowedTypes={ [ 'image' ] } + render={ ( { open } ) => { + return ( +
{ + open(); + } } + onKeyDown={ open } + > + + { url && ( + <> + + + { title } + + + ) } + { ! url && ( + <> + + + { __( + 'Choose an image…' + ) } + + + ) } + { url && ( + <> +
+ ); + } } + /> +
+
+ ); + }, + enableSorting: false, + }, { label: __( 'Title' ), id: 'title', @@ -366,87 +558,9 @@ function usePostFields( viewType ) { id: 'featured_media', label: __( 'Featured Image' ), type: 'image', - render: ( { item } ) => { - const mediaId = item.featured_media; - - const media = getFeaturedMediaUrl( mediaId ); - - const url = media?.source_url; - const title = media?.title?.rendered; - - // This is a false positive - // eslint-disable-next-line react-hooks/rules-of-hooks - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); - - if ( viewType === LAYOUT_GRID && item.status !== 'trash' ) { - if ( ! url ) { - return null; - } - return ( - - ); - } - - if ( viewType === LAYOUT_LIST ) { - if ( ! url ) { - return null; - } - - return ( - - ); - } - - if ( ! url ) { - return ( - - - - - - { __( 'Choose an image…' ) } - - - ); - } - - return ( - - - { title } - - ); - }, + render: ( { item } ) => ( + + ), Edit: ( { field, onChange, data } ) => { const { id } = field; diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss index 1bbd8b304f52d7..cd875b61ebd7cc 100644 --- a/packages/edit-site/src/components/post-fields/style.scss +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -10,6 +10,16 @@ } } +.edit-site-post-featured-image-container { + .edit-site-post-featured-image-placeholder { + margin: 0; + } + + span { + margin-right: auto; + } +} + .edit-site-post-featured-image-placeholder { width: 24px; height: 24px; @@ -21,6 +31,12 @@ linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); } +.edit-site-post-featured-image { + width: 24px; + height: 24px; + border: $radius-small; +} + .edit-site-dataviews-controls__featured-image { .edit-side-dataviews-controls__featured-image-container { border: $border-width solid $gray-300; @@ -31,12 +47,6 @@ } } - img { - width: 24px; - height: 24px; - border: $radius-small; - } - span { align-self: center; text-align: start; From 4095dab6822737a52f4721bd3ad23294cde39ed0 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 29 Aug 2024 15:11:38 +0200 Subject: [PATCH 09/59] remove not necessary configuration --- .../src/components/sidebar-dataviews/default-views.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 37a090be07822e..64854fc19db46c 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -31,9 +31,6 @@ export const defaultLayouts = { layout: { primaryField: 'title', styles: { - featured_media: { - width: '1%', - }, title: { maxWidth: 300, }, From ec715ed16ca684a2a3b6586500ef446da2b596c6 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 29 Aug 2024 15:17:44 +0200 Subject: [PATCH 10/59] format _z-index.scss file --- packages/base-styles/_z-index.scss | 241 ++++++++++++++--------------- 1 file changed, 115 insertions(+), 126 deletions(-) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 73571f41f4d20e..59b7a54728aecc 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -3,228 +3,217 @@ // value is designed to work with). $z-layers: ( - '.block-editor-block-list__block::before': 0, - '.block-editor-block-list__block.is-selected': 20, - '.block-editor-block-switcher__arrow': 1, - '.block-editor-block-list__block {core/image aligned wide or fullwide}': 20, - '.block-library-classic__toolbar': 31, - // When scrolled to top this toolbar needs to sit over block-editor-block-toolbar - '.block-editor-block-list__block-selection-button': 22, - '.components-form-toggle__input': 1, - '.editor-text-editor__toolbar': 1, + ".block-editor-block-list__block::before": 0, + ".block-editor-block-list__block.is-selected": 20, + ".block-editor-block-switcher__arrow": 1, + ".block-editor-block-list__block {core/image aligned wide or fullwide}": 20, + ".block-library-classic__toolbar": 31, // When scrolled to top this toolbar needs to sit over block-editor-block-toolbar + ".block-editor-block-list__block-selection-button": 22, + ".components-form-toggle__input": 1, + ".editor-text-editor__toolbar": 1, // These next three share a stacking context - '.block-library-template-part__selection-search': 2, - // higher sticky element - '.block-library-query-pattern__selection-search': 2, + ".block-library-template-part__selection-search": 2, // higher sticky element + ".block-library-query-pattern__selection-search": 2, // higher sticky element - // higher sticky element // These next two share a stacking context - '.interface-complementary-area .components-panel': 0, - // lower scrolling content - '.interface-complementary-area .components-panel__header': 1, - - // higher sticky element - '.components-modal__header': 10, - '.edit-post-meta-boxes-area.is-loading::before': 1, - '.edit-post-meta-boxes-area .spinner': 5, - '.components-popover__close': 5, - '.block-editor-block-list__insertion-point': 6, - '.block-editor-warning': 5, - '.block-library-gallery-item__inline-menu': 20, - '.block-editor-url-input__suggestions': 30, - '.edit-post-layout__footer': 30, - '.interface-interface-skeleton__header': 30, - '.interface-interface-skeleton__content': 20, - '.edit-widgets-header': 30, - '.wp-block-cover__inner-container': 1, - // InnerBlocks area inside cover image block. - '.wp-block-cover.is-placeholder .components-placeholder.is-large': 1, - // Cover block resizer component inside a large placeholder. - '.wp-block-cover.has-background-dim::before': 1, - // Overlay area inside block cover need to be higher than the video background. - '.block-library-cover__padding-visualizer': 2, - // BoxControl visualizer needs to be +1 higher than .wp-block-cover.has-background-dim::before - '.wp-block-cover__image-background': 0, - // Image background inside cover block. - '.wp-block-cover__video-background': 0, - // Video background inside cover block. - '.wp-block-template-part__placeholder-preview-filter-input': 1, + ".interface-complementary-area .components-panel" : 0, // lower scrolling content + ".interface-complementary-area .components-panel__header": 1, // higher sticky element + + ".components-modal__header": 10, + ".edit-post-meta-boxes-area.is-loading::before": 1, + ".edit-post-meta-boxes-area .spinner": 5, + ".components-popover__close": 5, + ".block-editor-block-list__insertion-point": 6, + ".block-editor-warning": 5, + ".block-library-gallery-item__inline-menu": 20, + ".block-editor-url-input__suggestions": 30, + ".edit-post-layout__footer": 30, + ".interface-interface-skeleton__header": 30, + ".interface-interface-skeleton__content": 20, + ".edit-widgets-header": 30, + ".wp-block-cover__inner-container": 1, // InnerBlocks area inside cover image block. + ".wp-block-cover.is-placeholder .components-placeholder.is-large": 1, // Cover block resizer component inside a large placeholder. + ".wp-block-cover.has-background-dim::before": 1, // Overlay area inside block cover need to be higher than the video background. + ".block-library-cover__padding-visualizer": 2, // BoxControl visualizer needs to be +1 higher than .wp-block-cover.has-background-dim::before + ".wp-block-cover__image-background": 0, // Image background inside cover block. + ".wp-block-cover__video-background": 0, // Video background inside cover block. + ".wp-block-template-part__placeholder-preview-filter-input": 1, // Fixed position appender: - '.block-editor-block-list__block .block-list-appender': 2, + ".block-editor-block-list__block .block-list-appender": 2, // Navigation menu dropdown. - '.has-child .wp-block-navigation__submenu-container': 28, - '.has-child:hover .wp-block-navigation__submenu-container': 29, + ".has-child .wp-block-navigation__submenu-container": 28, + ".has-child:hover .wp-block-navigation__submenu-container": 29, // Active pill button - '.components-button {:focus or .is-primary}': 1, + ".components-button {:focus or .is-primary}": 1, // The draggable element should show up above the entire UI - '.components-draggable__clone': 1000000000, + ".components-draggable__clone": 1000000000, - '.block-editor-block-list__block .reusable-block-edit-panel *': 1, + ".block-editor-block-list__block .reusable-block-edit-panel *": 1, // Show drop zone above most standard content, but below any overlays - '.components-drop-zone': 40, - '.components-drop-zone__content': 50, + ".components-drop-zone": 40, + ".components-drop-zone__content": 50, // The floated blocks should be above the other blocks to allow selection. - '{core/image aligned left or right} .wp-block': 21, + "{core/image aligned left or right} .wp-block": 21, // Needs to be below media library that has a z-index of 160000. - '{core/video track editor popover}': 160000 - 10, + "{core/video track editor popover}": 160000 - 10, // Needs to be below media library (.media-model) that has a z-index of 160000. - '.block-editor-format-toolbar__image-popover': 160000 - 10, + ".block-editor-format-toolbar__image-popover": 160000 - 10, // Below the media library backdrop (.media-modal-backdrop), which has a z-index of 159900. - '.block-editor-global-styles-background-panel__popover': 159900 - 10, + ".block-editor-global-styles-background-panel__popover": 159900 - 10, // Small screen inner blocks overlay must be displayed above drop zone, // settings menu, and movers. - '.block-editor-block-list__layout.has-overlay::after': 60, + ".block-editor-block-list__layout.has-overlay::after": 60, // The toolbar, when contextual, should be above any adjacent nested block click overlays. - '.block-editor-block-contextual-toolbar': 61, + ".block-editor-block-contextual-toolbar": 61, // Ensures content overlay appears higher than resize containers used for image/video/etc. - '.block-editor-block-list__block.has-block-overlay': 10, + ".block-editor-block-list__block.has-block-overlay": 10, // Query block setup state. - '.block-editor-block-pattern-setup .pattern-slide': 100, - '.block-editor-block-pattern-setup .{next,previous}-slide': 101, - '.block-editor-block-pattern-setup .active-slide': 102, + ".block-editor-block-pattern-setup .pattern-slide": 100, + ".block-editor-block-pattern-setup .{next,previous}-slide": 101, + ".block-editor-block-pattern-setup .active-slide": 102, // Show sidebar above wp-admin navigation bar for mobile viewports: // #wpadminbar { z-index: 99999 } - '.interface-interface-skeleton__sidebar': 100000, - '.editor-layout__toggle-sidebar-panel': 100000, - '.edit-widgets-sidebar': 100000, - '.editor-post-publish-panel': 100001, + ".interface-interface-skeleton__sidebar": 100000, + ".editor-layout__toggle-sidebar-panel": 100000, + ".edit-widgets-sidebar": 100000, + ".editor-post-publish-panel": 100001, // For larger views, the wp-admin navbar dropdown should be at top of // the Publish Post sidebar. - '.editor-post-publish-panel {greater than small}': 99998, + ".editor-post-publish-panel {greater than small}": 99998, // For larger views, the wp-admin navbar dropdown should be on top of // the multi-entity saving sidebar. - '.edit-site-editor__toggle-save-panel': 100000, + ".edit-site-editor__toggle-save-panel": 100000, // Show sidebar in greater than small viewports above editor related elements // but below #adminmenuback { z-index: 100 } - '.interface-interface-skeleton__sidebar {greater than small}': 90, - '.edit-widgets-sidebar {greater than small}': 90, + ".interface-interface-skeleton__sidebar {greater than small}": 90, + ".edit-widgets-sidebar {greater than small}": 90, // Show interface skeleton footer above interface skeleton drawer - '.interface-interface-skeleton__footer': 90, + ".interface-interface-skeleton__footer": 90, // Above the block list and the header. - '.block-editor-block-popover': 31, + ".block-editor-block-popover": 31, // Below the block toolbar. - '.block-editor-grid-visualizer': 30, + ".block-editor-grid-visualizer": 30, // Show snackbars above everything (similar to popovers) - '.components-snackbar-list': 100000, + ".components-snackbar-list": 100000, // Show modal under the wp-admin menus and the popover - '.components-modal__screen-overlay': 100000, + ".components-modal__screen-overlay": 100000, // Show popovers above wp-admin menus and submenus and sidebar: // #adminmenuwrap { z-index: 9990 } - '.components-popover': 1000000, + ".components-popover": 1000000, // Should be above the popover (dropdown) - '.reusable-blocks-menu-items__convert-modal': 1000001, - '.patterns-menu-items__convert-modal': 1000001, - '.editor-create-template-part-modal': 1000001, - '.block-editor-block-lock-modal': 1000001, - '.block-editor-template-part__selection-modal': 1000001, - '.block-editor-block-rename-modal': 1000001, - '.edit-site-list__rename-modal': 1000001, - '.dataviews-action-modal': 1000001, - '.editor-action-modal': 1000001, - '.editor-post-template__swap-template-modal': 1000001, - '.edit-site-template-panel__replace-template-modal': 1000001, + ".reusable-blocks-menu-items__convert-modal": 1000001, + ".patterns-menu-items__convert-modal": 1000001, + ".editor-create-template-part-modal": 1000001, + ".block-editor-block-lock-modal": 1000001, + ".block-editor-template-part__selection-modal": 1000001, + ".block-editor-block-rename-modal": 1000001, + ".edit-site-list__rename-modal": 1000001, + ".dataviews-action-modal": 1000001, + ".editor-action-modal": 1000001, + ".editor-post-template__swap-template-modal": 1000001, + ".edit-site-template-panel__replace-template-modal": 1000001, // Note: The ConfirmDialog component's z-index is being set to 1000001 in packages/components/src/confirm-dialog/styles.ts // because it uses emotion and not sass. We need it to render on top its parent popover. + // ...Except for popovers immediately beneath wp-admin menu on large breakpoints - '.components-popover.block-editor-inserter__popover': 99999, - '.components-popover.table-of-contents__popover': 99998, - '.components-popover.interface-more-menu__content': 99998, - '.components-popover.more-menu__content': 99998, - '.components-popover.block-editor-rich-text__inline-format-toolbar': 99998, - '.components-popover.block-editor-warning__dropdown': 99998, + ".components-popover.block-editor-inserter__popover": 99999, + ".components-popover.table-of-contents__popover": 99998, + ".components-popover.interface-more-menu__content": 99998, + ".components-popover.more-menu__content": 99998, + ".components-popover.block-editor-rich-text__inline-format-toolbar": 99998, + ".components-popover.block-editor-warning__dropdown": 99998, - '.components-autocomplete__results': 1000000, + ".components-autocomplete__results": 1000000, - '.skip-to-selected-block': 100000, - '.interface-interface-skeleton__actions': 100000, - '.edit-site-layout__actions': 100000, + ".skip-to-selected-block": 100000, + ".interface-interface-skeleton__actions": 100000, + ".edit-site-layout__actions": 100000, // The focus styles of the region navigation containers should be above their content. - '.is-focusing-regions {region} :focus::after': 1000000, + ".is-focusing-regions {region} :focus::after": 1000000, // Show NUX tips above popovers, wp-admin menus, submenus, and sidebar: - '.nux-dot-tip': 1000001, + ".nux-dot-tip": 1000001, // Show tooltips above NUX tips, wp-admin menus, submenus, and sidebar: - '.components-tooltip': 1000002, + ".components-tooltip": 1000002, // Make sure corner handles are above side handles for ResizableBox component - '.components-resizable-box__handle': 2, - '.components-resizable-box__side-handle': 2, - '.components-resizable-box__corner-handle': 2, + ".components-resizable-box__handle": 2, + ".components-resizable-box__side-handle": 2, + ".components-resizable-box__corner-handle": 2, // Make sure block manager sticky category titles appear above the options - '.editor-block-manager__category-title': 1, + ".editor-block-manager__category-title": 1, // And block manager sticky disabled block count is higher still - '.editor-block-manager__disabled-blocks-count': 2, + ".editor-block-manager__disabled-blocks-count": 2, // Needs to appear below other color circular picker related UI elements. - '.components-circular-option-picker__option-wrapper::before': -1, + ".components-circular-option-picker__option-wrapper::before": -1, - '.components-circular-option-picker__option.is-pressed': 1, + ".components-circular-option-picker__option.is-pressed": 1, // Needs to be higher than .components-circular-option-picker__option.is-pressed. - '.components-circular-option-picker__option.is-pressed + svg': 2, + ".components-circular-option-picker__option.is-pressed + svg": 2, // The following two indexes are needed so that the swatches (and their tooltips) // always render on top of the rest of the component's UI. - '.components-circular-option-picker__swatches': 1, - '> *:not(.components-circular-option-picker__swatches)': 0, + ".components-circular-option-picker__swatches": 1, + "> *:not(.components-circular-option-picker__swatches)": 0, // Appear under the customizer heading UI, but over anything else. - '.customize-widgets__topbar': 8, + ".customize-widgets__topbar": 8, // Appear under the topbar. - '.customize-widgets__block-toolbar': 7, + ".customize-widgets__block-toolbar": 7, // Site editor layout - '.edit-site-page-header': 2, - '.edit-site-page-content': 1, - '.edit-site-templates__dataviews-list-pagination': 2, - '.edit-site-layout__canvas-container': 2, - '.edit-site-layout__sidebar': 1, - '.edit-site-layout__canvas-container.is-resizing::after': 100, + ".edit-site-page-header": 2, + ".edit-site-page-content": 1, + ".edit-site-templates__dataviews-list-pagination": 2, + ".edit-site-layout__canvas-container": 2, + ".edit-site-layout__sidebar": 1, + ".edit-site-layout__canvas-container.is-resizing::after": 100, // Title needs to appear above other UI the section content. - '.edit-site-sidebar-navigation-screen__title-icon': 1, + ".edit-site-sidebar-navigation-screen__title-icon": 1, // Ensure modal footer actions appear above modal contents - '.editor-start-template-options__modal__actions': 1, + ".editor-start-template-options__modal__actions": 1, // Ensure checkbox + actions don't overlap table header - '.dataviews-view-table thead': 1, + ".dataviews-view-table thead": 1, // Ensure selection checkbox stays above the preview field. - '.dataviews-view-grid__card .dataviews-selection-checkbox': 1, + ".dataviews-view-grid__card .dataviews-selection-checkbox": 1, - // Ensure quick actions toolbar appear above pagination - '.dataviews-bulk-actions-toolbar': 2, - // Needs to be below media library (.media-model) that has a z-index of 160000. - '.components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown': 160000 - 10, // Ensure footer stays above the preview field. - '.dataviews-footer': 2, + ".dataviews-footer": 2, + + // Needs to be below media library (.media-model) that has a z-index of 160000. + ".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown": 160000 - 10, ); @function z-index( $key ) { From ea29690b58c5ec7165eaec720c06ddb9910ad0e0 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 29 Aug 2024 16:45:22 +0200 Subject: [PATCH 11/59] improve style --- .../src/components/post-fields/index.js | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 5ae5dd3ad9deff..55b6c5044e70b4 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -163,20 +163,18 @@ function FeaturedImage( { item, viewType, getFeaturedMediaUrl } ) { return null; } return ( - - - + ); } From 106af4d66820703030ec561d845d0d5689aab447 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 29 Aug 2024 16:47:20 +0200 Subject: [PATCH 12/59] remove not necessary code --- .../src/components/post-fields/index.js | 120 ------------------ 1 file changed, 120 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 55b6c5044e70b4..345b9a73196ea8 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -552,126 +552,6 @@ function usePostFields( viewType ) { }, ], }, - { - id: 'featured_media', - label: __( 'Featured Image' ), - type: 'image', - render: ( { item } ) => ( - - ), - Edit: ( { field, onChange, data } ) => { - const { id } = field; - - const value = field.getValue( { item: data } ) ?? ''; - - const onChangeControl = useCallback( - ( newValue ) => - onChange( { - [ id ]: newValue, - } ), - [ id, onChange ] - ); - - const media = getFeaturedMediaUrl( value ); - - const url = media?.source_url; - const title = media?.title?.rendered; - const filename = - media?.media_details?.file?.match( '([^/]+$)' )[ 0 ]; - - return ( -
-
- - onChangeControl( selectedMedia.id ) - } - allowedTypes={ [ 'image' ] } - render={ ( { open } ) => { - return ( -
{ - open(); - } } - onKeyDown={ open } - > - - { url && ( - <> - - - { title } - - - ) } - { ! url && ( - <> - - - { __( - 'Choose an image…' - ) } - - - ) } - { url && ( - <> -
- ); - } } - /> -
-
- ); - }, - enableSorting: false, - }, ], [ authors, getFeaturedMediaUrl, viewType, frontPageId, postsPageId ] ); From c6dffd7fbf75b656586451eb63697e5c11391de7 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 9 Sep 2024 15:15:17 +0200 Subject: [PATCH 13/59] fix focus --- .../src/components/post-fields/index.js | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 345b9a73196ea8..30831e1e25547b 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -13,6 +13,8 @@ import { useMemo, useState, useCallback, + useRef, + useEffect, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; import { @@ -262,13 +264,25 @@ function usePostFields( viewType ) { const filename = media?.media_details?.file?.match( '([^/]+$)' )[ 0 ]; + const ref = useRef( null ); + + useEffect( () => { + if ( ref.current ) { + ref.current.focus(); + } + }, [] ); + return (
-
+
- onChangeControl( selectedMedia.id ) - } + onSelect={ ( selectedMedia ) => { + onChangeControl( selectedMedia.id ); + } } allowedTypes={ [ 'image' ] } render={ ( { open } ) => { return ( From 3c262d690d66777a634e9b89c9ff46ef6239add4 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 9 Sep 2024 15:27:26 +0200 Subject: [PATCH 14/59] remove image field type --- .../dataform/stories/index.story.tsx | 7 -- .../dataviews/src/dataform-controls/image.tsx | 83 ------------------- .../dataviews/src/dataform-controls/index.tsx | 2 - packages/dataviews/src/field-types/image.tsx | 9 -- packages/dataviews/src/field-types/index.tsx | 5 -- packages/dataviews/src/types.ts | 2 +- 6 files changed, 1 insertion(+), 107 deletions(-) delete mode 100644 packages/dataviews/src/dataform-controls/image.tsx delete mode 100644 packages/dataviews/src/field-types/image.tsx diff --git a/packages/dataviews/src/components/dataform/stories/index.story.tsx b/packages/dataviews/src/components/dataform/stories/index.story.tsx index 101e3e8eccf46b..7147b9c2342638 100644 --- a/packages/dataviews/src/components/dataform/stories/index.story.tsx +++ b/packages/dataviews/src/components/dataform/stories/index.story.tsx @@ -76,11 +76,6 @@ const fields = [ { value: 'published', label: 'Published' }, ], }, - { - id: 'image', - label: 'Image', - type: 'image' as const, - }, ]; export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { @@ -92,7 +87,6 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { reviewer: 'fulano', date: '2021-01-01T12:00:00', birthdate: '1950-02-23T12:00:00', - image: 'https://picsum.photos/200', } ); const form = { @@ -104,7 +98,6 @@ export const Default = ( { type }: { type: 'panel' | 'regular' } ) => { 'status', 'date', 'birthdate', - 'image', ], }; diff --git a/packages/dataviews/src/dataform-controls/image.tsx b/packages/dataviews/src/dataform-controls/image.tsx deleted file mode 100644 index c61cbffd997736..00000000000000 --- a/packages/dataviews/src/dataform-controls/image.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/** - * WordPress dependencies - */ -import { - Button, - FormFileUpload, - __experimentalHStack as HStack, - __experimentalVStack as VStack, - BaseControl, - VisuallyHidden, -} from '@wordpress/components'; -import { useCallback } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import type { DataFormControlProps } from '../types'; -import { __ } from '@wordpress/i18n'; - -export default function Image< Item >( { - data, - field, - onChange, - hideLabelFromVision, -}: DataFormControlProps< Item > ) { - const { id, label } = field; - const value = field.getValue( { item: data } ); - - const onChangeControl = useCallback( - ( newValue: string ) => - onChange( { - [ id ]: newValue, - } ), - [ id, onChange ] - ); - - return ( -
- { hideLabelFromVision ? ( - { label } - ) : ( - - { label } - - ) } - - { value && } - { ! value && ( - - ) } - - { - if ( event.target.files?.length ) { - const objectUrl = URL.createObjectURL( - event.target.files[ 0 ] - ); - onChangeControl( objectUrl ); - } - } } - > - - - { value && ( - - ) } - - -
- ); -} diff --git a/packages/dataviews/src/dataform-controls/index.tsx b/packages/dataviews/src/dataform-controls/index.tsx index 600d7c256314c6..297e73c28f837c 100644 --- a/packages/dataviews/src/dataform-controls/index.tsx +++ b/packages/dataviews/src/dataform-controls/index.tsx @@ -16,7 +16,6 @@ import integer from './integer'; import radio from './radio'; import select from './select'; import text from './text'; -import image from './image'; interface FormControls { [ key: string ]: ComponentType< DataFormControlProps< any > >; @@ -28,7 +27,6 @@ const FORM_CONTROLS: FormControls = { radio, select, text, - image, }; export function getControl< Item >( diff --git a/packages/dataviews/src/field-types/image.tsx b/packages/dataviews/src/field-types/image.tsx deleted file mode 100644 index b95a12dde80a9f..00000000000000 --- a/packages/dataviews/src/field-types/image.tsx +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Internal dependencies - */ - -export default { - sort: () => 0, - isValid: () => true, - Edit: 'image', -}; diff --git a/packages/dataviews/src/field-types/index.tsx b/packages/dataviews/src/field-types/index.tsx index 360311a24e0cbe..eb9dada479c6bf 100644 --- a/packages/dataviews/src/field-types/index.tsx +++ b/packages/dataviews/src/field-types/index.tsx @@ -5,7 +5,6 @@ import type { FieldType, SortDirection, ValidationContext } from '../types'; import { default as integer } from './integer'; import { default as text } from './text'; import { default as datetime } from './datetime'; -import { default as image } from './image'; /** * @@ -26,10 +25,6 @@ export default function getFieldTypeDefinition( type?: FieldType ) { return datetime; } - if ( 'image' === type ) { - return image; - } - return { sort: ( a: any, b: any, direction: SortDirection ) => { if ( typeof a === 'number' && typeof b === 'number' ) { diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 116672df79499e..e95a43994cd63d 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -42,7 +42,7 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type FieldType = 'text' | 'integer' | 'datetime' | 'image'; +export type FieldType = 'text' | 'integer' | 'datetime'; export type ValidationContext = { elements?: Option[]; From c053a9ac17c2049d515559c15b70f9d1eb902166 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 9 Sep 2024 15:42:23 +0200 Subject: [PATCH 15/59] add comment --- packages/edit-site/src/components/post-fields/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 30831e1e25547b..7447b69cf8394e 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -266,6 +266,7 @@ function usePostFields( viewType ) { const ref = useRef( null ); + // Focus to the media upload button when the component mounts. useEffect( () => { if ( ref.current ) { ref.current.focus(); @@ -274,11 +275,7 @@ function usePostFields( viewType ) { return (
-
+
{ onChangeControl( selectedMedia.id ); @@ -287,8 +284,9 @@ function usePostFields( viewType ) { render={ ( { open } ) => { return (
{ open(); } } From 57faa8f53934c28a8a0916a1666337fcb111e5d1 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 9 Sep 2024 18:12:04 +0200 Subject: [PATCH 16/59] fix warning --- .../src/components/post-fields/index.js | 160 +++++++++--------- 1 file changed, 77 insertions(+), 83 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 7447b69cf8394e..c3a3d2a22652af 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -14,7 +14,6 @@ import { useState, useCallback, useRef, - useEffect, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; import { @@ -92,65 +91,16 @@ const getFormattedDate = ( dateToDisplay ) => getDate( dateToDisplay ) ); -function PostStatusField( { item } ) { - const status = STATUSES.find( ( { value } ) => value === item.status ); - const label = status?.label || item.status; - const icon = status?.icon; - return ( - - { icon && ( -
- -
- ) } - { label } -
- ); -} +function FeaturedImage( { item, viewType } ) { + const mediaId = item.featured_media; -function PostAuthorField( { item } ) { - const { text, imageUrl } = useSelect( + const media = useSelect( ( select ) => { - const { getUser } = select( coreStore ); - const user = getUser( item.author ); - return { - imageUrl: user?.avatar_urls?.[ 48 ], - text: user?.name, - }; + const { getEntityRecord } = select( coreStore ); + return getEntityRecord( 'root', 'media', mediaId ); }, - [ item ] - ); - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - return ( - - { !! imageUrl && ( -
- setIsImageLoaded( true ) } - alt={ __( 'Author avatar' ) } - src={ imageUrl } - /> -
- ) } - { ! imageUrl && ( -
- -
- ) } - { text } -
+ [ mediaId ] ); -} - -function FeaturedImage( { item, viewType, getFeaturedMediaUrl } ) { - const mediaId = item.featured_media; - - const media = getFeaturedMediaUrl( mediaId ); - const url = media?.source_url; const title = media?.title?.rendered; @@ -213,23 +163,72 @@ function FeaturedImage( { item, viewType, getFeaturedMediaUrl } ) { ); } -function usePostFields( viewType ) { - const { records: authors, isResolving: isLoadingAuthors } = - useEntityRecords( 'root', 'user', { per_page: -1 } ); +function PostStatusField( { item } ) { + const status = STATUSES.find( ( { value } ) => value === item.status ); + const label = status?.label || item.status; + const icon = status?.icon; + return ( + + { icon && ( +
+ +
+ ) } + { label } +
+ ); +} - const { frontPageId, postsPageId, getFeaturedMediaUrl } = useSelect( +function PostAuthorField( { item } ) { + const { text, imageUrl } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); + const { getUser } = select( coreStore ); + const user = getUser( item.author ); return { - frontPageId: siteSettings?.page_on_front, - postsPageId: siteSettings?.page_for_posts, - getFeaturedMediaUrl: ( id ) => - getEntityRecord( 'root', 'media', id ), + imageUrl: user?.avatar_urls?.[ 48 ], + text: user?.name, }; }, - [] + [ item ] + ); + const [ isImageLoaded, setIsImageLoaded ] = useState( false ); + return ( + + { !! imageUrl && ( +
+ setIsImageLoaded( true ) } + alt={ __( 'Author avatar' ) } + src={ imageUrl } + /> +
+ ) } + { ! imageUrl && ( +
+ +
+ ) } + { text } +
); +} + +function usePostFields( viewType ) { + const { records: authors, isResolving: isLoadingAuthors } = + useEntityRecords( 'root', 'user', { per_page: -1 } ); + + const { frontPageId, postsPageId } = useSelect( ( select ) => { + const { getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + return { + frontPageId: siteSettings?.page_on_front, + postsPageId: siteSettings?.page_for_posts, + }; + }, [] ); const fields = useMemo( () => [ @@ -238,16 +237,20 @@ function usePostFields( viewType ) { label: __( 'Featured Image' ), type: 'image', render: ( { item } ) => ( - + ), Edit: ( { field, onChange, data } ) => { const { id } = field; - const value = field.getValue( { item: data } ) ?? ''; + const value = field.getValue( { item: data } ); + + const media = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + return getEntityRecord( 'root', 'media', value ); + }, + [ value ] + ); const onChangeControl = useCallback( ( newValue ) => @@ -257,8 +260,6 @@ function usePostFields( viewType ) { [ id, onChange ] ); - const media = getFeaturedMediaUrl( value ); - const url = media?.source_url; const title = media?.title?.rendered; const filename = @@ -266,13 +267,6 @@ function usePostFields( viewType ) { const ref = useRef( null ); - // Focus to the media upload button when the component mounts. - useEffect( () => { - if ( ref.current ) { - ref.current.focus(); - } - }, [] ); - return (
@@ -565,7 +559,7 @@ function usePostFields( viewType ) { ], }, ], - [ authors, getFeaturedMediaUrl, viewType, frontPageId, postsPageId ] + [ authors, viewType, frontPageId, postsPageId ] ); return { From d2eeb0e8de8ee42894c9177433d7597bc57c0f17 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 10 Sep 2024 00:11:26 +0200 Subject: [PATCH 17/59] fix image for deleted pages --- packages/edit-site/src/components/post-fields/index.js | 2 +- .../edit-site/src/components/sidebar-dataviews/default-views.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index c3a3d2a22652af..dc630dcbfff223 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -110,7 +110,7 @@ function FeaturedImage( { item, viewType } ) { canvas: 'edit', } ); - if ( viewType === LAYOUT_GRID && item.status !== 'trash' ) { + if ( viewType === LAYOUT_GRID ) { if ( ! url ) { return null; } diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 64854fc19db46c..3142dd3949f4d9 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -30,6 +30,7 @@ export const defaultLayouts = { [ LAYOUT_TABLE ]: { layout: { primaryField: 'title', + mediaField: 'featured_media', styles: { title: { maxWidth: 300, From 05f0d1a6fb0b257bbf7b62e1ee6df841e7b7a243 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 10 Sep 2024 14:37:51 +0200 Subject: [PATCH 18/59] remove filename --- .../src/components/post-fields/index.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index dc630dcbfff223..48aaa936dbdabe 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -262,9 +262,6 @@ function usePostFields( viewType ) { const url = media?.source_url; const title = media?.title?.rendered; - const filename = - media?.media_details?.file?.match( '([^/]+$)' )[ 0 ]; - const ref = useRef( null ); return ( @@ -290,7 +287,6 @@ function usePostFields( viewType ) { rowGap={ 0 } columnGap={ 8 } templateColumns="24px 1fr 0.5fr" - rows={ url ? 2 : 0 } > { url && ( <> @@ -337,18 +333,6 @@ function usePostFields( viewType ) { ); } } /> - - { filename } - ) } From c4db3b9e2f6a645043902c41fb7f013bddcdbbbd Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 10 Sep 2024 14:38:03 +0200 Subject: [PATCH 19/59] add border-radius --- .../src/components/post-fields/style.scss | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss index cd875b61ebd7cc..fee496f2522019 100644 --- a/packages/edit-site/src/components/post-fields/style.scss +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -2,11 +2,12 @@ .edit-site-post-featured-image { width: 16px; height: 16px; - border: $radius-small; + border-radius: $radius-small; } .edit-site-post-featured-image-placeholder { width: 16px; height: 16px; + border-radius: $radius-small; } } @@ -23,6 +24,7 @@ .edit-site-post-featured-image-placeholder { width: 24px; height: 24px; + border-radius: $radius-small; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); display: inline-block; padding: 0; @@ -34,12 +36,13 @@ .edit-site-post-featured-image { width: 24px; height: 24px; - border: $radius-small; + border-radius: $radius-small; } .edit-site-dataviews-controls__featured-image { .edit-side-dataviews-controls__featured-image-container { border: $border-width solid $gray-300; + border-radius: $radius-small; padding: 8px 12px; cursor: pointer; &:hover { @@ -53,13 +56,6 @@ white-space: nowrap; } - .edit-site-dataviews-controls__featured-image-filename { - color: $gray-700; - grid-area: 2 / 2 / 2 / 4; - line-height: 16px; - font-size: 12px; - } - .edit-site-dataviews-controls__featured-image-upload-button { padding: 0; height: fit-content; From 83569778dba9dd64dbd6db2e4623e36457b7f7ac Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 18 Sep 2024 17:46:27 +0200 Subject: [PATCH 20/59] migrate featured image to fields package --- package-lock.json | 2 + .../core-data/src/entity-types/attachment.ts | 36 +++- packages/dataviews/src/constants.ts | 3 + .../src/dataforms-layouts/panel/index.tsx | 3 +- .../src/dataviews-layouts/grid/index.tsx | 15 +- .../src/dataviews-layouts/list/index.tsx | 10 +- .../src/dataviews-layouts/table/index.tsx | 4 +- packages/dataviews/src/types.ts | 19 +- packages/edit-site/package.json | 1 + .../src/components/post-edit/index.js | 2 +- .../src/components/post-fields/index.js | 204 +----------------- packages/fields/README.md | 4 + packages/fields/package.json | 2 + .../featured-image/featured-image-edit.tsx | 122 +++++++++++ .../featured-image/featured-image-view.tsx | 137 ++++++++++++ .../fields/src/fields/featured-image/index.ts | 23 ++ .../src/fields/featured-image/style.scss | 27 +++ packages/fields/src/fields/index.ts | 1 + packages/fields/src/style.scss | 1 + 19 files changed, 402 insertions(+), 214 deletions(-) create mode 100644 packages/fields/src/fields/featured-image/featured-image-edit.tsx create mode 100644 packages/fields/src/fields/featured-image/featured-image-view.tsx create mode 100644 packages/fields/src/fields/featured-image/index.ts create mode 100644 packages/fields/src/fields/featured-image/style.scss create mode 100644 packages/fields/src/style.scss diff --git a/package-lock.json b/package-lock.json index dcdc5043ac6d88..73f049ae5c00ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54212,6 +54212,7 @@ "@wordpress/patterns": "file:../patterns", "@wordpress/primitives": "file:../primitives", "@wordpress/private-apis": "file:../private-apis", + "@wordpress/router": "file:../router", "@wordpress/url": "file:../url", "@wordpress/warning": "file:../warning", "change-case": "4.1.2", @@ -68959,6 +68960,7 @@ "@wordpress/patterns": "file:../patterns", "@wordpress/primitives": "file:../primitives", "@wordpress/private-apis": "file:../private-apis", + "@wordpress/router": "file:../router", "@wordpress/url": "file:../url", "@wordpress/warning": "file:../warning", "change-case": "4.1.2", diff --git a/packages/core-data/src/entity-types/attachment.ts b/packages/core-data/src/entity-types/attachment.ts index 703a08611c0e2b..3d4e6814e29cf6 100644 --- a/packages/core-data/src/entity-types/attachment.ts +++ b/packages/core-data/src/entity-types/attachment.ts @@ -14,6 +14,40 @@ import type { import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records'; +interface MediaDetails { + width: number; + height: number; + file: string; + filesize: number; + sizes: { [ key: string ]: Size }; + image_meta: ImageMeta; + original_image?: string; +} +interface ImageMeta { + aperture: string; + credit: string; + camera: string; + caption: string; + created_timestamp: string; + copyright: string; + focal_length: string; + iso: string; + shutter_speed: string; + title: string; + orientation: string; + keywords: any[]; +} + +interface Size { + file: string; + width: number; + height: number; + filesize?: number; + mime_type: string; + source_url: string; + uncropped?: boolean; +} + declare module './base-entity-records' { export namespace BaseEntityRecords { export interface Attachment< C extends Context > { @@ -124,7 +158,7 @@ declare module './base-entity-records' { /** * Details about the media file, specific to its type. */ - media_details: Record< string, string >; + media_details: MediaDetails; /** * The ID for the associated post of the attachment. */ diff --git a/packages/dataviews/src/constants.ts b/packages/dataviews/src/constants.ts index 5ae94c7eb4a135..1583ae1af9c56c 100644 --- a/packages/dataviews/src/constants.ts +++ b/packages/dataviews/src/constants.ts @@ -68,3 +68,6 @@ export const sortIcons = { export const LAYOUT_TABLE = 'table'; export const LAYOUT_GRID = 'grid'; export const LAYOUT_LIST = 'list'; + +// Form layouts. +export const LAYOUT_PANEL = 'panel'; diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index 9f118584998bd3..2cb801aa426587 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -18,6 +18,7 @@ import { closeSmall } from '@wordpress/icons'; */ import { normalizeFields } from '../../normalize-fields'; import type { DataFormProps, NormalizedField, Field } from '../../types'; +import { LAYOUT_PANEL } from '../../constants'; interface FormFieldProps< Item > { data: Item; @@ -111,7 +112,7 @@ function FormField< Item >( { ) } onClick={ onToggle } > - + ) } renderContent={ ( { onClose } ) => ( diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 230ffe0dc50b5c..fd87a3edbb0af8 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -24,6 +24,7 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; +import { LAYOUT_GRID } from '../../constants'; interface GridItemProps< Item > { selection: string[]; @@ -54,10 +55,10 @@ function GridItem< Item >( { const id = getItemId( item ); const isSelected = selection.includes( id ); const renderedMediaField = mediaField?.render ? ( - + ) : null; const renderedPrimaryField = primaryField?.render ? ( - + ) : null; return ( ( { key={ field.id } className="dataviews-view-grid__field-value" > - + ); } ) } @@ -151,7 +155,10 @@ function GridItem< Item >( { className="dataviews-view-grid__field-value" style={ { maxHeight: 'none' } } > - + diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index fb46521fe217b7..c827929aa72c81 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -36,6 +36,7 @@ import { ActionModal, } from '../../components/dataviews-item-actions'; import type { Action, NormalizedField, ViewListProps } from '../../types'; +import { LAYOUT_LIST } from '../../constants'; interface ListViewItemProps< Item > { actions: Action< Item >[]; @@ -178,13 +179,13 @@ function ListItem< Item >( { }, [ actions, item ] ); const renderedMediaField = mediaField?.render ? ( - + ) : (
); const renderedPrimaryField = primaryField?.render ? ( - + ) : null; return ( @@ -249,7 +250,10 @@ function ListItem< Item >( { { field.label } - +
) ) } diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 4e1607b01489c2..17c99b0e7c5a9a 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -19,7 +19,7 @@ import { useEffect, useId, useRef, useState } from '@wordpress/element'; */ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox'; import ItemActions from '../../components/dataviews-item-actions'; -import { sortValues } from '../../constants'; +import { LAYOUT_TABLE, sortValues } from '../../constants'; import { useSomeItemHasAPossibleBulkAction, useHasAPossibleBulkAction, @@ -110,7 +110,7 @@ function TableColumnField< Item >( { primaryField?.id === field.id, } ) } > - +
); } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index e95a43994cd63d..d6979be640e567 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -7,6 +7,12 @@ import type { ReactElement, ComponentType } from 'react'; * Internal dependencies */ import type { SetSelection } from './private-types'; +import type { + LAYOUT_GRID, + LAYOUT_LIST, + LAYOUT_PANEL, + LAYOUT_TABLE, +} from './constants'; export type SortDirection = 'asc' | 'desc'; @@ -106,7 +112,7 @@ export type Field< Item > = { /** * Callback used to render the field. Defaults to `field.getValue`. */ - render?: ComponentType< { item: Item } >; + render?: ComponentType< DataViewRenderFieldProps< Item > >; /** * Callback used to render an edit control for the field. @@ -159,7 +165,7 @@ export type NormalizedField< Item > = Field< Item > & { label: string; header: string | ReactElement; getValue: ( args: { item: Item } ) => any; - render: ComponentType< { item: Item } >; + render: ComponentType< DataViewRenderFieldProps< Item > >; Edit: ComponentType< DataFormControlProps< Item > >; sort: ( a: Item, b: Item, direction: SortDirection ) => number; isValid: ( item: Item, context?: ValidationContext ) => boolean; @@ -189,6 +195,15 @@ export type DataFormControlProps< Item > = { hideLabelFromVision?: boolean; }; +export type DataViewRenderFieldProps< Item > = { + item: Item; + view: + | typeof LAYOUT_LIST + | typeof LAYOUT_GRID + | typeof LAYOUT_TABLE + | typeof LAYOUT_PANEL; +}; + /** * The filters applied to the dataset. */ diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 43bcf68aa68e68..a7b22e9c314300 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -48,6 +48,7 @@ "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/escape-html": "file:../escape-html", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 2bc789b4bdc7d5..bb0e66de5512be 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -72,7 +72,7 @@ function PostEditForm( { postType, postId } ) { for ( const id of ids ) { if ( edits.status !== 'future' && - record.status === 'future' && + record?.status === 'future' && new Date( record.date ) > new Date() ) { edits.date = null; diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index 48aaa936dbdabe..c40b86c8026536 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -8,12 +8,11 @@ import clsx from 'clsx'; */ import { __, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; +import { featuredImageField } from '@wordpress/fields'; import { createInterpolateElement, useMemo, useState, - useCallback, - useRef, } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; import { @@ -24,15 +23,8 @@ import { pending, notAllowed, commentAuthorAvatar as authorIcon, - lineSolid, } from '@wordpress/icons'; -import { - __experimentalHStack as HStack, - __experimentalText as Text, - __experimentalGrid as Grid, - Icon, - Button, -} from '@wordpress/components'; +import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; @@ -41,13 +33,10 @@ import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; */ import { LAYOUT_GRID, - LAYOUT_LIST, LAYOUT_TABLE, OPERATOR_IS_ANY, } from '../../utils/constants'; -import { default as Link, useLink } from '../routes/link'; -import Media from '../media'; -import { MediaUpload } from '@wordpress/block-editor'; +import { default as Link } from '../routes/link'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. @@ -91,78 +80,6 @@ const getFormattedDate = ( dateToDisplay ) => getDate( dateToDisplay ) ); -function FeaturedImage( { item, viewType } ) { - const mediaId = item.featured_media; - - const media = useSelect( - ( select ) => { - const { getEntityRecord } = select( coreStore ); - return getEntityRecord( 'root', 'media', mediaId ); - }, - [ mediaId ] - ); - const url = media?.source_url; - const title = media?.title?.rendered; - - const { onClick } = useLink( { - postId: item.id, - postType: item.type, - canvas: 'edit', - } ); - - if ( viewType === LAYOUT_GRID ) { - if ( ! url ) { - return null; - } - return ( - - ); - } - - if ( viewType === LAYOUT_LIST ) { - if ( ! url ) { - return null; - } - - return ( -
- -
- ); - } - - if ( ! url ) { - return ( - - - { __( 'Choose an image…' ) } - - ); - } - - return ( - - - { title } - - ); -} - function PostStatusField( { item } ) { const status = STATUSES.find( ( { value } ) => value === item.status ); const label = status?.label || item.status; @@ -232,120 +149,7 @@ function usePostFields( viewType ) { const fields = useMemo( () => [ - { - id: 'featured_media', - label: __( 'Featured Image' ), - type: 'image', - render: ( { item } ) => ( - - ), - Edit: ( { field, onChange, data } ) => { - const { id } = field; - - const value = field.getValue( { item: data } ); - - const media = useSelect( - ( select ) => { - const { getEntityRecord } = select( coreStore ); - return getEntityRecord( 'root', 'media', value ); - }, - [ value ] - ); - - const onChangeControl = useCallback( - ( newValue ) => - onChange( { - [ id ]: newValue, - } ), - [ id, onChange ] - ); - - const url = media?.source_url; - const title = media?.title?.rendered; - const ref = useRef( null ); - - return ( -
-
- { - onChangeControl( selectedMedia.id ); - } } - allowedTypes={ [ 'image' ] } - render={ ( { open } ) => { - return ( -
{ - open(); - } } - onKeyDown={ open } - > - - { url && ( - <> - - - { title } - - - ) } - { ! url && ( - <> - - - { __( - 'Choose an image…' - ) } - - - ) } - { url && ( - <> -
- ); - } } - /> -
-
- ); - }, - enableSorting: false, - }, + featuredImageField, { label: __( 'Title' ), id: 'title', diff --git a/packages/fields/README.md b/packages/fields/README.md index 842fab02606af8..002b27641a870d 100644 --- a/packages/fields/README.md +++ b/packages/fields/README.md @@ -34,6 +34,10 @@ Undocumented declaration. Undocumented declaration. +### featuredImageField + +Undocumented declaration. + ### orderField Undocumented declaration. diff --git a/packages/fields/package.json b/packages/fields/package.json index 2e417c9f4de570..44f88e9cd157d0 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -34,6 +34,7 @@ "dependencies": { "@babel/runtime": "^7.16.0", "@wordpress/blob": "file:../blob", + "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -49,6 +50,7 @@ "@wordpress/patterns": "file:../patterns", "@wordpress/primitives": "file:../primitives", "@wordpress/private-apis": "file:../private-apis", + "@wordpress/router": "file:../router", "@wordpress/url": "file:../url", "@wordpress/warning": "file:../warning", "change-case": "4.1.2", diff --git a/packages/fields/src/fields/featured-image/featured-image-edit.tsx b/packages/fields/src/fields/featured-image/featured-image-edit.tsx new file mode 100644 index 00000000000000..b503f3fa5cc196 --- /dev/null +++ b/packages/fields/src/fields/featured-image/featured-image-edit.tsx @@ -0,0 +1,122 @@ +/** + * WordPress dependencies + */ +import { + Button, + __experimentalGrid as Grid, + __experimentalText as Text, +} from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useCallback, useRef } from '@wordpress/element'; +// @ts-ignore +import { MediaUpload } from '@wordpress/block-editor'; +import { lineSolid } from '@wordpress/icons'; +import { store as coreStore } from '@wordpress/core-data'; +import type { DataFormControlProps } from '@wordpress/dataviews'; +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; + +export const FeaturedImageEdit = ( { + data, + field, + onChange, +}: DataFormControlProps< BasePost > ) => { + const { id } = field; + + const value = field.getValue( { item: data } ); + + const media = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + return getEntityRecord( 'root', 'media', value ); + }, + [ value ] + ); + + const onChangeControl = useCallback( + ( newValue: number ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const url = media?.source_url; + const title = media?.title?.rendered; + const ref = useRef( null ); + + return ( +
+
+ { + onChangeControl( selectedMedia.id ); + } } + allowedTypes={ [ 'image' ] } + render={ ( { open }: { open: () => void } ) => { + return ( +
{ + open(); + } } + onKeyDown={ open } + > + + { url && ( + <> + + + { title } + + + ) } + { ! url && ( + <> + + + { __( 'Choose an image…' ) } + + + ) } + { url && ( + <> +
+ ); + } } + /> +
+
+ ); +}; diff --git a/packages/fields/src/fields/featured-image/featured-image-view.tsx b/packages/fields/src/fields/featured-image/featured-image-view.tsx new file mode 100644 index 00000000000000..52118777e1b95e --- /dev/null +++ b/packages/fields/src/fields/featured-image/featured-image-view.tsx @@ -0,0 +1,137 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { useCallback } from '@wordpress/element'; +import type { Attachment } from '@wordpress/core-data'; +import { store as coreStore, useEntityRecord } from '@wordpress/core-data'; +// @ts-ignore +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { __experimentalHStack as HStack } from '@wordpress/components'; +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { __ } from '@wordpress/i18n'; +import type { BasePost } from '../../types'; +import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; +import { getItemTitle } from '../../actions/utils'; + +const { useHistory } = unlock( routerPrivateApis ); + +const Media = ( { + id, + size = [ 'large', 'medium', 'thumbnail' ], + ...props +}: { + id: string; + size?: Array< 'large' | 'medium' | 'full' | 'thumbnail' >; +} & Record< string, any > ) => { + const { record: media } = useEntityRecord< Attachment >( + 'root', + 'media', + id + ); + const currentSize = + size.find( ( s ) => !! media?.media_details?.sizes[ s ] ) ?? ''; + + const mediaUrl = + media?.media_details?.sizes[ currentSize ]?.source_url || + media?.source_url; + + if ( ! mediaUrl ) { + return null; + } + + return {; +}; + +export const FeaturedImageView = ( { + item, + view, +}: DataViewRenderFieldProps< BasePost > ) => { + const mediaId = item.featured_media; + + const media = useSelect( + ( select ) => { + const { getEntityRecord } = select( coreStore ); + return mediaId ? getEntityRecord( 'root', 'media', mediaId ) : null; + }, + [ mediaId ] + ); + const url = media?.source_url; + const title = media?.title?.rendered; + + const history = useHistory(); + + const onClick = useCallback( () => { + const params = { + post: item.id, + post_type: item.type, + canvas: 'edit', + }; + + history.push( params ); + }, [ history, item.id, item.type ] ); + + if ( view === 'grid' ) { + if ( ! url ) { + return null; + } + return ( + + ); + } + + if ( view === 'list' ) { + if ( ! url ) { + return <>; + } + + return ( +
+ +
+ ); + } + + if ( ! url ) { + return ( + + + { view === 'panel' ? ( + { __( 'Choose an image…' ) } + ) : null } + + ); + } + + return ( + + + { view === 'panel' ? { title } : null } + + ); +}; diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts new file mode 100644 index 00000000000000..c4d806c1b0aeb9 --- /dev/null +++ b/packages/fields/src/fields/featured-image/index.ts @@ -0,0 +1,23 @@ +/** + * WordPress dependencies + */ +import type { Field } from '@wordpress/dataviews'; + +/** + * Internal dependencies + */ +import type { BasePost } from '../../types'; +import { __ } from '@wordpress/i18n'; +import { FeaturedImageEdit } from './featured-image-edit'; +import { FeaturedImageView } from './featured-image-view'; + +const featuredImageField: Field< BasePost > = { + id: 'featured_media', + label: __( 'Featured Image' ), + getValue: ( { item } ) => item.featured_media, + Edit: FeaturedImageEdit, + render: FeaturedImageView, + enableSorting: false, +}; + +export default featuredImageField; diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss new file mode 100644 index 00000000000000..1b65077840cb39 --- /dev/null +++ b/packages/fields/src/fields/featured-image/style.scss @@ -0,0 +1,27 @@ +.fields-controls__featured-image { + border: none; + padding: 0; + .fields-controls__featured-image-container { + @include input-control; + margin: 0; + } + + .fields-controls__featured-image-placeholder { + width: 200px; + height: 200px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + display: inline-block; + margin: 6px 12px; + background: + $white + linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); + } + + img { + width: 200px; + margin: 6px 12px; + height: 200px; + border: $radius-small; + object-fit: cover; + } +} diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts index 63ff87842fa4c9..62a1e1485e75e8 100644 --- a/packages/fields/src/fields/index.ts +++ b/packages/fields/src/fields/index.ts @@ -1,2 +1,3 @@ export { default as titleField } from './title'; export { default as orderField } from './order'; +export { default as featuredImageField } from './featured-image'; diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss new file mode 100644 index 00000000000000..701865b89025dd --- /dev/null +++ b/packages/fields/src/style.scss @@ -0,0 +1 @@ +@import "./fields/featured-image/style.scss"; From e27dec1f8391106c98ccf2f967eb8e1cfeff3685 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 19 Sep 2024 10:17:25 +0200 Subject: [PATCH 21/59] fix CSS --- .../src/components/post-fields/style.scss | 73 ------------ packages/edit-site/src/style.scss | 2 + .../featured-image/featured-image-edit.tsx | 10 +- .../featured-image/featured-image-view.tsx | 20 ++-- .../src/fields/featured-image/style.scss | 105 ++++++++++++++---- 5 files changed, 104 insertions(+), 106 deletions(-) diff --git a/packages/edit-site/src/components/post-fields/style.scss b/packages/edit-site/src/components/post-fields/style.scss index fee496f2522019..adeaf9a2678253 100644 --- a/packages/edit-site/src/components/post-fields/style.scss +++ b/packages/edit-site/src/components/post-fields/style.scss @@ -1,76 +1,3 @@ -.dataforms-layouts-panel__field-control { - .edit-site-post-featured-image { - width: 16px; - height: 16px; - border-radius: $radius-small; - } - .edit-site-post-featured-image-placeholder { - width: 16px; - height: 16px; - border-radius: $radius-small; - } -} - -.edit-site-post-featured-image-container { - .edit-site-post-featured-image-placeholder { - margin: 0; - } - - span { - margin-right: auto; - } -} - -.edit-site-post-featured-image-placeholder { - width: 24px; - height: 24px; - border-radius: $radius-small; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); - display: inline-block; - padding: 0; - background: - $white - linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); -} - -.edit-site-post-featured-image { - width: 24px; - height: 24px; - border-radius: $radius-small; -} - -.edit-site-dataviews-controls__featured-image { - .edit-side-dataviews-controls__featured-image-container { - border: $border-width solid $gray-300; - border-radius: $radius-small; - padding: 8px 12px; - cursor: pointer; - &:hover { - background-color: $gray-100; - } - } - - span { - align-self: center; - text-align: start; - white-space: nowrap; - } - - .edit-site-dataviews-controls__featured-image-upload-button { - padding: 0; - height: fit-content; - &:hover, - &:focus { - border: 0; - color: unset; - } - } - - .edit-site-dataviews-controls__featured-image-remove-button { - place-self: end; - } -} - .components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown { z-index: z-index(".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown"); } diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 7f0f65909598f4..6445b1685cd555 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,4 +1,6 @@ @import "../../dataviews/src/style.scss"; +@import "../../fields/src/fields/featured-image/style.scss"; + @import "./components/add-new-template/style.scss"; @import "./components/block-editor/style.scss"; diff --git a/packages/fields/src/fields/featured-image/featured-image-edit.tsx b/packages/fields/src/fields/featured-image/featured-image-edit.tsx index b503f3fa5cc196..a90d037c2b660b 100644 --- a/packages/fields/src/fields/featured-image/featured-image-edit.tsx +++ b/packages/fields/src/fields/featured-image/featured-image-edit.tsx @@ -49,8 +49,8 @@ export const FeaturedImageEdit = ( { const ref = useRef( null ); return ( -
-
+
+
{ onChangeControl( selectedMedia.id ); @@ -75,7 +75,7 @@ export const FeaturedImageEdit = ( { { url && ( <> @@ -90,7 +90,7 @@ export const FeaturedImageEdit = ( { ) } { ! url && ( <> - + { __( 'Choose an image…' ) } @@ -100,7 +100,7 @@ export const FeaturedImageEdit = ( { <> + + ), + }, + list: { + NoUrl: <>, + WithUrl: ( +
+ +
+ ), + }, + panel: { + NoUrl: ( + + + { __( 'Choose an image…' ) } + + ), + WithUrl: ( + + + { title } + + ), + }, + table: { + NoUrl: ( + + ), + WithUrl: ( + + + + ), + }, +} ); + export const FeaturedImageView = ( { item, view, @@ -75,81 +170,13 @@ export const FeaturedImageView = ( { history.push( params ); }, [ history, item.id, item.type ] ); - if ( view === 'grid' ) { - if ( ! url ) { - return null; - } - return ( - - ); - } - - if ( view === 'list' ) { - if ( ! url ) { - return <>; - } + const component = getComponentToDisplay( { item, title, url, onClick } )[ + view + ]; - return ( -
- -
- ); - } - - if ( ! url ) { - return ( - - - { view === 'panel' ? ( - { __( 'Choose an image…' ) } - ) : null } - - ); + if ( url ) { + return component.WithUrl; } - if ( view === 'panel' ) { - return ( - - - { title } - - ); - } - - return ( - - - { title } - - ); + return component.NoUrl; }; diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss index 628ee36ecfafbd..a9a0cc49107682 100644 --- a/packages/fields/src/fields/featured-image/style.scss +++ b/packages/fields/src/fields/featured-image/style.scss @@ -1,6 +1,4 @@ .fields-controls__featured-image-placeholder { - width: 16px; - height: 16px; border-radius: $radius-small; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); display: inline-block; From 1b84ac0d3244bd88fbae54524978b25df032b903 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Fri, 20 Sep 2024 15:30:15 +0200 Subject: [PATCH 28/59] use same placeholder style grid/list layout --- .../featured-image/featured-image-view.tsx | 8 +------- .../src/fields/featured-image/style.scss | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/fields/src/fields/featured-image/featured-image-view.tsx b/packages/fields/src/fields/featured-image/featured-image-view.tsx index 1dac431d239c62..6720884122d82f 100644 --- a/packages/fields/src/fields/featured-image/featured-image-view.tsx +++ b/packages/fields/src/fields/featured-image/featured-image-view.tsx @@ -120,13 +120,7 @@ const getComponentToDisplay = ( { }, table: { NoUrl: ( - + ), WithUrl: ( diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss index a9a0cc49107682..edad963f2c6c4a 100644 --- a/packages/fields/src/fields/featured-image/style.scss +++ b/packages/fields/src/fields/featured-image/style.scss @@ -6,6 +6,26 @@ background: $white linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); + + &__table { + width: 32px; + height: 32px; + background-color: $gray-100; + border-radius: $grid-unit-05; + position: relative; + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.1); + border-radius: $grid-unit-05; + pointer-events: none; + } + } } .fields-controls__featured-image-title { From 6ca01ff227473510586a8232eb5f18138dd1ec25 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Fri, 20 Sep 2024 15:39:56 +0200 Subject: [PATCH 29/59] fix tsconfig --- packages/fields/tsconfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index c55be59acf40f0..ce3de392731884 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -22,8 +22,8 @@ { "path": "../blob" }, { "path": "../core-data" }, { "path": "../hooks" }, - { "path": "../html-entities" } + { "path": "../html-entities" }, + { "path": "../block-editor" } ], - "include": [ "src" ], - "exclude": [ "@wordpress/editor" ] + "include": [ "src" ] } From c448c494b25d9bf31b5e3c0b76c07e2f9a88bd04 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 09:52:43 +0200 Subject: [PATCH 30/59] add type --- packages/dataviews/src/types.ts | 2 +- packages/fields/src/fields/featured-image/index.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 34fcf2cef8c045..73e4dc1b923e08 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -48,7 +48,7 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type FieldType = 'text' | 'integer' | 'datetime'; +export type FieldType = 'text' | 'integer' | 'datetime' | string; export type ValidationContext = { elements?: Option[]; diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts index c4d806c1b0aeb9..bbb1e98b1d6852 100644 --- a/packages/fields/src/fields/featured-image/index.ts +++ b/packages/fields/src/fields/featured-image/index.ts @@ -13,6 +13,7 @@ import { FeaturedImageView } from './featured-image-view'; const featuredImageField: Field< BasePost > = { id: 'featured_media', + type: 'featured-image', label: __( 'Featured Image' ), getValue: ( { item } ) => item.featured_media, Edit: FeaturedImageEdit, From 2b595c20f63b245b7fbbbe27a512ac11e6079701 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 09:56:28 +0200 Subject: [PATCH 31/59] remove mediaField from layout table --- .../edit-site/src/components/sidebar-dataviews/default-views.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 5b468ce8e897e3..72f4c94fe6bcdd 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -30,7 +30,6 @@ export const defaultLayouts = { [ LAYOUT_TABLE ]: { layout: { primaryField: 'title', - mediaField: 'featured_media', styles: { title: { maxWidth: 300, From 9cc6d80958c9a240524cbe0e715b81a38030e37a Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 10:52:19 +0200 Subject: [PATCH 32/59] update type --- packages/fields/src/fields/featured-image/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts index bbb1e98b1d6852..eda5249f16a6f2 100644 --- a/packages/fields/src/fields/featured-image/index.ts +++ b/packages/fields/src/fields/featured-image/index.ts @@ -13,7 +13,7 @@ import { FeaturedImageView } from './featured-image-view'; const featuredImageField: Field< BasePost > = { id: 'featured_media', - type: 'featured-image', + type: 'media', label: __( 'Featured Image' ), getValue: ( { item } ) => item.featured_media, Edit: FeaturedImageEdit, From 01a57a861348a49d641b7638be365442efbca97a Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 10:57:53 +0200 Subject: [PATCH 33/59] use text as type --- packages/dataviews/src/types.ts | 2 +- packages/fields/src/fields/featured-image/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 73e4dc1b923e08..34fcf2cef8c045 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -48,7 +48,7 @@ export type Operator = | 'isAll' | 'isNotAll'; -export type FieldType = 'text' | 'integer' | 'datetime' | string; +export type FieldType = 'text' | 'integer' | 'datetime'; export type ValidationContext = { elements?: Option[]; diff --git a/packages/fields/src/fields/featured-image/index.ts b/packages/fields/src/fields/featured-image/index.ts index eda5249f16a6f2..44f9a1b4064648 100644 --- a/packages/fields/src/fields/featured-image/index.ts +++ b/packages/fields/src/fields/featured-image/index.ts @@ -13,7 +13,7 @@ import { FeaturedImageView } from './featured-image-view'; const featuredImageField: Field< BasePost > = { id: 'featured_media', - type: 'media', + type: 'text', label: __( 'Featured Image' ), getValue: ( { item } ) => item.featured_media, Edit: FeaturedImageEdit, From 7b1e40a6f0a56a990c97e45f1c57ffa12ba899d5 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 11:03:45 +0200 Subject: [PATCH 34/59] use media-utils package --- packages/fields/package.json | 2 +- .../fields/src/fields/featured-image/featured-image-edit.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fields/package.json b/packages/fields/package.json index 577f966abc955f..2e725611a14a53 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -34,7 +34,6 @@ "@babel/runtime": "7.25.7", "@wordpress/api-fetch": "file:../api-fetch", "@wordpress/blob": "file:../blob", - "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", @@ -46,6 +45,7 @@ "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/media-utils": "file:../media-utils", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", "@wordpress/primitives": "file:../primitives", diff --git a/packages/fields/src/fields/featured-image/featured-image-edit.tsx b/packages/fields/src/fields/featured-image/featured-image-edit.tsx index 67006533da011b..b0dc612cdcfa50 100644 --- a/packages/fields/src/fields/featured-image/featured-image-edit.tsx +++ b/packages/fields/src/fields/featured-image/featured-image-edit.tsx @@ -5,7 +5,7 @@ import { Button, __experimentalGrid as Grid } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useCallback, useRef } from '@wordpress/element'; // @ts-ignore -import { MediaUpload } from '@wordpress/block-editor'; +import { MediaUpload } from '@wordpress/media-utils'; import { lineSolid } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; import type { DataFormControlProps } from '@wordpress/dataviews'; From 6592d3652ad22d751038fd9bf375ea2da5e9dafa Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 11:21:40 +0200 Subject: [PATCH 35/59] fix tsconfig --- packages/fields/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fields/tsconfig.json b/packages/fields/tsconfig.json index c7d5b9b0a30ac8..c553ee023993d0 100644 --- a/packages/fields/tsconfig.json +++ b/packages/fields/tsconfig.json @@ -24,7 +24,7 @@ { "path": "../core-data" }, { "path": "../hooks" }, { "path": "../html-entities" }, - { "path": "../block-editor" }, + { "path": "../media-utils" }, { "path": "../router" } ], "include": [ "src" ] From c2994e0ab6850e23b284d1a82ad7b4608b13311d Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 15:45:39 +0200 Subject: [PATCH 36/59] remove view prop --- packages/dataviews/src/constants.ts | 3 - .../src/dataforms-layouts/panel/index.tsx | 3 +- .../src/dataviews-layouts/grid/index.tsx | 15 +- .../src/dataviews-layouts/list/index.tsx | 10 +- .../src/dataviews-layouts/table/index.tsx | 4 +- packages/dataviews/src/types.ts | 11 -- .../featured-image/featured-image-view.tsx | 158 ++---------------- .../src/fields/featured-image/style.scss | 59 +++---- 8 files changed, 42 insertions(+), 221 deletions(-) diff --git a/packages/dataviews/src/constants.ts b/packages/dataviews/src/constants.ts index 1583ae1af9c56c..5ae94c7eb4a135 100644 --- a/packages/dataviews/src/constants.ts +++ b/packages/dataviews/src/constants.ts @@ -68,6 +68,3 @@ export const sortIcons = { export const LAYOUT_TABLE = 'table'; export const LAYOUT_GRID = 'grid'; export const LAYOUT_LIST = 'list'; - -// Form layouts. -export const LAYOUT_PANEL = 'panel'; diff --git a/packages/dataviews/src/dataforms-layouts/panel/index.tsx b/packages/dataviews/src/dataforms-layouts/panel/index.tsx index a7efaa572d06b7..5d3bbc532ad457 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/index.tsx +++ b/packages/dataviews/src/dataforms-layouts/panel/index.tsx @@ -19,7 +19,6 @@ import { closeSmall } from '@wordpress/icons'; import { normalizeFields } from '../../normalize-fields'; import { getVisibleFields } from '../get-visible-fields'; import type { DataFormProps, NormalizedField } from '../../types'; -import { LAYOUT_PANEL } from '../../constants'; interface FormFieldProps< Item > { data: Item; @@ -111,7 +110,7 @@ function FormField< Item >( { ) } onClick={ onToggle } > - + ) } renderContent={ ( { onClose } ) => ( diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index fd87a3edbb0af8..230ffe0dc50b5c 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -24,7 +24,6 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; -import { LAYOUT_GRID } from '../../constants'; interface GridItemProps< Item > { selection: string[]; @@ -55,10 +54,10 @@ function GridItem< Item >( { const id = getItemId( item ); const isSelected = selection.includes( id ); const renderedMediaField = mediaField?.render ? ( - + ) : null; const renderedPrimaryField = primaryField?.render ? ( - + ) : null; return ( ( { key={ field.id } className="dataviews-view-grid__field-value" > - + ); } ) } @@ -155,10 +151,7 @@ function GridItem< Item >( { className="dataviews-view-grid__field-value" style={ { maxHeight: 'none' } } > - + diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index 900db73001f3ee..e737b18f5b02a9 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -36,7 +36,6 @@ import { ActionModal, } from '../../components/dataviews-item-actions'; import type { Action, NormalizedField, ViewListProps } from '../../types'; -import { LAYOUT_LIST } from '../../constants'; interface ListViewItemProps< Item > { actions: Action< Item >[]; @@ -177,13 +176,13 @@ function ListItem< Item >( { }, [ actions, item ] ); const renderedMediaField = mediaField?.render ? ( - + ) : (
); const renderedPrimaryField = primaryField?.render ? ( - + ) : null; const usedActions = eligibleActions?.length > 0 && ( @@ -281,10 +280,7 @@ function ListItem< Item >( { { field.label } - +
) ) } diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 17c99b0e7c5a9a..4e1607b01489c2 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -19,7 +19,7 @@ import { useEffect, useId, useRef, useState } from '@wordpress/element'; */ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox'; import ItemActions from '../../components/dataviews-item-actions'; -import { LAYOUT_TABLE, sortValues } from '../../constants'; +import { sortValues } from '../../constants'; import { useSomeItemHasAPossibleBulkAction, useHasAPossibleBulkAction, @@ -110,7 +110,7 @@ function TableColumnField< Item >( { primaryField?.id === field.id, } ) } > - +
); } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 34fcf2cef8c045..2a335dce3af32b 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -7,12 +7,6 @@ import type { ReactElement, ComponentType } from 'react'; * Internal dependencies */ import type { SetSelection } from './private-types'; -import type { - LAYOUT_GRID, - LAYOUT_LIST, - LAYOUT_PANEL, - LAYOUT_TABLE, -} from './constants'; export type SortDirection = 'asc' | 'desc'; @@ -189,11 +183,6 @@ export type DataFormControlProps< Item > = { export type DataViewRenderFieldProps< Item > = { item: Item; - view: - | typeof LAYOUT_LIST - | typeof LAYOUT_GRID - | typeof LAYOUT_TABLE - | typeof LAYOUT_PANEL; }; /** diff --git a/packages/fields/src/fields/featured-image/featured-image-view.tsx b/packages/fields/src/fields/featured-image/featured-image-view.tsx index 6720884122d82f..36793e6f2ff9ab 100644 --- a/packages/fields/src/fields/featured-image/featured-image-view.tsx +++ b/packages/fields/src/fields/featured-image/featured-image-view.tsx @@ -2,143 +2,16 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { useCallback } from '@wordpress/element'; -import type { Attachment } from '@wordpress/core-data'; -import { store as coreStore, useEntityRecord } from '@wordpress/core-data'; -// @ts-ignore -import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { __experimentalHStack as HStack } from '@wordpress/components'; +import { store as coreStore } from '@wordpress/core-data'; + /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; -import { __ } from '@wordpress/i18n'; import type { BasePost } from '../../types'; import type { DataViewRenderFieldProps } from '@wordpress/dataviews'; -import { getItemTitle } from '../../actions/utils'; - -const { useHistory } = unlock( routerPrivateApis ); - -const Media = ( { - id, - size = [ 'large', 'medium', 'thumbnail' ], - ...props -}: { - id: number; - size?: Array< 'large' | 'medium' | 'full' | 'thumbnail' >; -} & Record< string, any > ) => { - const { record: media } = useEntityRecord< Attachment >( - 'root', - 'media', - id - ); - - const currentSize = - size.find( ( s ) => !! media?.media_details?.sizes[ s ] ) ?? ''; - - const mediaUrl = - media?.media_details?.sizes[ currentSize ]?.source_url || - media?.source_url; - - if ( ! mediaUrl ) { - return null; - } - - return {; -}; - -const getComponentToDisplay = ( { - item, - url, - title, - onClick, -}: { - item: BasePost; - title: string | undefined; - url: string | undefined; - onClick: () => void; -} ) => ( { - grid: { - NoUrl: <>, - WithUrl: ( - <> - - - ), - }, - list: { - NoUrl: <>, - WithUrl: ( -
- -
- ), - }, - panel: { - NoUrl: ( - - - { __( 'Choose an image…' ) } - - ), - WithUrl: ( - - - { title } - - ), - }, - table: { - NoUrl: ( - - ), - WithUrl: ( - - - - ), - }, -} ); export const FeaturedImageView = ( { item, - view, }: DataViewRenderFieldProps< BasePost > ) => { const mediaId = item.featured_media; @@ -150,27 +23,16 @@ export const FeaturedImageView = ( { [ mediaId ] ); const url = media?.source_url; - const title = media?.title?.rendered; - - const history = useHistory(); - - const onClick = useCallback( () => { - const params = { - post: item.id, - post_type: item.type, - canvas: 'edit', - }; - - history.push( params ); - }, [ history, item.id, item.type ] ); - - const component = getComponentToDisplay( { item, title, url, onClick } )[ - view - ]; if ( url ) { - return component.WithUrl; + return ( + + ); } - return component.NoUrl; + return ; }; diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss index edad963f2c6c4a..46d37960199ead 100644 --- a/packages/fields/src/fields/featured-image/style.scss +++ b/packages/fields/src/fields/featured-image/style.scss @@ -6,26 +6,6 @@ background: $white linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%); - - &__table { - width: 32px; - height: 32px; - background-color: $gray-100; - border-radius: $grid-unit-05; - position: relative; - - &::after { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - box-shadow: inset 0 0 0 $border-width rgba(0, 0, 0, 0.1); - border-radius: $grid-unit-05; - pointer-events: none; - } - } } .fields-controls__featured-image-title { @@ -37,6 +17,8 @@ } .fields-controls__featured-image-image { + width: 100%; + height: 100%; border-radius: $radius-small; align-self: center; } @@ -88,23 +70,26 @@ fieldset.fields-controls__featured-image { } } -.fields-controls__featured-image-button { - box-shadow: none; - border: none; - padding: 0; - background-color: unset; - box-sizing: border-box; - cursor: pointer; - overflow: hidden; - height: 100%; - width: 100%; - border-radius: $grid-unit-05; +.dataforms-layouts-panel__field-control { + .fields-controls__featured-image-image { + width: 16px; + height: 16px; + } + + .fields-controls__featured-image-placeholder { + width: 16px; + height: 16px; + } +} + +.dataviews-view-table__cell-content-wrapper { + .fields-controls__featured-image-image { + width: 32px; + height: 32px; + } - &: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; + .fields-controls__featured-image-placeholder { + width: 32px; + height: 32px; } } From b039310229a9c52252615070a8462bbb36b3b4f5 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 16:10:27 +0200 Subject: [PATCH 37/59] revert changes --- packages/fields/src/actions/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fields/src/actions/utils.ts b/packages/fields/src/actions/utils.ts index 4d4ccc67270f52..14e8edae4be048 100644 --- a/packages/fields/src/actions/utils.ts +++ b/packages/fields/src/actions/utils.ts @@ -34,10 +34,10 @@ export function getItemTitle( item: Post ) { if ( typeof item.title === 'string' ) { return decodeEntities( item.title ); } - if ( item.title && 'rendered' in item.title ) { + if ( 'rendered' in item.title ) { return decodeEntities( item.title.rendered ); } - if ( item.title && 'raw' in item?.title ) { + if ( 'raw' in item.title ) { return decodeEntities( item.title.raw ); } return ''; From 42f90f4e50aab6f8b837a4d01e4c6c6acb4f517e Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 22 Oct 2024 16:11:06 +0200 Subject: [PATCH 38/59] generate package-lock.json --- package-lock.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index 43c4939a201213..3edb4e4458d109 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55268,6 +55268,7 @@ "@wordpress/editor": "file:../editor", "@wordpress/element": "file:../element", "@wordpress/escape-html": "file:../escape-html", + "@wordpress/fields": "file:../fields", "@wordpress/hooks": "file:../hooks", "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", @@ -55674,6 +55675,7 @@ "@wordpress/html-entities": "file:../html-entities", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", + "@wordpress/media-utils": "file:../media-utils", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", "@wordpress/primitives": "file:../primitives", From 1c3bdb9673fcaf1081d2228c3eb7dd0335f00fce Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 23 Oct 2024 13:24:05 +0200 Subject: [PATCH 39/59] add onClick and isClickable props --- .../src/components/dataviews-context/index.ts | 4 ++ .../src/components/dataviews-layout/index.tsx | 4 ++ .../src/components/dataviews/index.tsx | 6 +++ .../src/dataviews-layouts/grid/index.tsx | 53 ++++++++++++++++++- .../src/dataviews-layouts/grid/style.scss | 9 ++++ .../src/dataviews-layouts/table/index.tsx | 35 ++++++++++++ packages/dataviews/src/types.ts | 2 + .../src/components/post-fields/index.js | 36 +++---------- .../src/components/post-list/index.js | 12 +++-- .../src/components/post-list/style.scss | 31 +++++++++-- 10 files changed, 155 insertions(+), 37 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 3936288b3095b0..7eb62241873119 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,6 +26,8 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; + onClick: ( item: Item ) => void; + isClickable: ( item: Item ) => boolean; density: number; }; @@ -43,6 +45,8 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, + onClick: () => {}, + isClickable: () => false, density: 0, } ); diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index bae4071fe2f773..5df84cc47aa86e 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -28,6 +28,8 @@ export default function DataViewsLayout() { onChangeSelection, setOpenedFilter, density, + onClick, + isClickable, } = useContext( DataViewsContext ); const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) @@ -44,6 +46,8 @@ export default function DataViewsLayout() { onChangeSelection={ onChangeSelection } selection={ selection } setOpenedFilter={ setOpenedFilter } + onClick={ onClick } + isClickable={ isClickable } view={ view } density={ density } /> diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index da60ab15ecadec..e71fd42fde578f 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -44,6 +44,8 @@ type DataViewsProps< Item > = { defaultLayouts: SupportedLayouts; selection?: string[]; onChangeSelection?: ( items: string[] ) => void; + onClick?: ( item: Item ) => void; + isClickable?: ( item: Item ) => boolean; header?: ReactNode; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } @@ -65,6 +67,8 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, + onClick, + isClickable, header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); @@ -110,6 +114,8 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, + isClickable: isClickable ?? ( () => false ), + onClick: onClick ?? ( () => {} ), density, } } > diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 230ffe0dc50b5c..44189e20e6f952 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -29,6 +29,8 @@ interface GridItemProps< Item > { selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; + onClick: ( item: Item ) => void; + isClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; mediaField?: NormalizedField< Item >; @@ -41,6 +43,8 @@ interface GridItemProps< Item > { function GridItem< Item >( { selection, onChangeSelection, + onClick, + isClickable, getItemId, item, actions, @@ -59,6 +63,7 @@ function GridItem< Item >( { const renderedPrimaryField = primaryField?.render ? ( ) : null; + return ( ( { } } } > -
+
{ + if ( isClickable( item ) ) { + onClick( item ); + } + } } + onKeyDown={ ( event ) => { + if ( + ( event.key === 'Enter' || event.key === '' ) && + isClickable( item ) + ) { + onClick( item ); + } + } } + > { renderedMediaField }
( { justify="space-between" className="dataviews-view-grid__title-actions" > - + { + if ( isClickable( item ) ) { + onClick( item ); + } + } } + onKeyDown={ ( event ) => { + if ( + ( event.key === 'Enter' || event.key === '' ) && + isClickable( item ) + ) { + onClick( item ); + } + } } + > { renderedPrimaryField } @@ -170,6 +215,8 @@ export default function ViewGrid< Item >( { getItemId, isLoading, onChangeSelection, + onClick, + isClickable, selection, view, density, @@ -223,6 +270,8 @@ export default function ViewGrid< Item >( { key={ getItemId( item ) } selection={ selection } onChangeSelection={ onChangeSelection } + onClick={ onClick } + isClickable={ isClickable } getItemId={ getItemId } item={ item } actions={ actions } diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 6286ed94685a04..25b21badc70a68 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -17,8 +17,13 @@ .dataviews-view-grid__primary-field { min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button + + &--clickable { + cursor: pointer; + } } + &.is-selected { .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { color: $gray-900; @@ -56,6 +61,10 @@ border-radius: $grid-unit-05; pointer-events: none; } + + &--clickable { + cursor: pointer; + } } .dataviews-view-grid__fields { diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 4e1607b01489c2..57f4b8e66a6e0c 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -40,6 +40,8 @@ interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; field: NormalizedField< Item >; item: Item; + isClickable: ( item: Item ) => boolean; + onClick: ( item: Item ) => void; } interface TableColumnCombinedProps< Item > { @@ -48,6 +50,8 @@ interface TableColumnCombinedProps< Item > { field: CombinedField; item: Item; view: ViewTableType; + isClickable: ( item: Item ) => boolean; + onClick: ( item: Item ) => void; } interface TableColumnProps< Item > { @@ -56,6 +60,8 @@ interface TableColumnProps< Item > { item: Item; column: string; view: ViewTableType; + isClickable: ( item: Item ) => boolean; + onClick: ( item: Item ) => void; } interface TableRowProps< Item > { @@ -69,6 +75,8 @@ interface TableRowProps< Item > { selection: string[]; getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; + isClickable: ( item: Item ) => boolean; + onClick: ( item: Item ) => void; } function TableColumn< Item >( { @@ -102,13 +110,32 @@ function TableColumnField< Item >( { primaryField, item, field, + isClickable, + onClick, }: TableColumnFieldProps< Item > ) { return (
{ + if ( isClickable( item ) ) { + onClick( item ); + } + } } + onKeyDown={ ( event ) => { + if ( + ( event.key === 'Enter' || event.key === '' ) && + isClickable( item ) + ) { + onClick( item ); + } + } } >
@@ -139,6 +166,8 @@ function TableRow< Item >( { primaryField, selection, getItemId, + isClickable, + onClick, onChangeSelection, }: TableRowProps< Item > ) { const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item ); @@ -214,6 +243,8 @@ function TableRow< Item >( { ( { onChangeSelection, selection, setOpenedFilter, + onClick, + isClickable, view, }: ViewTableProps< Item > ) { const headerMenuRefs = useRef< @@ -392,6 +425,8 @@ function ViewTable< Item >( { selection={ selection } getItemId={ getItemId } onChangeSelection={ onChangeSelection } + onClick={ onClick } + isClickable={ isClickable } /> ) ) } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 2a335dce3af32b..d92d0240108e26 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -493,6 +493,8 @@ export interface ViewBaseProps< Item > { onChangeSelection: SetSelection; selection: string[]; setOpenedFilter: ( fieldId: string ) => void; + onClick: ( item: Item ) => void; + isClickable: ( item: Item ) => boolean; view: View; density: number; } diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index c40b86c8026536..53fc619fc5f124 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -31,12 +31,7 @@ import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ -import { - LAYOUT_GRID, - LAYOUT_TABLE, - OPERATOR_IS_ANY, -} from '../../utils/constants'; -import { default as Link } from '../routes/link'; +import { OPERATOR_IS_ANY } from '../../utils/constants'; // See https://github.com/WordPress/gutenberg/issues/55886 // We do not support custom statutes at the moment. @@ -134,7 +129,7 @@ function PostAuthorField( { item } ) { ); } -function usePostFields( viewType ) { +function usePostFields() { const { records: authors, isResolving: isLoadingAuthors } = useEntityRecords( 'root', 'user', { per_page: -1 } ); @@ -159,30 +154,10 @@ function usePostFields( viewType ) { ? item.title : item.title?.raw, render: ( { item } ) => { - const addLink = - [ LAYOUT_TABLE, LAYOUT_GRID ].includes( viewType ) && - item.status !== 'trash'; const renderedTitle = typeof item.title === 'string' ? item.title : item.title?.rendered; - const title = addLink ? ( - - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - - ) : ( - - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - - ); let suffix = ''; if ( item.id === frontPageId ) { @@ -205,7 +180,10 @@ function usePostFields( viewType ) { alignment="center" justify="flex-start" > - { title } + + { decodeEntities( renderedTitle ) || + __( '(no title)' ) } + { suffix }
); @@ -347,7 +325,7 @@ function usePostFields( viewType ) { ], }, ], - [ authors, viewType, frontPageId, postsPageId ] + [ authors, frontPageId, postsPageId ] ); return { diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 6738310ff6021b..12fde7e616b034 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -208,9 +208,7 @@ export default function PostList( { postType } ) { return found?.filters ?? []; }; - const { isLoading: isLoadingFields, fields: _fields } = usePostFields( - view.type - ); + const { isLoading: isLoadingFields, fields: _fields } = usePostFields(); const fields = useMemo( () => { const activeViewFilters = getActiveViewFilters( defaultViews, @@ -402,6 +400,14 @@ export default function PostList( { postType } ) { onChangeView={ setView } selection={ selection } onChangeSelection={ onChangeSelection } + isClickable={ ( item ) => item.status !== 'trash' } + handleClick={ ( { id } ) => { + history.push( { + postId: id, + postType, + canvas: 'edit', + } ); + } } getItemId={ getItemId } defaultLayouts={ defaultLayouts } header={ diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index 895a02b3106725..8de54bc696c3d2 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -9,7 +9,9 @@ width: 100%; border-radius: $grid-unit-05; - &.is-layout-table:not(:has(.edit-site-post-list__featured-image-button)), + &.is-layout-table:not( + :has(.edit-site-post-list__featured-image-button) +), &.is-layout-table .edit-site-post-list__featured-image-button { width: $grid-unit-40; height: $grid-unit-40; @@ -46,7 +48,9 @@ border-radius: $grid-unit-05; &:focus-visible { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + 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; } @@ -54,7 +58,9 @@ .dataviews-view-grid__card.is-selected { .edit-site-post-list__featured-image-button::after { - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + box-shadow: + inset 0 0 0 var(--wp-admin-border-width-focus) + var(--wp-admin-theme-color); background: rgba(var(--wp-admin-theme-color--rgb), 0.04); } } @@ -64,6 +70,25 @@ overflow: hidden; } +.dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable, +.dataviews-view-table__primary-field.dataviews-view-table__primary-field--clickable { + .edit-site-post-list__title span { + cursor: pointer; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; + flex-grow: 0; + color: $gray-900; + + &:hover { + color: var(--wp-admin-theme-color); + } + @include link-reset(); + } +} + .edit-site-post-list__title-badge { background: $gray-100; color: $gray-700; From 1d0809a41bb679a6dbe44eb24be6ff39f4e09e79 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 23 Oct 2024 13:30:45 +0200 Subject: [PATCH 40/59] generate package-lock.json --- package-lock.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index 76bc76d72f33a2..d2c0fb2f5de5fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54457,10 +54457,12 @@ "@wordpress/html-entities": "*", "@wordpress/i18n": "*", "@wordpress/icons": "*", + "@wordpress/media-utils": "*", "@wordpress/notices": "*", "@wordpress/patterns": "*", "@wordpress/primitives": "*", "@wordpress/private-apis": "*", + "@wordpress/router": "*", "@wordpress/url": "*", "@wordpress/warning": "*", "change-case": "4.1.2", From e6e3eb9d21e94536e523853b9bf67d6b1ecbd30d Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 23 Oct 2024 13:37:55 +0200 Subject: [PATCH 41/59] add documentation --- packages/dataviews/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 95b8fc898555c3..a2a020239a2cad 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -320,6 +320,14 @@ The `defaultLayouts` property should be an object that includes properties named Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. +### `isClickable`: `function` + +A function that determines if an item is clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. + +### `onClickable`: `function` + +A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. + ## Types ### Layouts From 09b2f79ebcca9ca75da96d0cce62e977040064fe Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 23 Oct 2024 13:40:06 +0200 Subject: [PATCH 42/59] fix naming --- packages/dataviews/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index a2a020239a2cad..4193c3a5f72ac0 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -324,7 +324,7 @@ Callback that signals the user selected one of more items, and takes them as par A function that determines if an item is clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. -### `onClickable`: `function` +### `onClick`: `function` A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. From 9e2cbf93be279c65fa611abc8bf9d1fa67b36fbb Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 23 Oct 2024 13:44:46 +0200 Subject: [PATCH 43/59] improve documentation --- packages/dataviews/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 4193c3a5f72ac0..1f219757684666 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -322,7 +322,7 @@ Callback that signals the user selected one of more items, and takes them as par ### `isClickable`: `function` -A function that determines if an item is clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. +A function that determines if a media field or a primary field are clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. ### `onClick`: `function` From e77b93b6eada2f05046857613df959485d7f25f9 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 23 Oct 2024 13:30:45 +0200 Subject: [PATCH 44/59] generate package-lock.json --- package-lock.json | 3 +++ packages/edit-site/package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/package-lock.json b/package-lock.json index 76bc76d72f33a2..883efd7e4ed703 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54065,6 +54065,7 @@ "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/escape-html": "*", + "@wordpress/fields": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", "@wordpress/i18n": "*", @@ -54457,10 +54458,12 @@ "@wordpress/html-entities": "*", "@wordpress/i18n": "*", "@wordpress/icons": "*", + "@wordpress/media-utils": "*", "@wordpress/notices": "*", "@wordpress/patterns": "*", "@wordpress/primitives": "*", "@wordpress/private-apis": "*", + "@wordpress/router": "*", "@wordpress/url": "*", "@wordpress/warning": "*", "change-case": "4.1.2", diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 83cae4a7100bc7..f85a9e26a9d689 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -48,6 +48,7 @@ "@wordpress/editor": "*", "@wordpress/element": "*", "@wordpress/escape-html": "*", + "@wordpress/fields": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", "@wordpress/i18n": "*", From a8e3d7569e9252ed9eb5517247c00b39386baf2a Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Thu, 24 Oct 2024 17:00:03 +0200 Subject: [PATCH 45/59] update documentation --- packages/dataviews/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 1f219757684666..e1faa68bab9121 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -318,7 +318,7 @@ The `defaultLayouts` property should be an object that includes properties named ### `onChangeSelection`: `function` -Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. +Callback that signals the user selected one of more items, and takes them as parameter. ### `isClickable`: `function` From c9ab19d095f3211c082a075472702df575938fe1 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 30 Oct 2024 12:04:16 +0100 Subject: [PATCH 46/59] fix prop name --- packages/edit-site/src/components/post-list/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 00af5089fbdc15..d8ed5d122d10f9 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -401,7 +401,7 @@ export default function PostList( { postType } ) { selection={ selection } onChangeSelection={ onChangeSelection } isClickable={ ( item ) => item.status !== 'trash' } - handleClick={ ( { id } ) => { + onClick={ ( { id } ) => { history.push( { postId: id, postType, From eb2a816b3f22e426d60c7bae4178922bb482d5e4 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 4 Nov 2024 13:04:09 +0100 Subject: [PATCH 47/59] fix logic table view --- .../src/dataviews-layouts/table/index.tsx | 46 +++++++++++-------- .../src/components/post-list/style.scss | 2 +- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 57f4b8e66a6e0c..75dd93f1dc4dc2 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -113,31 +113,37 @@ function TableColumnField< Item >( { isClickable, onClick, }: TableColumnFieldProps< Item > ) { + const isPrimaryField = primaryField?.id === field.id; + const isClickableField = isClickable( item ) && isPrimaryField; return (
{ - if ( isClickable( item ) ) { - onClick( item ); - } - } } - onKeyDown={ ( event ) => { - if ( - ( event.key === 'Enter' || event.key === '' ) && - isClickable( item ) - ) { - onClick( item ); - } - } } > - +
{ + if ( isClickableField ) { + onClick( item ); + } + } } + onKeyDown={ ( event ) => { + if ( + ( event.key === 'Enter' || event.key === '' ) && + isClickableField + ) { + onClick( item ); + } + } } + > + +
); } diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index 2d60404b02e0dd..67bdcfd532f34b 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -71,7 +71,7 @@ } .dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable, -.dataviews-view-table__primary-field.dataviews-view-table__primary-field--clickable { +.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable { .edit-site-post-list__title span { cursor: pointer; text-decoration: none; From f8d86b1f7d113f1f7f294effd6cb5eb2ebdd387b Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 4 Nov 2024 14:27:36 +0100 Subject: [PATCH 48/59] Rename isClickable to isItemClickable and onClick to onItemClick for clarity --- packages/dataviews/README.md | 4 +- .../src/components/dataviews-context/index.ts | 8 +-- .../src/components/dataviews-layout/index.tsx | 8 +-- .../src/components/dataviews/index.tsx | 12 ++--- .../src/dataviews-layouts/grid/index.tsx | 40 +++++++-------- .../src/dataviews-layouts/table/index.tsx | 50 +++++++++---------- packages/dataviews/src/types.ts | 4 +- .../src/components/post-list/index.js | 4 +- 8 files changed, 65 insertions(+), 65 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index e1faa68bab9121..95757ee01ce027 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -320,11 +320,11 @@ The `defaultLayouts` property should be an object that includes properties named Callback that signals the user selected one of more items, and takes them as parameter. -### `isClickable`: `function` +### `isItemClickable`: `function` A function that determines if a media field or a primary field are clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. -### `onClick`: `function` +### `onClickItem`: `function` A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 7eb62241873119..c364b62b63637e 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,8 +26,8 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; - onClick: ( item: Item ) => void; - isClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; density: number; }; @@ -45,8 +45,8 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, - onClick: () => {}, - isClickable: () => false, + onItemClick: () => {}, + isItemClickable: () => false, density: 0, } ); diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index 5df84cc47aa86e..38a0bfbe595ec0 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -28,8 +28,8 @@ export default function DataViewsLayout() { onChangeSelection, setOpenedFilter, density, - onClick, - isClickable, + onItemClick, + isItemClickable, } = useContext( DataViewsContext ); const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) @@ -46,8 +46,8 @@ export default function DataViewsLayout() { onChangeSelection={ onChangeSelection } selection={ selection } setOpenedFilter={ setOpenedFilter } - onClick={ onClick } - isClickable={ isClickable } + onItemClick={ onItemClick } + isItemClickable={ isItemClickable } view={ view } density={ density } /> diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index e71fd42fde578f..018b7bd09cd532 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -44,8 +44,8 @@ type DataViewsProps< Item > = { defaultLayouts: SupportedLayouts; selection?: string[]; onChangeSelection?: ( items: string[] ) => void; - onClick?: ( item: Item ) => void; - isClickable?: ( item: Item ) => boolean; + onItemClick?: ( item: Item ) => void; + isItemClickable?: ( item: Item ) => boolean; header?: ReactNode; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } @@ -67,8 +67,8 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, - onClick, - isClickable, + onItemClick, + isItemClickable, header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); @@ -114,8 +114,8 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, - isClickable: isClickable ?? ( () => false ), - onClick: onClick ?? ( () => {} ), + isItemClickable: isItemClickable ?? ( () => false ), + onItemClick: onItemClick ?? ( () => {} ), density, } } > diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 44189e20e6f952..a1effe2327680c 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -29,8 +29,8 @@ interface GridItemProps< Item > { selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; - onClick: ( item: Item ) => void; - isClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; mediaField?: NormalizedField< Item >; @@ -43,8 +43,8 @@ interface GridItemProps< Item > { function GridItem< Item >( { selection, onChangeSelection, - onClick, - isClickable, + onItemClick, + isItemClickable, getItemId, item, actions, @@ -89,21 +89,21 @@ function GridItem< Item >( {
{ - if ( isClickable( item ) ) { - onClick( item ); + if ( isItemClickable( item ) ) { + onItemClick( item ); } } } onKeyDown={ ( event ) => { if ( ( event.key === 'Enter' || event.key === '' ) && - isClickable( item ) + isItemClickable( item ) ) { - onClick( item ); + onItemClick( item ); } } } > @@ -124,21 +124,21 @@ function GridItem< Item >( { { - if ( isClickable( item ) ) { - onClick( item ); + if ( isItemClickable( item ) ) { + onItemClick( item ); } } } onKeyDown={ ( event ) => { if ( ( event.key === 'Enter' || event.key === '' ) && - isClickable( item ) + isItemClickable( item ) ) { - onClick( item ); + onItemClick( item ); } } } > @@ -215,8 +215,8 @@ export default function ViewGrid< Item >( { getItemId, isLoading, onChangeSelection, - onClick, - isClickable, + onItemClick, + isItemClickable, selection, view, density, @@ -270,8 +270,8 @@ export default function ViewGrid< Item >( { key={ getItemId( item ) } selection={ selection } onChangeSelection={ onChangeSelection } - onClick={ onClick } - isClickable={ isClickable } + onItemClick={ onItemClick } + isItemClickable={ isItemClickable } getItemId={ getItemId } item={ item } actions={ actions } diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 75dd93f1dc4dc2..32994acc611af3 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -40,8 +40,8 @@ interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; field: NormalizedField< Item >; item: Item; - isClickable: ( item: Item ) => boolean; - onClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; } interface TableColumnCombinedProps< Item > { @@ -50,8 +50,8 @@ interface TableColumnCombinedProps< Item > { field: CombinedField; item: Item; view: ViewTableType; - isClickable: ( item: Item ) => boolean; - onClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; } interface TableColumnProps< Item > { @@ -60,8 +60,8 @@ interface TableColumnProps< Item > { item: Item; column: string; view: ViewTableType; - isClickable: ( item: Item ) => boolean; - onClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; } interface TableRowProps< Item > { @@ -75,8 +75,8 @@ interface TableRowProps< Item > { selection: string[]; getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; - isClickable: ( item: Item ) => boolean; - onClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; } function TableColumn< Item >( { @@ -110,11 +110,11 @@ function TableColumnField< Item >( { primaryField, item, field, - isClickable, - onClick, + isItemClickable, + onItemClick, }: TableColumnFieldProps< Item > ) { const isPrimaryField = primaryField?.id === field.id; - const isClickableField = isClickable( item ) && isPrimaryField; + const isItemClickableField = isItemClickable( item ) && isPrimaryField; return (
( {
{ - if ( isClickableField ) { - onClick( item ); + if ( isItemClickableField ) { + onItemClick( item ); } } } onKeyDown={ ( event ) => { if ( ( event.key === 'Enter' || event.key === '' ) && - isClickableField + isItemClickableField ) { - onClick( item ); + onItemClick( item ); } } } > @@ -172,8 +172,8 @@ function TableRow< Item >( { primaryField, selection, getItemId, - isClickable, - onClick, + isItemClickable, + onItemClick, onChangeSelection, }: TableRowProps< Item > ) { const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item ); @@ -249,8 +249,8 @@ function TableRow< Item >( { ( { onChangeSelection, selection, setOpenedFilter, - onClick, - isClickable, + onItemClick, + isItemClickable, view, }: ViewTableProps< Item > ) { const headerMenuRefs = useRef< @@ -431,8 +431,8 @@ function ViewTable< Item >( { selection={ selection } getItemId={ getItemId } onChangeSelection={ onChangeSelection } - onClick={ onClick } - isClickable={ isClickable } + onItemClick={ onItemClick } + isItemClickable={ isItemClickable } /> ) ) } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 7aaf3ab9aba518..fbb42378e49d93 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -498,8 +498,8 @@ export interface ViewBaseProps< Item > { onChangeSelection: SetSelection; selection: string[]; setOpenedFilter: ( fieldId: string ) => void; - onClick: ( item: Item ) => void; - isClickable: ( item: Item ) => boolean; + onItemClick: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; view: View; density: number; } diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index c43211184af2d5..357f99e5fefe70 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -400,8 +400,8 @@ export default function PostList( { postType } ) { onChangeView={ setView } selection={ selection } onChangeSelection={ onChangeSelection } - isClickable={ ( item ) => item.status !== 'trash' } - onClick={ ( { id } ) => { + isItemClickable={ ( item ) => item.status !== 'trash' } + onItemClick={ ( { id } ) => { history.push( { postId: id, postType, From 5c7b0c45c8f68f863521f3312c161d8b3a8d9d83 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Mon, 4 Nov 2024 14:31:05 +0100 Subject: [PATCH 49/59] fix style --- packages/fields/src/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss index cdb130337f1cd9..1639f455ba093e 100644 --- a/packages/fields/src/style.scss +++ b/packages/fields/src/style.scss @@ -1 +1,2 @@ @import "./fields/slug/style.scss"; +@import "./fields/featured-image/style.scss"; From 419f3fa7d2ee0da4c855087d7cc74ef88030cc4a Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 5 Nov 2024 16:10:44 +0100 Subject: [PATCH 50/59] rename onItemClick to onClickItem --- .../src/components/dataviews-context/index.ts | 4 +- .../src/components/dataviews-layout/index.tsx | 4 +- .../src/components/dataviews/index.tsx | 6 +- .../src/dataviews-layouts/grid/index.tsx | 61 ++++++++++--------- .../src/dataviews-layouts/table/index.tsx | 22 +++---- packages/dataviews/src/types.ts | 2 +- 6 files changed, 52 insertions(+), 47 deletions(-) diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index c364b62b63637e..87acade73bc819 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,7 +26,7 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; density: number; }; @@ -45,7 +45,7 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, - onItemClick: () => {}, + onClickItem: () => {}, isItemClickable: () => false, density: 0, } ); diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index 38a0bfbe595ec0..4ef0125b1f64b5 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -28,7 +28,7 @@ export default function DataViewsLayout() { onChangeSelection, setOpenedFilter, density, - onItemClick, + onClickItem, isItemClickable, } = useContext( DataViewsContext ); @@ -46,7 +46,7 @@ export default function DataViewsLayout() { onChangeSelection={ onChangeSelection } selection={ selection } setOpenedFilter={ setOpenedFilter } - onItemClick={ onItemClick } + onClickItem={ onClickItem } isItemClickable={ isItemClickable } view={ view } density={ density } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 018b7bd09cd532..2a1c307d4845ef 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -44,7 +44,7 @@ type DataViewsProps< Item > = { defaultLayouts: SupportedLayouts; selection?: string[]; onChangeSelection?: ( items: string[] ) => void; - onItemClick?: ( item: Item ) => void; + onClickItem?: ( item: Item ) => void; isItemClickable?: ( item: Item ) => boolean; header?: ReactNode; } & ( Item extends ItemWithId @@ -67,7 +67,7 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, - onItemClick, + onClickItem, isItemClickable, header, }: DataViewsProps< Item > ) { @@ -115,7 +115,7 @@ export default function DataViews< Item >( { setOpenedFilter, getItemId, isItemClickable: isItemClickable ?? ( () => false ), - onItemClick: onItemClick ?? ( () => {} ), + onClickItem: onClickItem ?? ( () => {} ), density, } } > diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index a1effe2327680c..1894601d3df0d0 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -29,7 +29,7 @@ interface GridItemProps< Item > { selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; @@ -43,7 +43,7 @@ interface GridItemProps< Item > { function GridItem< Item >( { selection, onChangeSelection, - onItemClick, + onClickItem, isItemClickable, getItemId, item, @@ -95,7 +95,7 @@ function GridItem< Item >( { role="button" onClick={ () => { if ( isItemClickable( item ) ) { - onItemClick( item ); + onClickItem( item ); } } } onKeyDown={ ( event ) => { @@ -103,7 +103,7 @@ function GridItem< Item >( { ( event.key === 'Enter' || event.key === '' ) && isItemClickable( item ) ) { - onItemClick( item ); + onClickItem( item ); } } } > @@ -121,28 +121,33 @@ function GridItem< Item >( { justify="space-between" className="dataviews-view-grid__title-actions" > - { - if ( isItemClickable( item ) ) { - onItemClick( item ); - } - } } - onKeyDown={ ( event ) => { - if ( - ( event.key === 'Enter' || event.key === '' ) && - isItemClickable( item ) - ) { - onItemClick( item ); - } - } } - > - { renderedPrimaryField } + +
{ + if ( isItemClickable( item ) ) { + onClickItem( item ); + } + } } + onKeyDown={ ( event ) => { + if ( + ( event.key === 'Enter' || event.key === '' ) && + isItemClickable( item ) + ) { + onClickItem( item ); + } + } } + > + { renderedPrimaryField } +
@@ -215,7 +220,7 @@ export default function ViewGrid< Item >( { getItemId, isLoading, onChangeSelection, - onItemClick, + onClickItem, isItemClickable, selection, view, @@ -270,7 +275,7 @@ export default function ViewGrid< Item >( { key={ getItemId( item ) } selection={ selection } onChangeSelection={ onChangeSelection } - onItemClick={ onItemClick } + onClickItem={ onClickItem } isItemClickable={ isItemClickable } getItemId={ getItemId } item={ item } diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 32994acc611af3..c7459801dc9cbc 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -41,7 +41,7 @@ interface TableColumnFieldProps< Item > { field: NormalizedField< Item >; item: Item; isItemClickable: ( item: Item ) => boolean; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; } interface TableColumnCombinedProps< Item > { @@ -51,7 +51,7 @@ interface TableColumnCombinedProps< Item > { item: Item; view: ViewTableType; isItemClickable: ( item: Item ) => boolean; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; } interface TableColumnProps< Item > { @@ -61,7 +61,7 @@ interface TableColumnProps< Item > { column: string; view: ViewTableType; isItemClickable: ( item: Item ) => boolean; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; } interface TableRowProps< Item > { @@ -76,7 +76,7 @@ interface TableRowProps< Item > { getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; isItemClickable: ( item: Item ) => boolean; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; } function TableColumn< Item >( { @@ -111,7 +111,7 @@ function TableColumnField< Item >( { item, field, isItemClickable, - onItemClick, + onClickItem, }: TableColumnFieldProps< Item > ) { const isPrimaryField = primaryField?.id === field.id; const isItemClickableField = isItemClickable( item ) && isPrimaryField; @@ -130,7 +130,7 @@ function TableColumnField< Item >( { role="button" onClick={ () => { if ( isItemClickableField ) { - onItemClick( item ); + onClickItem( item ); } } } onKeyDown={ ( event ) => { @@ -138,7 +138,7 @@ function TableColumnField< Item >( { ( event.key === 'Enter' || event.key === '' ) && isItemClickableField ) { - onItemClick( item ); + onClickItem( item ); } } } > @@ -173,7 +173,7 @@ function TableRow< Item >( { selection, getItemId, isItemClickable, - onItemClick, + onClickItem, onChangeSelection, }: TableRowProps< Item > ) { const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item ); @@ -250,7 +250,7 @@ function TableRow< Item >( { ( { onChangeSelection, selection, setOpenedFilter, - onItemClick, + onClickItem, isItemClickable, view, }: ViewTableProps< Item > ) { @@ -431,7 +431,7 @@ function ViewTable< Item >( { selection={ selection } getItemId={ getItemId } onChangeSelection={ onChangeSelection } - onItemClick={ onItemClick } + onClickItem={ onClickItem } isItemClickable={ isItemClickable } /> ) ) } diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index fbb42378e49d93..71990f72d4eecd 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -498,7 +498,7 @@ export interface ViewBaseProps< Item > { onChangeSelection: SetSelection; selection: string[]; setOpenedFilter: ( fieldId: string ) => void; - onItemClick: ( item: Item ) => void; + onClickItem: ( item: Item ) => void; isItemClickable: ( item: Item ) => boolean; view: View; density: number; From 7a7964457a25010712721a454ee5d6b0c883ed63 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 5 Nov 2024 16:53:47 +0100 Subject: [PATCH 51/59] improve CSS --- .../src/components/dataviews/style.scss | 12 +++++-- .../src/dataviews-layouts/grid/style.scss | 6 +--- .../src/components/post-list/index.js | 2 +- .../src/components/post-list/style.scss | 31 ++++++++++--------- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index aa8fbcfb009c05..bd75a1ff9e2a18 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -19,7 +19,7 @@ position: sticky; left: 0; transition: padding ease-out 0.1s; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } .dataviews-view-list__primary-field, @@ -62,6 +62,13 @@ } } +.dataviews-view-list__primary-field--clickable, +.dataviews-view-grid__primary-field--clickable, +.dataviews-view-grid__media--clickable, +.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable { + cursor: pointer; +} + .dataviews-no-results, .dataviews-loading { padding: 0 $grid-unit-60; @@ -70,7 +77,7 @@ align-items: center; justify-content: center; transition: padding ease-out 0.1s; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ @@ -86,4 +93,3 @@ padding-right: $grid-unit-30; } } - diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 25b21badc70a68..55768240a18714 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -19,7 +19,7 @@ min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button &--clickable { - cursor: pointer; + width: fit-content; } } @@ -61,10 +61,6 @@ border-radius: $grid-unit-05; pointer-events: none; } - - &--clickable { - cursor: pointer; - } } .dataviews-view-grid__fields { diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 357f99e5fefe70..4639cb3c950b76 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -401,7 +401,7 @@ export default function PostList( { postType } ) { selection={ selection } onChangeSelection={ onChangeSelection } isItemClickable={ ( item ) => item.status !== 'trash' } - onItemClick={ ( { id } ) => { + onClickItem={ ( { id } ) => { history.push( { postId: id, postType, diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss index 67bdcfd532f34b..14bb11b41d4450 100644 --- a/packages/edit-site/src/components/post-list/style.scss +++ b/packages/edit-site/src/components/post-list/style.scss @@ -70,23 +70,24 @@ overflow: hidden; } -.dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable, -.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable { - .edit-site-post-list__title span { - cursor: pointer; - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - display: block; - flex-grow: 0; - color: $gray-900; +.dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable +.edit-site-post-list__title +span, +.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable +.edit-site-post-list__title +span { + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: block; + flex-grow: 0; + color: $gray-900; - &:hover { - color: var(--wp-admin-theme-color); - } - @include link-reset(); + &:hover { + color: var(--wp-admin-theme-color); } + @include link-reset(); } .edit-site-post-list__title-badge { From 0071e096fc4d063ff70832ba5a632f6cf3345237 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 5 Nov 2024 17:05:59 +0100 Subject: [PATCH 52/59] fix docs --- packages/dataviews/README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index 78598b70cc4781..ab677c8764d2b7 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -377,15 +377,6 @@ The `defaultLayouts` property should be an object that includes properties named #### `selection`: `string[]` -Callback that signals the user selected one of more items, and takes them as parameter. - -### `isItemClickable`: `function` - -A function that determines if a media field or a primary field are clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. - -### `onClickItem`: `function` - -A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. The list of selected items' ids. If `selection` and `onChangeSelection` are provided, the `DataViews` component behaves as a controlled component, otherwise, it behaves like an uncontrolled component. @@ -396,6 +387,14 @@ Callback that signals the user selected one of more items. It receives the list If `selection` and `onChangeSelection` are provided, the `DataViews` component behaves as a controlled component, otherwise, it behaves like an uncontrolled component. +### `isItemClickable`: `function` + +A function that determines if a media field or a primary field are clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. + +### `onClickItem`: `function` + +A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. + #### `header`: React component React component to be rendered next to the view config button. From 507d60b0db8dc4c056e3699a567394025d352d98 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 5 Nov 2024 18:06:01 +0100 Subject: [PATCH 53/59] add useClickableItemProps --- .../src/dataviews-layouts/grid/index.tsx | 64 +++++-------------- .../hooks/use-clickable-item-props.ts | 34 ++++++++++ .../src/dataviews-layouts/table/index.tsx | 34 ++++------ 3 files changed, 63 insertions(+), 69 deletions(-) create mode 100644 packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 1894601d3df0d0..e474eb9a17da84 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -24,6 +24,7 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; +import { useClickableItemProps } from '../hooks/use-clickable-item-props'; interface GridItemProps< Item > { selection: string[]; @@ -64,6 +65,20 @@ function GridItem< Item >( { ) : null; + const clickableMediaItemProps = useClickableItemProps( + item, + isItemClickable, + onClickItem, + 'dataviews-view-grid__media' + ); + + const clickablePrimaryItemProps = useClickableItemProps( + item, + isItemClickable, + onClickItem, + 'dataviews-view-grid__primary-field' + ); + return ( ( { } } } > -
{ - if ( isItemClickable( item ) ) { - onClickItem( item ); - } - } } - onKeyDown={ ( event ) => { - if ( - ( event.key === 'Enter' || event.key === '' ) && - isItemClickable( item ) - ) { - onClickItem( item ); - } - } } - > - { renderedMediaField } -
+
{ renderedMediaField }
( { className="dataviews-view-grid__title-actions" > -
{ - if ( isItemClickable( item ) ) { - onClickItem( item ); - } - } } - onKeyDown={ ( event ) => { - if ( - ( event.key === 'Enter' || event.key === '' ) && - isItemClickable( item ) - ) { - onClickItem( item ); - } - } } - > +
{ renderedPrimaryField }
diff --git a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts new file mode 100644 index 00000000000000..0540cea9f72455 --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts @@ -0,0 +1,34 @@ +/** + * External dependencies + */ +import clsx from 'clsx'; + +export const useClickableItemProps = < Item >( + item: Item, + isItemClickable: ( item: Item ) => boolean, + onClickItem: ( item: Item ) => void, + className: string +) => { + const isClickable = isItemClickable( item ); + + return { + className: clsx( className, { + [ className + '--clickable' ]: isClickable, + } ), + role: isItemClickable( item ) ? 'button' : undefined, + onClick: () => { + if ( isClickable ) { + onClickItem( item ); + } + }, + tabIndex: isClickable ? 0 : undefined, + onKeyDown: ( event: React.KeyboardEvent ) => { + if ( + ( event.key === 'Enter' || event.key === '' ) && + isClickable + ) { + onClickItem( item ); + } + }, + }; +}; diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index c7459801dc9cbc..43dbf6e82485ef 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -35,6 +35,7 @@ import type { import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; import { getVisibleFieldIds } from '../index'; +import { useClickableItemProps } from '../hooks/use-clickable-item-props'; interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; @@ -114,34 +115,23 @@ function TableColumnField< Item >( { onClickItem, }: TableColumnFieldProps< Item > ) { const isPrimaryField = primaryField?.id === field.id; - const isItemClickableField = isItemClickable( item ) && isPrimaryField; + const isItemClickableField = ( i: Item ) => + isItemClickable( i ) && isPrimaryField; + + const clickableProps = useClickableItemProps( + item, + isItemClickableField, + onClickItem, + 'dataviews-view-table__cell-content' + ); + return (
-
{ - if ( isItemClickableField ) { - onClickItem( item ); - } - } } - onKeyDown={ ( event ) => { - if ( - ( event.key === 'Enter' || event.key === '' ) && - isItemClickableField - ) { - onClickItem( item ); - } - } } - > +
From ed48f39f6dfe06446c8de64dc1efaea412104e09 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 6 Nov 2024 12:03:54 +0100 Subject: [PATCH 54/59] use `isClickable` variable Co-authored-by: Riad Benguella --- .../src/dataviews-layouts/hooks/use-clickable-item-props.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts index 0540cea9f72455..f5d0e980051d9c 100644 --- a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts @@ -15,7 +15,7 @@ export const useClickableItemProps = < Item >( className: clsx( className, { [ className + '--clickable' ]: isClickable, } ), - role: isItemClickable( item ) ? 'button' : undefined, + role: isClickable ? 'button' : undefined, onClick: () => { if ( isClickable ) { onClickItem( item ); From c9e418b5fddc40020c9c677c3b29ae6dda162747 Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Wed, 6 Nov 2024 17:16:28 +0100 Subject: [PATCH 55/59] improve code style --- .../hooks/use-clickable-item-props.ts | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts index f5d0e980051d9c..00c2726a7f57ba 100644 --- a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts @@ -16,19 +16,14 @@ export const useClickableItemProps = < Item >( [ className + '--clickable' ]: isClickable, } ), role: isClickable ? 'button' : undefined, - onClick: () => { - if ( isClickable ) { - onClickItem( item ); - } - }, tabIndex: isClickable ? 0 : undefined, - onKeyDown: ( event: React.KeyboardEvent ) => { - if ( - ( event.key === 'Enter' || event.key === '' ) && - isClickable - ) { - onClickItem( item ); - } - }, + onClick: ! isClickable ? undefined : () => onClickItem( item ), + onKeyDown: ! isClickable + ? undefined + : ( event: React.KeyboardEvent ) => { + if ( event.key === 'Enter' || event.key === '' ) { + onClickItem( item ); + } + }, }; }; From fdc2892f34acae7e6230ff6d7de1f0fa68240576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:33:17 +0100 Subject: [PATCH 56/59] Address feedback about getClickableItemProps --- packages/dataviews/src/dataviews-layouts/grid/index.tsx | 6 +++--- packages/dataviews/src/dataviews-layouts/table/index.tsx | 4 ++-- .../get-clickable-item-props.ts} | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) rename packages/dataviews/src/dataviews-layouts/{hooks/use-clickable-item-props.ts => utils/get-clickable-item-props.ts} (91%) diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index e474eb9a17da84..91cc87ec7b35b6 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -24,7 +24,7 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; -import { useClickableItemProps } from '../hooks/use-clickable-item-props'; +import getClickableItemProps from '../utils/get-clickable-item-props'; interface GridItemProps< Item > { selection: string[]; @@ -65,14 +65,14 @@ function GridItem< Item >( { ) : null; - const clickableMediaItemProps = useClickableItemProps( + const clickableMediaItemProps = getClickableItemProps( item, isItemClickable, onClickItem, 'dataviews-view-grid__media' ); - const clickablePrimaryItemProps = useClickableItemProps( + const clickablePrimaryItemProps = getClickableItemProps( item, isItemClickable, onClickItem, diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 43dbf6e82485ef..8ef41db1c38798 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -35,7 +35,7 @@ import type { import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; import { getVisibleFieldIds } from '../index'; -import { useClickableItemProps } from '../hooks/use-clickable-item-props'; +import getClickableItemProps from '../utils/get-clickable-item-props'; interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; @@ -118,7 +118,7 @@ function TableColumnField< Item >( { const isItemClickableField = ( i: Item ) => isItemClickable( i ) && isPrimaryField; - const clickableProps = useClickableItemProps( + const clickableProps = getClickableItemProps( item, isItemClickableField, onClickItem, diff --git a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts similarity index 91% rename from packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts rename to packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts index 00c2726a7f57ba..8ca0574fc80ac0 100644 --- a/packages/dataviews/src/dataviews-layouts/hooks/use-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -3,12 +3,12 @@ */ import clsx from 'clsx'; -export const useClickableItemProps = < Item >( +export default function getClickableItemProps< Item >( item: Item, isItemClickable: ( item: Item ) => boolean, onClickItem: ( item: Item ) => void, className: string -) => { +) { const isClickable = isItemClickable( item ); return { @@ -26,4 +26,4 @@ export const useClickableItemProps = < Item >( } }, }; -}; +} From 84cc4c27e220e105d2ddb776d0808039f1df966f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:05:02 +0100 Subject: [PATCH 57/59] Remove defaults, they are already provided by the Provider --- packages/dataviews/src/components/dataviews/index.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 2a1c307d4845ef..f2c01d052617fb 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -52,6 +52,8 @@ type DataViewsProps< Item > = { : { getItemId: ( item: Item ) => string } ); const defaultGetItemId = ( item: ItemWithId ) => item.id; +const defaultIsItemClickable = () => false; +const defaultOnClickItem = () => {}; export default function DataViews< Item >( { view, @@ -67,8 +69,8 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, - onClickItem, - isItemClickable, + onClickItem = defaultOnClickItem, + isItemClickable = defaultIsItemClickable, header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); @@ -114,8 +116,8 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, - isItemClickable: isItemClickable ?? ( () => false ), - onClickItem: onClickItem ?? ( () => {} ), + isItemClickable, + onClickItem, density, } } > From eaa3324fcfbb8c7f35895bfa68b331bccbd51d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:07:19 +0100 Subject: [PATCH 58/59] Cache empty actions --- packages/dataviews/src/components/dataviews/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index f2c01d052617fb..77a5cb8740f712 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -54,6 +54,7 @@ type DataViewsProps< Item > = { const defaultGetItemId = ( item: ItemWithId ) => item.id; const defaultIsItemClickable = () => false; const defaultOnClickItem = () => {}; +const EMPTY_ARRAY: any[] = []; export default function DataViews< Item >( { view, @@ -61,7 +62,7 @@ export default function DataViews< Item >( { fields, search = true, searchLabel = undefined, - actions = [], + actions = EMPTY_ARRAY, data, getItemId = defaultGetItemId, isLoading = false, From f24172ba41318288889fb46fe1689f90fbdc74ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Maneiro?= <583546+oandregal@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:11:18 +0100 Subject: [PATCH 59/59] Address feedback: simplify getClickableItemProps --- .../utils/get-clickable-item-props.ts | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts index 8ca0574fc80ac0..e2a6081a68fa3e 100644 --- a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -1,29 +1,22 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - export default function getClickableItemProps< Item >( item: Item, isItemClickable: ( item: Item ) => boolean, onClickItem: ( item: Item ) => void, className: string ) { - const isClickable = isItemClickable( item ); + if ( ! isItemClickable( item ) ) { + return { className }; + } return { - className: clsx( className, { - [ className + '--clickable' ]: isClickable, - } ), - role: isClickable ? 'button' : undefined, - tabIndex: isClickable ? 0 : undefined, - onClick: ! isClickable ? undefined : () => onClickItem( item ), - onKeyDown: ! isClickable - ? undefined - : ( event: React.KeyboardEvent ) => { - if ( event.key === 'Enter' || event.key === '' ) { - onClickItem( item ); - } - }, + className: `${ className } ${ className }--clickable`, + role: 'button', + tabIndex: 0, + onClick: () => onClickItem( item ), + onKeyDown: ( event: React.KeyboardEvent ) => { + if ( event.key === 'Enter' || event.key === '' ) { + onClickItem( item ); + } + }, }; }