diff --git a/package-lock.json b/package-lock.json index f8e9c4aba0abf8..6c8b8f14303cd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17051,6 +17051,7 @@ "@wordpress/editor": "file:packages/editor", "@wordpress/element": "file:packages/element", "@wordpress/hooks": "file:packages/hooks", + "@wordpress/html-entities": "file:packages/html-entities", "@wordpress/i18n": "file:packages/i18n", "@wordpress/icons": "file:packages/icons", "@wordpress/interface": "file:packages/interface", diff --git a/packages/block-editor/src/components/inspector-popover-header/index.js b/packages/block-editor/src/components/inspector-popover-header/index.js index e88380a61032a8..90fc8e3d64039e 100644 --- a/packages/block-editor/src/components/inspector-popover-header/index.js +++ b/packages/block-editor/src/components/inspector-popover-header/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -13,13 +18,20 @@ import { closeSmall } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; export default function InspectorPopoverHeader( { + className, title, help, actions = [], onClose, } ) { return ( - + ) } /> - - - - - - diff --git a/packages/edit-post/src/components/sidebar/featured-image/index.js b/packages/edit-post/src/components/sidebar/featured-image/index.js deleted file mode 100644 index 5a9db1e3839460..00000000000000 --- a/packages/edit-post/src/components/sidebar/featured-image/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * External dependencies - */ -import { get, partial } from 'lodash'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { PanelBody } from '@wordpress/components'; -import { - PostFeaturedImage, - PostFeaturedImageCheck, - store as editorStore, -} from '@wordpress/editor'; -import { compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; - -/** - * Internal dependencies - */ -import { store as editPostStore } from '../../../store'; - -/** - * Module Constants - */ -const PANEL_NAME = 'featured-image'; - -function FeaturedImage( { isEnabled, isOpened, postType, onTogglePanel } ) { - if ( ! isEnabled ) { - return null; - } - - return ( - - - - - - ); -} - -const applyWithSelect = withSelect( ( select ) => { - const { getEditedPostAttribute } = select( editorStore ); - const { getPostType } = select( coreStore ); - const { isEditorPanelEnabled, isEditorPanelOpened } = - select( editPostStore ); - - return { - postType: getPostType( getEditedPostAttribute( 'type' ) ), - isEnabled: isEditorPanelEnabled( PANEL_NAME ), - isOpened: isEditorPanelOpened( PANEL_NAME ), - }; -} ); - -const applyWithDispatch = withDispatch( ( dispatch ) => { - const { toggleEditorPanelOpened } = dispatch( editPostStore ); - - return { - onTogglePanel: partial( toggleEditorPanelOpened, PANEL_NAME ), - }; -} ); - -export default compose( applyWithSelect, applyWithDispatch )( FeaturedImage ); diff --git a/packages/edit-post/src/components/sidebar/post-excerpt/index.js b/packages/edit-post/src/components/sidebar/post-excerpt/index.js deleted file mode 100644 index b2d56808d64c79..00000000000000 --- a/packages/edit-post/src/components/sidebar/post-excerpt/index.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { PanelBody } from '@wordpress/components'; -import { - PostExcerpt as PostExcerptForm, - PostExcerptCheck, -} from '@wordpress/editor'; -import { compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { store as editPostStore } from '../../../store'; - -/** - * Module Constants - */ -const PANEL_NAME = 'post-excerpt'; - -function PostExcerpt( { isEnabled, isOpened, onTogglePanel } ) { - if ( ! isEnabled ) { - return null; - } - - return ( - - - - - - ); -} - -export default compose( [ - withSelect( ( select ) => { - return { - isEnabled: - select( editPostStore ).isEditorPanelEnabled( PANEL_NAME ), - isOpened: select( editPostStore ).isEditorPanelOpened( PANEL_NAME ), - }; - } ), - withDispatch( ( dispatch ) => ( { - onTogglePanel() { - return dispatch( editPostStore ).toggleEditorPanelOpened( - PANEL_NAME - ); - }, - } ) ), -] )( PostExcerpt ); diff --git a/packages/edit-post/src/components/sidebar/post-featured-image/index.js b/packages/edit-post/src/components/sidebar/post-featured-image/index.js new file mode 100644 index 00000000000000..2444fe21a832dc --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-featured-image/index.js @@ -0,0 +1,18 @@ +/** + * WordPress dependencies + */ +import { + PostFeaturedImageCheck, + PostFeaturedImage as PostFeaturedImageForm, +} from '@wordpress/editor'; +import { MediaUploadCheck } from '@wordpress/block-editor'; + +export default function PostFeaturedImage() { + return ( + + + + + + ); +} diff --git a/packages/edit-post/src/components/sidebar/post-featured-image/style.scss b/packages/edit-post/src/components/sidebar/post-featured-image/style.scss new file mode 100644 index 00000000000000..6c35d935663a87 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-featured-image/style.scss @@ -0,0 +1,11 @@ +.edit-post-post-featured-image { + .editor-post-featured-image__container { + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; + } + + .editor-post-featured-image__toggle { + border-bottom: $border-width solid $gray-200; + border-top: $border-width solid $gray-200; + } +} diff --git a/packages/edit-post/src/components/sidebar/post-status/index.js b/packages/edit-post/src/components/sidebar/post-status/index.js index 1ed32b0116bd72..7e673c9aa63ddf 100644 --- a/packages/edit-post/src/components/sidebar/post-status/index.js +++ b/packages/edit-post/src/components/sidebar/post-status/index.js @@ -8,6 +8,8 @@ import { useSelect } from '@wordpress/data'; * Internal dependencies */ import PostStatusHeader from './header'; +import PostFeaturedImage from '../post-featured-image'; +import PostSummary from '../post-summary'; import PostVisibility from '../post-visibility'; import PostSchedule from '../post-schedule'; import PostAuthor from '../post-author'; @@ -43,6 +45,8 @@ export default function PostStatus() { { ( fills ) => ( <> + + diff --git a/packages/edit-post/src/components/sidebar/post-status/style.scss b/packages/edit-post/src/components/sidebar/post-status/style.scss index 6f156601c616b1..afeaeee619ae3f 100644 --- a/packages/edit-post/src/components/sidebar/post-status/style.scss +++ b/packages/edit-post/src/components/sidebar/post-status/style.scss @@ -1,4 +1,7 @@ .edit-post-post-status__header { + margin: (-$grid-unit-20) (-$grid-unit-20) 0 (-$grid-unit-20); + padding: $grid-unit-20; + .components-dropdown-menu { line-height: 0; margin: -$grid-unit-05 0; @@ -8,6 +11,14 @@ min-width: $grid-unit-30; padding: 0; } + + & + .components-panel__row { + margin-top: 5px; + } +} + +[class].edit-post-post-status__header { + box-sizing: content-box; } [class].edit-post-post-status__heading { @@ -25,7 +36,3 @@ min-height: $icon-size; min-width: $icon-size; } - -[class].edit-post-post-status__post-trash { - box-shadow: none; -} diff --git a/packages/edit-post/src/components/sidebar/post-summary/excerpt.js b/packages/edit-post/src/components/sidebar/post-summary/excerpt.js new file mode 100644 index 00000000000000..6ce844b12f3d80 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-summary/excerpt.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; +import { PlainText } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; + +export default function PostSummaryExcerpt() { + const excerpt = useSelect( + ( select ) => select( editorStore ).getEditedPostAttribute( 'excerpt' ), + [] + ); + + const { editPost } = useDispatch( editorStore ); + + return ( + editPost( { excerpt: value } ) } + /> + ); +} diff --git a/packages/edit-post/src/components/sidebar/post-summary/index.js b/packages/edit-post/src/components/sidebar/post-summary/index.js new file mode 100644 index 00000000000000..0d0bab66507000 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-summary/index.js @@ -0,0 +1,23 @@ +/** + * WordPress dependencies + */ +import { PostTypeSupportCheck, PostExcerptCheck } from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import PostSummaryTitle from './title'; +import PostSummaryExcerpt from './excerpt'; + +export default function PostSummary() { + return ( + <div className="edit-post-post-summary"> + <PostTypeSupportCheck supportKeys="title"> + <PostSummaryTitle /> + </PostTypeSupportCheck> + <PostExcerptCheck> + <PostSummaryExcerpt /> + </PostExcerptCheck> + </div> + ); +} diff --git a/packages/edit-post/src/components/sidebar/post-summary/style.scss b/packages/edit-post/src/components/sidebar/post-summary/style.scss new file mode 100644 index 00000000000000..8e806a4c3a978d --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-summary/style.scss @@ -0,0 +1,21 @@ +.edit-post-post-summary { + border-bottom: $border-width solid $gray-200; + border-top: $border-width solid $gray-200; + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; + padding: $grid-unit-10 $grid-unit-20 $grid-unit-20; + + .edit-post-post-featured-image + & { + margin-top: -1px; + } +} + +.edit-post-post-summary__title, +.edit-post-post-summary__excerpt { + margin-top: $grid-unit-10; +} + +.edit-post-post-summary__title { + font-size: 16px; + font-weight: 600; +} diff --git a/packages/edit-post/src/components/sidebar/post-summary/title.js b/packages/edit-post/src/components/sidebar/post-summary/title.js new file mode 100644 index 00000000000000..6efc25811187d5 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-summary/title.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as editorStore } from '@wordpress/editor'; +import { PlainText } from '@wordpress/block-editor'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __ } from '@wordpress/i18n'; + +export default function PostSummaryTitle() { + const { title, titlePlaceholder } = useSelect( + ( select ) => ( { + title: select( editorStore ).getEditedPostAttribute( 'title' ), + titlePlaceholder: + select( editorStore ).getEditorSettings().titlePlaceholder, + } ), + [] + ); + + const { editPost } = useDispatch( editorStore ); + + return ( + <PlainText + __experimentalVersion={ 2 } + className="edit-post-post-summary__title" + placeholder={ + decodeEntities( titlePlaceholder ) || __( 'Add title' ) + } + disableLineBreaks + value={ title } + onChange={ ( value ) => editPost( { title: value } ) } + /> + ); +} diff --git a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js index b969a66c88e500..8782b383495ee6 100644 --- a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js +++ b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js @@ -16,8 +16,6 @@ import { store as interfaceStore } from '@wordpress/interface'; import SettingsHeader from '../settings-header'; import PostStatus from '../post-status'; import PostTaxonomies from '../post-taxonomies'; -import FeaturedImage from '../featured-image'; -import PostExcerpt from '../post-excerpt'; import DiscussionPanel from '../discussion-panel'; import PageAttributes from '../page-attributes'; import MetaBoxes from '../../meta-boxes'; @@ -85,8 +83,6 @@ const SettingsSidebar = () => { <PostStatus /> <PluginDocumentSettingPanel.Slot /> <PostTaxonomies /> - <FeaturedImage /> - <PostExcerpt /> <DiscussionPanel /> <PageAttributes /> <MetaBoxes location="side" /> diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index a33cc6461c08e5..1754f052b23417 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -10,10 +10,12 @@ @import "./components/secondary-sidebar/style.scss"; @import "./components/sidebar/style.scss"; @import "./components/sidebar/post-author/style.scss"; +@import "./components/sidebar/post-featured-image/style.scss"; @import "./components/sidebar/post-format/style.scss"; @import "./components/sidebar/post-schedule/style.scss"; @import "./components/sidebar/post-slug/style.scss"; @import "./components/sidebar/post-status/style.scss"; +@import "./components/sidebar/post-summary/style.scss"; @import "./components/sidebar/post-template/style.scss"; @import "./components/sidebar/post-url/style.scss"; @import "./components/sidebar/post-visibility/style.scss"; diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index 800177adfccd04..b9ed7ba1e8ef1f 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -2,6 +2,7 @@ * External dependencies */ import { has, get } from 'lodash'; +import classnames from 'classnames'; /** * WordPress dependencies @@ -10,30 +11,29 @@ import { __, sprintf } from '@wordpress/i18n'; import { applyFilters } from '@wordpress/hooks'; import { DropZone, - Button, - Spinner, - ResponsiveWrapper, withNotices, withFilters, + Dropdown, } from '@wordpress/components'; import { isBlobURL } from '@wordpress/blob'; import { useState } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { useSelect, withDispatch, withSelect } from '@wordpress/data'; -import { - MediaUpload, - MediaUploadCheck, - store as blockEditorStore, -} from '@wordpress/block-editor'; +import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies */ import PostFeaturedImageCheck from './check'; +import PostFeaturedImageUploadProvider from './upload-provider'; +import PostFeaturedImageToggle from './toggle'; +import PostFeaturedImagePreview from './preview'; +import PostFeaturedImageMenu from './menu'; import { store as editorStore } from '../../store'; const ALLOWED_MEDIA_TYPES = [ 'image' ]; +const ALLOWED_UPLOAD_TYPES = 'image/*'; // Used when labels from post type were not yet loaded or when they are not present. const DEFAULT_FEATURE_IMAGE_LABEL = __( 'Featured image' ); @@ -50,7 +50,7 @@ const instructions = ( function getMediaDetails( media, postId ) { if ( ! media ) { - return {}; + return null; } const defaultSize = applyFilters( @@ -61,9 +61,9 @@ function getMediaDetails( media, postId ) { ); if ( has( media, [ 'media_details', 'sizes', defaultSize ] ) ) { return { - mediaWidth: media.media_details.sizes[ defaultSize ].width, - mediaHeight: media.media_details.sizes[ defaultSize ].height, - mediaSourceUrl: media.media_details.sizes[ defaultSize ].source_url, + width: media.media_details.sizes[ defaultSize ].width, + height: media.media_details.sizes[ defaultSize ].height, + sourceUrl: media.media_details.sizes[ defaultSize ].source_url, }; } @@ -76,22 +76,22 @@ function getMediaDetails( media, postId ) { ); if ( has( media, [ 'media_details', 'sizes', fallbackSize ] ) ) { return { - mediaWidth: media.media_details.sizes[ fallbackSize ].width, - mediaHeight: media.media_details.sizes[ fallbackSize ].height, - mediaSourceUrl: - media.media_details.sizes[ fallbackSize ].source_url, + width: media.media_details.sizes[ fallbackSize ].width, + height: media.media_details.sizes[ fallbackSize ].height, + sourceUrl: media.media_details.sizes[ fallbackSize ].source_url, }; } // Use full image size when fallbackSize and defaultSize are not available. return { - mediaWidth: media.media_details.width, - mediaHeight: media.media_details.height, - mediaSourceUrl: media.source_url, + width: media.media_details.width, + height: media.media_details.height, + sourceUrl: media.source_url, }; } function PostFeaturedImage( { + className, currentPostId, featuredImageId, onUpdateImage, @@ -106,14 +106,11 @@ function PostFeaturedImage( { return select( blockEditorStore ).getSettings().mediaUpload; }, [] ); const postLabel = get( postType, [ 'labels' ], {} ); - const { mediaWidth, mediaHeight, mediaSourceUrl } = getMediaDetails( - media, - currentPostId - ); + const mediaDetails = getMediaDetails( media, currentPostId ); - function onDropFiles( filesList ) { + function processUpload( filesList ) { mediaUpload( { - allowedTypes: [ 'image' ], + allowedTypes: ALLOWED_MEDIA_TYPES, filesList, onFileChange( [ image ] ) { if ( isBlobURL( image?.url ) ) { @@ -133,7 +130,12 @@ function PostFeaturedImage( { return ( <PostFeaturedImageCheck> { noticeUI } - <div className="editor-post-featured-image"> + <div + className={ classnames( + 'editor-post-featured-image', + className + ) } + > { media && ( <div id={ `editor-post-featured-image-${ featuredImageId }-describedby` } @@ -156,92 +158,66 @@ function PostFeaturedImage( { ) } </div> ) } - <MediaUploadCheck fallback={ instructions }> - <MediaUpload - title={ - postLabel.featured_image || - DEFAULT_FEATURE_IMAGE_LABEL - } - onSelect={ onUpdateImage } - unstableFeaturedImageFlow - allowedTypes={ ALLOWED_MEDIA_TYPES } - modalClass="editor-post-featured-image__media-modal" - render={ ( { open } ) => ( - <div className="editor-post-featured-image__container"> - <Button - className={ - ! featuredImageId - ? 'editor-post-featured-image__toggle' - : 'editor-post-featured-image__preview' - } - onClick={ open } - aria-label={ - ! featuredImageId - ? null - : __( 'Edit or update the image' ) - } - aria-describedby={ - ! featuredImageId - ? null - : `editor-post-featured-image-${ featuredImageId }-describedby` - } - > - { !! featuredImageId && media && ( - <ResponsiveWrapper - naturalWidth={ mediaWidth } - naturalHeight={ mediaHeight } - isInline + <PostFeaturedImageUploadProvider + fallback={ instructions } + title={ + postLabel.featured_image || DEFAULT_FEATURE_IMAGE_LABEL + } + selectedId={ featuredImageId } + allowedMediaTypes={ ALLOWED_MEDIA_TYPES } + allowedUploadTypes={ ALLOWED_UPLOAD_TYPES } + onSelect={ onUpdateImage } + onUpload={ processUpload } + > + { ( { openMediaLibrary, openFileDialog } ) => ( + <div className="editor-post-featured-image__container"> + <Dropdown + className="editor-post-featured-image__dropdown" + position="center left" + renderToggle={ ( { isOpen, onToggle } ) => + featuredImageId ? ( + <PostFeaturedImagePreview + mediaDetails={ mediaDetails } + isLoading={ isLoading } + aria-expanded={ isOpen } + aria-describedby={ `editor-post-featured-image-${ featuredImageId }-describedby` } + onClick={ onToggle } + /> + ) : ( + <PostFeaturedImageToggle + aria-expanded={ isOpen } + onClick={ onToggle } > - <img - src={ mediaSourceUrl } - alt="" - /> - </ResponsiveWrapper> - ) } - { isLoading && <Spinner /> } - { ! featuredImageId && - ! isLoading && - ( postLabel.set_featured_image || - DEFAULT_SET_FEATURE_IMAGE_LABEL ) } - </Button> - <DropZone onFilesDrop={ onDropFiles } /> - </div> - ) } - value={ featuredImageId } - /> - </MediaUploadCheck> - { !! featuredImageId && ( - <MediaUploadCheck> - { media && ( - <MediaUpload - title={ - postLabel.featured_image || - DEFAULT_FEATURE_IMAGE_LABEL + { postLabel.set_featured_image || + DEFAULT_SET_FEATURE_IMAGE_LABEL } + </PostFeaturedImageToggle> + ) } - onSelect={ onUpdateImage } - unstableFeaturedImageFlow - allowedTypes={ ALLOWED_MEDIA_TYPES } - modalClass="editor-post-featured-image__media-modal" - render={ ( { open } ) => ( - <Button - onClick={ open } - variant="secondary" - > - { __( 'Replace Image' ) } - </Button> + renderContent={ ( { onClose } ) => ( + <PostFeaturedImageMenu + title={ + postLabel.featured_image || + DEFAULT_FEATURE_IMAGE_LABEL + } + removeImageLabel={ + postLabel.remove_featured_image || + DEFAULT_REMOVE_FEATURE_IMAGE_LABEL + } + onClose={ onClose } + onOpenMediaLibrary={ openMediaLibrary } + onOpenFileDialog={ openFileDialog } + onRemoveImage={ + featuredImageId + ? onRemoveImage + : null + } + /> ) } /> - ) } - <Button - onClick={ onRemoveImage } - variant="link" - isDestructive - > - { postLabel.remove_featured_image || - DEFAULT_REMOVE_FEATURE_IMAGE_LABEL } - </Button> - </MediaUploadCheck> - ) } + <DropZone onFilesDrop={ processUpload } /> + </div> + ) } + </PostFeaturedImageUploadProvider> </div> </PostFeaturedImageCheck> ); @@ -269,11 +245,12 @@ const applyWithDispatch = withDispatch( onUpdateImage( image ) { editPost( { featured_media: image.id } ); }, + // todo: this is dead code, but I suppose we can't remove it because of the filter? onDropImage( filesList ) { select( blockEditorStore ) .getSettings() .mediaUpload( { - allowedTypes: [ 'image' ], + allowedTypes: ALLOWED_MEDIA_TYPES, filesList, onFileChange( [ image ] ) { editPost( { featured_media: image.id } ); diff --git a/packages/editor/src/components/post-featured-image/menu.js b/packages/editor/src/components/post-featured-image/menu.js new file mode 100644 index 00000000000000..5abcdf39be6e87 --- /dev/null +++ b/packages/editor/src/components/post-featured-image/menu.js @@ -0,0 +1,66 @@ +/** + * WordPress dependencies + */ +import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; +import { MenuGroup, MenuItem } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { + media as mediaIcon, + upload as uploadIcon, + trash as trashIcon, +} from '@wordpress/icons'; + +export default function PostFeaturedImageMenu( { + title, + removeImageLabel, + onClose, + onOpenMediaLibrary, + onOpenFileDialog, + onRemoveImage, +} ) { + return ( + <div className="editor-post-featured-image__menu"> + <InspectorPopoverHeader + className="editor-post-featured-image__menu-header" + title={ title } + onClose={ onClose } + /> + <MenuGroup> + <MenuItem + icon={ mediaIcon } + iconPosition="left" + onClick={ () => { + onOpenMediaLibrary(); + onClose(); + } } + > + { __( 'Open Media Library' ) } + </MenuItem> + <MenuItem + icon={ uploadIcon } + iconPosition="left" + onClick={ () => { + onOpenFileDialog(); + onClose(); + } } + > + { __( 'Upload file' ) } + </MenuItem> + { onRemoveImage && ( + <MenuItem + className="editor-post-featured-image__remove-image" + icon={ trashIcon } + iconPosition="left" + isDestructive + onClick={ () => { + onRemoveImage(); + onClose(); + } } + > + { removeImageLabel } + </MenuItem> + ) } + </MenuGroup> + </div> + ); +} diff --git a/packages/editor/src/components/post-featured-image/preview.js b/packages/editor/src/components/post-featured-image/preview.js new file mode 100644 index 00000000000000..864a5f59e71382 --- /dev/null +++ b/packages/editor/src/components/post-featured-image/preview.js @@ -0,0 +1,30 @@ +/** + * WordPress dependencies + */ +import { Button, ResponsiveWrapper, Spinner } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +export default function PostFeaturedImagePreview( { + mediaDetails, + isLoading, + ...props +} ) { + return ( + <Button + className="editor-post-featured-image__preview" + aria-label={ __( 'Edit or update the image' ) } + { ...props } + > + { mediaDetails && ( + <ResponsiveWrapper + naturalWidth={ mediaDetails.width } + naturalHeight={ mediaDetails.height } + isInline + > + <img src={ mediaDetails.sourceUrl } alt="" /> + </ResponsiveWrapper> + ) } + { isLoading && <Spinner /> } + </Button> + ); +} diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index 965780179e6ef9..6cbe99399d4520 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -1,11 +1,14 @@ .editor-post-featured-image { padding: 0; - &__container { - margin-bottom: 1em; + .editor-post-featured-image__container { position: relative; } + .editor-post-featured-image__dropdown { + display: block; + } + .components-spinner { position: absolute; top: 50%; @@ -14,12 +17,6 @@ margin-left: -9px; } - // Stack consecutive buttons. - .components-button + .components-button { - display: block; - margin-top: 1em; - } - // This keeps images at their intrinsic size (eg. a 50px // image will never be wider than 50px). .components-responsive-wrapper__content { @@ -33,29 +30,26 @@ display: block; width: 100%; padding: 0; - transition: all 0.1s ease-out; - @include reduce-motion("transition"); - box-shadow: 0 0 0 0 var(--wp-admin-theme-color); + border-radius: 0; } .editor-post-featured-image__preview { height: auto; } -.editor-post-featured-image__preview:not(:disabled):not([aria-disabled="true"]):focus { - box-shadow: 0 0 0 4px var(--wp-admin-theme-color); -} +// .editor-post-featured-image__preview:not(:disabled):not([aria-disabled="true"]):focus { +// box-shadow: 0 0 0 4px var(--wp-admin-theme-color); +// } .editor-post-featured-image__toggle { - border-radius: $radius-block-ui; - background-color: $gray-100; - min-height: 90px; - line-height: 20px; - padding: $grid-unit-10 0; - text-align: center; - - &:hover { - background: $gray-300; - color: $gray-900; - } + min-height: $grid-unit-80; +} + +.editor-post-featured-image__menu { + margin: $grid-unit-10 0; +} + +.editor-post-featured-image__menu-header { + margin-left: $grid-unit-10; + margin-right: $grid-unit-10; } diff --git a/packages/editor/src/components/post-featured-image/toggle.js b/packages/editor/src/components/post-featured-image/toggle.js new file mode 100644 index 00000000000000..c8f1e8cf219eec --- /dev/null +++ b/packages/editor/src/components/post-featured-image/toggle.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { Button } from '@wordpress/components'; + +export default function PostFeaturedImageToggle( { children, ...props } ) { + return ( + <Button + className="editor-post-featured-image__toggle" + variant="tertiary" + { ...props } + > + { children } + </Button> + ); +} diff --git a/packages/editor/src/components/post-featured-image/upload-provider.js b/packages/editor/src/components/post-featured-image/upload-provider.js new file mode 100644 index 00000000000000..d391c24a8b5672 --- /dev/null +++ b/packages/editor/src/components/post-featured-image/upload-provider.js @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import { FormFileUpload } from '@wordpress/components'; +import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor'; + +export default function PostFeaturedImageUploadProvider( { + fallback, + title, + selectedId, + allowedMediaTypes, + allowedUploadTypes, + onSelect, + onUpload, + children, +} ) { + return ( + <MediaUploadCheck fallback={ fallback }> + <MediaUpload + title={ title } + onSelect={ onSelect } + unstableFeaturedImageFlow + allowedTypes={ allowedMediaTypes } + modalClass="editor-post-featured-image__media-modal" + value={ selectedId } + render={ ( { open: openMediaLibrary } ) => ( + <FormFileUpload + onChange={ ( event ) => onUpload( event.target.files ) } + accept={ allowedUploadTypes } + render={ ( { openFileDialog } ) => + children( { openMediaLibrary, openFileDialog } ) + } + /> + ) } + /> + </MediaUploadCheck> + ); +}