';
+
+ if ( isset( $attributes['displayFeaturedImage'] ) && $attributes['displayFeaturedImage'] && ! $is_tiled ) {
if ( $thumbnail ) {
$image_alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
@@ -115,10 +124,6 @@ function ( $x ) use ( $sticky_posts_id ) {
$class .= ' o-posts-grid-columns-' . $attributes['columns'];
}
- if ( isset( $attributes['cropImage'] ) && true === $attributes['cropImage'] ) {
- $class .= ' o-crop-img';
- }
-
$wrapper_attributes = get_block_wrapper_attributes();
$block_content = sprintf(
@@ -293,6 +298,9 @@ protected function render_featured_post( $post, $attributes ) {
$size = isset( $attributes['imageSize'] ) ? $attributes['imageSize'] : 'medium';
$thumb_id = get_post_thumbnail_id( $id );
$image_alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
+ $style = '';
+ $image_url = wp_get_attachment_image_src( $thumb_id, $size );
+ $is_tiled = isset( $attributes['className'] ) && false !== strpos( $attributes['className'], 'is-style-tiled' );
if ( ! $image_alt ) {
$image_alt = get_the_title( $id );
@@ -300,7 +308,7 @@ protected function render_featured_post( $post, $attributes ) {
$thumbnail = wp_get_attachment_image( $thumb_id, $size, false, array( 'alt' => $image_alt ) );
- if ( $thumbnail ) {
+ if ( $image_url && ! $is_tiled ) {
$html .= sprintf(
'
',
esc_url( get_the_permalink( $id ) ),
@@ -308,11 +316,18 @@ protected function render_featured_post( $post, $attributes ) {
);
}
+ if ( $is_tiled && $image_url ) {
+ $style = sprintf(
+ ' style="background-image: url(%1$s); background-size: cover; background-position: center center;"',
+ esc_url( $image_url[0] )
+ );
+ }
+
$html .= '
';
$html .= $this->get_post_fields( $id, $attributes );
$html .= '
';
- return sprintf( '
', $html );
+ return sprintf( '
', $html );
}
/**
diff --git a/src/blocks/blocks/posts/block.json b/src/blocks/blocks/posts/block.json
index 7cc2103d5..5ab79516a 100644
--- a/src/blocks/blocks/posts/block.json
+++ b/src/blocks/blocks/posts/block.json
@@ -110,9 +110,8 @@
"type": "boolean",
"default": false
},
- "cropImage": {
- "type": "boolean",
- "default": false
+ "imageRatio": {
+ "type": "string"
},
"customTitleFontSize": {
"type": [ "string", "number" ]
@@ -147,6 +146,9 @@
"backgroundColor": {
"type": "string"
},
+ "backgroundOverlay": {
+ "type": "string"
+ },
"borderColor": {
"type": "string"
},
diff --git a/src/blocks/blocks/posts/components/layout/featured.js b/src/blocks/blocks/posts/components/layout/featured.js
index 6e5f16e0b..741707852 100644
--- a/src/blocks/blocks/posts/components/layout/featured.js
+++ b/src/blocks/blocks/posts/components/layout/featured.js
@@ -14,7 +14,15 @@ import { applyFilters } from '@wordpress/hooks';
* Internal dependencies
*/
-import Thumbnail from './thumbnail.js';
+
+import {
+ Thumbnail,
+ useThumbnail
+} from './thumbnail.js';
+
+import { getActiveStyle } from '../../../../helpers/helper-functions.js';
+
+import { styles } from '../../constants.js';
import {
PostsCategory,
@@ -29,16 +37,34 @@ const FeaturedPost = ({
author,
categoriesList
}) => {
+ const activeStyle = getActiveStyle( styles, attributes?.className );
+ const isTiled = 'tiled' === activeStyle;
+ const { featuredImage } = useThumbnail( post?.featured_media, post.title?.rendered, attributes?.imageSize );
+
if ( ! post ) {
return '';
}
const category = categoriesList && 0 < post?.categories?.length ? categoriesList.find( item => item.id === post.categories[0]) : undefined;
+ const hasFeaturedImage = 0 !== post.featured_media && attributes.displayFeaturedImage;
+
+ const css = {
+ backgroundPosition: 'center center',
+ backgroundSize: 'cover'
+ };
+
+ if ( hasFeaturedImage && isTiled ) {
+ css.backgroundImage = `url(${ featuredImage })`;
+ }
+
return (
-
- { attributes.displayFeaturedImage && (
+
+ { ( attributes.displayFeaturedImage && ! isTiled ) && (
{
+ const activeStyle = getActiveStyle( styles, attributes?.className );
+ const isTiled = 'tiled' === activeStyle;
const postsToDisplay = posts
.filter( post => post );
@@ -36,72 +49,89 @@ const Layout = ({
'grid' === attributes.style ?
classnames(
'is-grid',
- `o-posts-grid-columns-${ attributes.columns }`,
- {
- 'o-crop-img': attributes.cropImage
- }
+ `o-posts-grid-columns-${ attributes.columns }`
) :
- classnames(
- 'is-list',
- {
- 'o-crop-img': attributes.cropImage
- }
- )
+ 'is-list'
}
>
{ postsToDisplay
.slice( attributes.enableFeaturedPost ? 1 : 0 )
.map( post => {
- const category = categoriesList && 0 < post?.categories?.length ? categoriesList.find( item => item.id === post.categories[0]) : undefined;
- const categories = categoriesList && 0 < post?.categories?.length ? categoriesList.filter( item => post.categories.includes( item.id ) ) : [];
- const author = authors && post.author ? authors.find( item => item.id === post.author ) : undefined;
return (
-
-
- { ( 0 !== post.featured_media && attributes.displayFeaturedImage ) && (
-
- ) }
-
-
- { attributes.template.map( element => {
- switch ( element ) {
- case 'category':
- return
;
- case 'title':
- return
;
- case 'meta':
- return
;
- case 'description':
- return
;
- default:
- return applyFilters( 'otter.postsBlock.templateLoop', '', element, attributes );
- }
- }) }
-
-
-
+
);
}) }
);
};
+const PostBody = ({ post, attributes, categoriesList, authors, isTiled }) => {
+ const { featuredImage } = useThumbnail( post?.featured_media, post.title?.rendered, attributes?.imageSize );
+ const category = categoriesList && 0 < post?.categories?.length ? categoriesList.find( item => item.id === post.categories[0]) : undefined;
+ const categories = categoriesList && 0 < post?.categories?.length ? categoriesList.filter( item => post.categories.includes( item.id ) ) : [];
+ const author = authors && post.author ? authors.find( item => item.id === post.author ) : undefined;
+ const hasFeaturedImage = 0 !== post.featured_media && attributes.displayFeaturedImage;
+ const css = {
+ backgroundPosition: 'center center',
+ backgroundSize: 'cover'
+ };
+
+ if ( hasFeaturedImage && isTiled ) {
+ css.backgroundImage = `url(${ featuredImage })`;
+ }
+
+ return (
+
+
+ { ( hasFeaturedImage && ! isTiled ) && (
+
+ ) }
+
+
+ { attributes.template.map( element => {
+ switch ( element ) {
+ case 'category':
+ return
;
+ case 'title':
+ return
;
+ case 'meta':
+ return
;
+ case 'description':
+ return
;
+ default:
+ return applyFilters( 'otter.postsBlock.templateLoop', '', element, attributes );
+ }
+ }) }
+
+
+
+ );
+};
+
export const PostsCategory = ({ attributes, element, category, categoriesList }) => {
if ( undefined !== category && ( attributes.displayCategory && categoriesList ) ) {
return
{ unescapeHTML( category.name ) };
diff --git a/src/blocks/blocks/posts/components/layout/thumbnail.js b/src/blocks/blocks/posts/components/layout/thumbnail.js
index 4bc2475f5..2aa363322 100644
--- a/src/blocks/blocks/posts/components/layout/thumbnail.js
+++ b/src/blocks/blocks/posts/components/layout/thumbnail.js
@@ -12,17 +12,18 @@ import { useSelect } from '@wordpress/data';
import { isEmpty } from 'lodash';
-const Thumbnail = ({
- id,
- link,
- alt,
- size,
- imgStyle
-}) => {
+export const useThumbnail = ( id, size, alt ) => {
const {
featuredImage,
altText
} = useSelect( select => {
+ if ( ! id ) {
+ return {
+ featuredImage: null,
+ altText: null
+ };
+ }
+
const image = select( 'core' ).getMedia( id, { context: 'view' });
const featuredImage = image ?
@@ -39,6 +40,20 @@ const Thumbnail = ({
};
}, [ size, id ]);
+ return {
+ featuredImage,
+ altText
+ };
+};
+
+export const Thumbnail = ({
+ id,
+ link,
+ alt,
+ size,
+ imgStyle
+}) => {
+ const { featuredImage, altText } = useThumbnail( id, size, alt );
if ( null === featuredImage ) {
return
;
@@ -52,5 +67,3 @@ const Thumbnail = ({
);
};
-
-export default Thumbnail;
diff --git a/src/blocks/blocks/posts/components/sortable.js b/src/blocks/blocks/posts/components/sortable.js
index 15f4b06bc..fdb8ef08a 100644
--- a/src/blocks/blocks/posts/components/sortable.js
+++ b/src/blocks/blocks/posts/components/sortable.js
@@ -168,10 +168,38 @@ export const SortableItem = ({
onChange={ imageSize => setAttributes({ imageSize }) }
/>
-
setAttributes({ cropImage }) }
+ {
+ if ( 'inherit' === imageRatio ) {
+ return setAttributes({ imageRatio: undefined });
+ }
+
+ setAttributes({ imageRatio });
+ } }
/>
) }
diff --git a/src/blocks/blocks/posts/constants.js b/src/blocks/blocks/posts/constants.js
new file mode 100644
index 000000000..f5ab1462f
--- /dev/null
+++ b/src/blocks/blocks/posts/constants.js
@@ -0,0 +1,20 @@
+/**
+ * WordPress dependencies.
+ */
+import { __ } from '@wordpress/i18n';
+
+export const styles = [
+ {
+ label: __( 'Default', 'otter-blocks' ),
+ value: 'default',
+ isDefault: true
+ },
+ {
+ label: __( 'Boxed', 'otter-blocks' ),
+ value: 'boxed'
+ },
+ {
+ label: __( 'Tiled', 'otter-blocks' ),
+ value: 'tiled'
+ }
+];
diff --git a/src/blocks/blocks/posts/edit.js b/src/blocks/blocks/posts/edit.js
index 655565861..65054a8c8 100644
--- a/src/blocks/blocks/posts/edit.js
+++ b/src/blocks/blocks/posts/edit.js
@@ -59,18 +59,7 @@ import {
import '../../components/store/index.js';
import FeaturedPost from './components/layout/featured.js';
import { domReady } from '../../helpers/frontend-helper-functions';
-
-const styles = [
- {
- label: __( 'Default', 'otter-blocks' ),
- value: 'default',
- isDefault: true
- },
- {
- label: __( 'Boxed', 'otter-blocks' ),
- value: 'boxed'
- }
-];
+import { styles } from './constants.js';
const { attributes: defaultAttributes } = metadata;
@@ -259,13 +248,19 @@ const Edit = ({
const inlineStyles = {
'--img-border-radius': isObject( attributes.borderRadius ) ? boxValues( attributes.borderRadius ) : _px( attributes.borderRadius ),
'--img-box-shadow': imageBoxShadow.active && `${ imageBoxShadow.horizontal }px ${ imageBoxShadow.vertical }px ${ imageBoxShadow.blur }px ${ imageBoxShadow.spread }px ${ hex2rgba( imageBoxShadow.color, imageBoxShadow.colorOpacity ) }`,
+ '--image-ratio': attributes.imageRatio,
'--border-width': _px( attributes.borderWidth ),
'--border-radius': boxValues( attributes.cardBorderRadius ),
+ '--border-radius-start-start': _px( attributes.cardBorderRadius?.top ),
+ '--border-radius-start-end': _px( attributes.cardBorderRadius?.right ),
+ '--border-radius-end-start': _px( attributes.cardBorderRadius?.bottom ),
+ '--border-radius-end-end': _px( attributes.cardBorderRadius?.left ),
'--box-shadow': boxShadow.active && `${ boxShadow.horizontal }px ${ boxShadow.vertical }px ${ boxShadow.blur }px ${ boxShadow.spread }px ${ hex2rgba( boxShadow.color, boxShadow.colorOpacity ) }`,
'--vert-align': _align( attributes.verticalAlign ),
'--text-align': attributes.textAlign,
'--text-color': attributes.textColor,
'--background-color': attributes.backgroundColor,
+ '--background-overlay': attributes.backgroundOverlay || '#0000005e',
'--border-color': attributes.borderColor,
'--content-gap': attributes.contentGap,
'--img-width': responsiveGetAttributes([ _px( attributes.imageWidth ), attributes.imageWidthTablet, attributes.imageWidthMobile ]),
diff --git a/src/blocks/blocks/posts/inspector.js b/src/blocks/blocks/posts/inspector.js
index 229066a67..2103e0115 100644
--- a/src/blocks/blocks/posts/inspector.js
+++ b/src/blocks/blocks/posts/inspector.js
@@ -51,18 +51,7 @@ import {
import { useResponsiveAttributes } from '../../helpers/utility-hooks.js';
import { useTabSwitch } from '../../helpers/block-utility';
import { makeBox } from '../../plugins/copy-paste/utils';
-
-const styles = [
- {
- label: __( 'Default', 'otter-blocks' ),
- value: 'default',
- isDefault: true
- },
- {
- label: __( 'Boxed', 'otter-blocks' ),
- value: 'boxed'
- }
-];
+import { styles } from './constants.js';
const defaultFontSizes = [
{
@@ -104,6 +93,7 @@ const Inspector = ({
isLoading
}) => {
const [ tab, setTab ] = useTabSwitch( attributes.id, 'settings' );
+ const style = getActiveStyle( styles, attributes?.className );
const {
slugs
@@ -443,6 +433,15 @@ const Inspector = ({
label: __( 'Border', 'otter-blocks' ),
isShownByDefault: false
},
+ ...( 'tiled' === style ? [
+ {
+ value: attributes.backgroundOverlay,
+ onChange: backgroundOverlay => setAttributes({ backgroundOverlay }),
+ label: __( 'Background Overlay', 'otter-blocks' ),
+ enableAlpha: true,
+ isShownByDefault: false
+ }
+ ] : []),
...( attributes.hasPagination ? [
{
value: attributes.pagColor,
@@ -644,6 +643,7 @@ const Inspector = ({
values={ attributes.cardBorderRadius ?? makeBox( '0px' ) }
onChange={ cardBorderRadius => setAttributes({ cardBorderRadius }) }
id="o-border-raduis-box"
+ allowReset={ false }
/>
{
diff --git a/src/blocks/blocks/posts/style.scss b/src/blocks/blocks/posts/style.scss
index 5f7ae8546..940191095 100644
--- a/src/blocks/blocks/posts/style.scss
+++ b/src/blocks/blocks/posts/style.scss
@@ -3,11 +3,17 @@
--vert-align: initial;
--img-border-radius: 0;
--img-box-shadow: none;
+ --image-ratio: inherit;
--border-width: 0;
--text-color: inherit;
--background-color: inherit;
+ --background-overlay: #0000005e;
--border-color: inherit;
--border-radius: 0;
+ --border-radius-start-start: 0;
+ --border-radius-start-end: 0;
+ --border-radius-end-start: 0;
+ --border-radius-end-end: 0;
--box-shadow: none;
--content-gap: 10px;
@@ -64,11 +70,72 @@
}
&.is-style-boxed {
+ --background-color: rgb( 240, 245, 250);
--border-width: 1px;
.o-posts-grid-post-body {
padding: var( --content-padding, 20px );
- background: rgb( 240, 245, 250);
+ }
+ }
+
+ &.is-style-tiled {
+ .o-posts-grid-post-blog {
+ background-color: var( --background-color );
+ border-width: var( --border-width );
+ border-style: solid;
+ border-color: var( --border-color );
+ border-radius: var( --border-radius );
+ box-shadow: var( --box-shadow );
+ }
+
+ .o-featured-post {
+ background-color: var( --background-color );
+
+ .o-posts-grid-post-body {
+ background: var( --background-overlay );
+ border-radius: calc( var( --border-radius-start-start ) - var( --border-width) ) calc( var( --border-radius-start-end ) - var( --border-width) ) calc( var( --border-radius-end-start ) - var( --border-width) ) calc( var( --border-radius-end-end ) - var( --border-width) );
+ }
+ }
+
+ .o-posts-grid-post {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: end;
+ background: var( --background-overlay );
+ border-radius: calc( var( --border-radius-start-start ) - var( --border-width) ) calc( var( --border-radius-start-end ) - var( --border-width) ) calc( var( --border-radius-end-start ) - var( --border-width) ) calc( var( --border-radius-end-end ) - var( --border-width) );
+ }
+
+ .o-posts-grid-post,
+ .o-featured-post {
+ .o-posts-grid-post-body {
+ padding: var( --content-padding, 36px );
+ color: var( --text-color, #fff );
+
+ .o-posts-grid-post-title a {
+ color: var( --text-color, #fff );
+ }
+ }
+ }
+ }
+
+ &:not(.is-style-tiled) {
+ .o-posts-grid-post-blog {
+ .o-posts-grid-post {
+ background: var( --background-color );
+ border-width: var( --border-width );
+ border-style: solid;
+ border-color: var( --border-color );
+ border-radius: var( --border-radius );
+ box-shadow: var( --box-shadow );
+ }
+ }
+
+ .o-featured-container {
+ .o-featured-post {
+ background-color: var( --background-color );
+ }
}
}
@@ -116,7 +183,6 @@
img {
height: 100%;
- object-fit: cover;
}
}
@@ -130,21 +196,6 @@
}
}
- .o-crop-img {
- .o-posts-grid-post-blog {
- .o-posts-grid-post {
- .o-posts-grid-post-image {
- img {
- width: 150px;
- height: 150px;
- object-fit: cover;
- border-radius: var( --img-border-radius );
- }
- }
- }
- }
- }
-
.o-posts-grid-post-blog {
width: 100%;
position: relative;
@@ -156,12 +207,6 @@
.o-posts-grid-post {
overflow: hidden;
- border-width: var( --border-width );
- border-style: solid;
- border-color: var( --border-color );
- border-radius: var( --border-radius );
- background: var( --background-color );
- box-shadow: var( --box-shadow );
}
}
@@ -184,6 +229,9 @@
border-radius: 5px;
border-radius: var( --img-border-radius );
box-shadow: var( --img-box-shadow );
+ object-fit: cover;
+ object-position: center center;
+ aspect-ratio: var( --image-ratio );
}
}
@@ -201,6 +249,11 @@
color: var( --text-color );
text-transform: capitalize;
margin: 0;
+
+ a {
+ font-size: var( --meta-text-size );
+ color: var( --text-color );
+ }
}
.o-posts-grid-post-title {
@@ -223,6 +276,11 @@
font-size: var( --meta-text-size );
color: var( --text-color );
margin: 0;
+
+ a {
+ font-size: var( --meta-text-size );
+ color: var( --text-color );
+ }
}
.o-posts-grid-post-description {
@@ -254,7 +312,6 @@
border-style: solid;
border-color: var( --border-color );
border-radius: var( --border-radius );
- background-color: var( --background-color );
box-shadow: var( --box-shadow );
margin-bottom: var( --row-gap );
@@ -265,6 +322,8 @@
width: 100%;
height: 250px;
object-fit: cover;
+ object-position: center center;
+ aspect-ratio: var( --image-ratio );
}
}
diff --git a/src/blocks/blocks/posts/types.d.ts b/src/blocks/blocks/posts/types.d.ts
index 37895f475..1bf0d122e 100644
--- a/src/blocks/blocks/posts/types.d.ts
+++ b/src/blocks/blocks/posts/types.d.ts
@@ -26,7 +26,7 @@ type Attributes = {
displayComments: boolean
displayPostCategory: boolean
displayReadMoreLink: boolean
- cropImage: boolean
+ imageRatio: string
customTitleFontSize: number
customTitleFontSizeTablet: number
customTitleFontSizeMobile: number
diff --git a/tests/test-post-grid-block.php b/tests/test-post-grid-block.php
index 8bcc970c0..5ddec6774 100644
--- a/tests/test-post-grid-block.php
+++ b/tests/test-post-grid-block.php
@@ -53,7 +53,6 @@ class Test_Post_Grid_Block extends WP_UnitTestCase {
'displayComments' => true,
'displayPostCategory' => false,
'displayReadMoreLink' => false,
- 'cropImage' => false,
'boxShadow' => array(
'active' => false,
'colorOpacity' => 50,