Skip to content

Commit

Permalink
Add ImageBlock to demo (#57)
Browse files Browse the repository at this point in the history
* add ImageBlock to demo

* remove unused styling for growToIverflowWidth

* add commonImageBlockStyles to MjmlHead

* set loaded width to doubled value of maximum rendered width

* fix prettier problems

* remove unused allowedImageSizes

* remove growToOverflow completely

* use cssClass directly

* add indentedSectionGroupStyles to fix responsive behaviour

* rename variable contentWidth to mailWidth and add new variable contentWidth to theme to avoid repetitive calculation of width

* use contentWidth from theme in imageBlockHelpers

* use css helper

* use variables from theme in IndentedSectionGroup

* use theme variable directly instead of defining a new one

* correct css class

* remove heightValues to keep correct aspectRatio

* correct contentWidth and aspectRatio

* remove padding from image

* pass paddingLeft and -Right directly to RichTextBlock to allow elements having full contentWidth

* undo changes on RichTextBlock and instead pass padding on IndentedSectionGroup of the image itself

* add MjmlAttributes to remove default padding

* use MjmlSection in ImageBlock instead of IndentedSectionGroup

* use inline styles for CommonImageBlock

* remove padding of MjmlSection globally

---------

Co-authored-by: Julia Wegmayr <[email protected]>
  • Loading branch information
juliawegmayr and Julia Wegmayr authored Aug 22, 2024
1 parent 72fb133 commit 7e56895
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"eslint.workingDirectories": ["demo", "package"]
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createBlocksBlock } from "@comet/blocks-admin";
import { PixelImageBlock } from "@comet/cms-admin";
import { RichTextBlock } from "@src/common/blocks/RichTextBlock";

import { DividerBlock } from "./DividerBlock";
Expand All @@ -8,5 +9,6 @@ export const EmailCampaignContentBlock = createBlocksBlock({
supportedBlocks: {
divider: DividerBlock,
text: RichTextBlock,
image: PixelImageBlock,
},
});
6 changes: 4 additions & 2 deletions demo/api/block-meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@
"kind": "OneOfBlocks",
"blocks": {
"text": "RichText",
"divider": "EmailCampaignDivider"
"divider": "EmailCampaignDivider",
"image": "PixelImage"
},
"nullable": false
}
Expand Down Expand Up @@ -243,7 +244,8 @@
"kind": "OneOfBlocks",
"blocks": {
"text": "RichText",
"divider": "EmailCampaignDivider"
"divider": "EmailCampaignDivider",
"image": "PixelImage"
},
"nullable": false
}
Expand Down
2 changes: 1 addition & 1 deletion demo/api/src/comet-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dam": {
"additionalMimeTypes": [],
"uploadsMaxFileSize": 500,
"allowedImageSizes": [320, 420, 640, 750, 768, 828, 1024, 1080, 1200, 1920, 2048, 3840],
"allowedImageSizes": [1200],
"allowedImageAspectRatios": ["16x9", "4x3", "3x2", "3x1", "2x1", "1x1", "1x2", "1x3", "2x3", "3x4", "9x16"]
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createBlocksBlock } from "@comet/blocks-api";
import { PixelImageBlock } from "@comet/cms-api";

import { EmailCampaignDividerBlock } from "./email-campaign-divider.block";
import { EmailCampaignRichTextBlock } from "./email-campaign-rich-text.block";
Expand All @@ -8,6 +9,7 @@ export const EmailCampaignContentBlock = createBlocksBlock(
supportedBlocks: {
text: EmailCampaignRichTextBlock,
divider: EmailCampaignDividerBlock,
image: PixelImageBlock,
},
},
{
Expand Down
3 changes: 3 additions & 0 deletions demo/campaign/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const nextConfig = {
compiler: {
styledComponents: true,
},
env: {
DAM_ALLOWED_IMAGE_SIZES: cometConfig.dam.allowedImageSizes.join(","),
},
async rewrites() {
return [
{
Expand Down
3 changes: 3 additions & 0 deletions demo/campaign/src/blocks/ContentBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { RichTextBlock } from "@src/blocks//RichTextBlock";
import { DividerBlock } from "@src/blocks/DividerBlock";
import React from "react";

import { ImageBlock } from "./ImageBlock";

const supportedBlocks: SupportedBlocks = {
divider: (data) => <DividerBlock />,
text: (data) => <RichTextBlock data={data} />,
image: (data) => <ImageBlock data={data} />,
};

interface Props {
Expand Down
15 changes: 15 additions & 0 deletions demo/campaign/src/blocks/ImageBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PropsWithData } from "@comet/cms-site";
import { MjmlColumn, MjmlSection } from "@luma-team/mjml-react";
import { PixelImageBlockData } from "@src/blocks.generated";
import { CommonImageBlock } from "@src/common/blocks/CommonImageBlock";
import { theme } from "@src/util/theme";

export const ImageBlock = ({ data }: PropsWithData<PixelImageBlockData>) => {
return (
<MjmlSection>
<MjmlColumn>
<CommonImageBlock data={data} desktopRenderWidth={theme.mailSize.contentWidth} />
</MjmlColumn>
</MjmlSection>
);
};
61 changes: 61 additions & 0 deletions demo/campaign/src/common/blocks/CommonImageBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { calculateInheritAspectRatio, generateImageUrl } from "@comet/cms-site";
import { MjmlImage, MjmlStyle } from "@luma-team/mjml-react";
import { PixelImageBlockData } from "@src/blocks.generated";
import { css } from "@src/util/stylesHelper";
import { theme } from "@src/util/theme";
import * as React from "react";

import { getDamAllowedImageWidth } from "../helpers/imageBlockHelpers";

interface Props extends React.ComponentProps<typeof MjmlImage> {
data: PixelImageBlockData;
desktopRenderWidth: number;
}

export const commonImageBlockStyles = (
<MjmlStyle>{css`
@media (max-width: ${theme.mailSize.contentWidth - 1}px) {
.image-block > table > tbody > tr > td {
width: 100% !important;
}
.image-block img {
height: auto !important;
}
}
`}</MjmlStyle>
);

export const CommonImageBlock = ({ data, desktopRenderWidth, ...restProps }: Props) => {
const { damFile, cropArea, urlTemplate } = data;

if (!damFile?.image) {
return null;
}

const usedCropArea = cropArea ?? damFile.image.cropArea;
const usedAspectRatio = calculateInheritAspectRatio(damFile.image, usedCropArea);

const imageUrl: string = generateImageUrl(
{
width: getDamAllowedImageWidth(desktopRenderWidth, theme.mailSize.contentWidth),
src: urlTemplate,
},
usedAspectRatio,
);

const desktopImageHeight = Math.round(desktopRenderWidth / usedAspectRatio);

return (
<MjmlImage
src={imageUrl}
fluidOnMobile="true"
cssClass="image-block"
width={desktopRenderWidth}
height={desktopImageHeight}
alt={damFile.altText}
title={damFile.title}
padding={0}
{...restProps}
/>
);
};
23 changes: 23 additions & 0 deletions demo/campaign/src/common/helpers/imageBlockHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const validSizes: number[] = (process.env.DAM_ALLOWED_IMAGE_SIZES as string)
.split(",")
.map((value) => parseInt(value))
.sort((a, b) => a - b);

export const getDamAllowedImageWidth = (minimumWidth: number, contentWidth): number => {
let width: number | null = null;
const largestPossibleWidth = validSizes[validSizes.length - 1];

validSizes.forEach((validWidth) => {
if (minimumWidth === contentWidth) {
width = contentWidth * 2;
} else if (!width && validWidth >= minimumWidth * 2) {
width = validWidth;
}
});

if (!width) {
return largestPossibleWidth;
}

return width;
};
18 changes: 14 additions & 4 deletions demo/campaign/src/components/IndentedSectionGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MjmlGroup, MjmlSection } from "@luma-team/mjml-react";
import { MjmlGroup, MjmlSection, MjmlStyle } from "@luma-team/mjml-react";
import { css } from "@src/util/stylesHelper";
import { theme } from "@src/util/theme";
import * as React from "react";

Expand All @@ -7,18 +8,27 @@ export interface IndentedSectionGroupProps extends React.ComponentProps<typeof M
cssClass?: string;
}

const CONTENT_WIDTH = theme.mailSize.contentWidth - theme.mailSize.contentSpacing * 2;
export const indentedSectionGroupStyles = (
<MjmlStyle>{css`
@media (max-width: ${theme.mailSize.contentWidth - 1}px) {
.indented-section__group {
width: 100% !important;
max-width: ${theme.mailSize.contentWidth};
}
}
`}</MjmlStyle>
);

export const IndentedSectionGroup = ({ children, cssClass, ...restProps }: IndentedSectionGroupProps) => {
return (
<MjmlSection
cssClass={`${cssClass || ""}`.trim()}
cssClass={`indented-section ${cssClass || ""}`.trim()}
paddingLeft={theme.mailSize.contentSpacing}
paddingRight={theme.mailSize.contentSpacing}
backgroundColor={theme.colors.background.content}
{...restProps}
>
<MjmlGroup width={CONTENT_WIDTH}>{children}</MjmlGroup>
<MjmlGroup cssClass="indented-section__group">{children}</MjmlGroup>
</MjmlSection>
);
};
12 changes: 11 additions & 1 deletion demo/campaign/src/components/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Mjml, MjmlBody, MjmlHead, MjmlTitle } from "@luma-team/mjml-react";
import { Mjml, MjmlAttributes, MjmlBody, MjmlDivider, MjmlHead, MjmlSection, MjmlText, MjmlTitle } from "@luma-team/mjml-react";
import { commonImageBlockStyles } from "@src/common/blocks/CommonImageBlock";
import { css } from "@src/util/stylesHelper";
import { theme } from "@src/util/theme";
import { MjmlConditionalComment } from "mjml-react/extensions";
import React from "react";
import { renderToString } from "react-dom/server";

import { indentedSectionGroupStyles } from "./IndentedSectionGroup";

type Props = React.PropsWithChildren<{
title?: string;
}>;
Expand Down Expand Up @@ -32,7 +35,14 @@ export const Root: React.FC<Props> = ({ children, title }) => {
return (
<Mjml>
<MjmlHead>
<MjmlAttributes>
<MjmlText padding={0} />
<MjmlDivider padding={0} />
<MjmlSection padding={0} />
</MjmlAttributes>
{!!title && <MjmlTitle>{title}</MjmlTitle>}
{indentedSectionGroupStyles}
{commonImageBlockStyles}
<MjmlConditionalComment condition="if mso">{outlookFontFixStyleString}</MjmlConditionalComment>
</MjmlHead>
<MjmlBody width={theme.mailSize.contentWidth}>{children}</MjmlBody>
Expand Down
3 changes: 3 additions & 0 deletions demo/site/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const nextConfig = {

return config;
},
env: {
DAM_ALLOWED_IMAGE_SIZES: cometConfig.dam.allowedImageSizes.join(","),
},
i18n,
typescript: {
ignoreBuildErrors: process.env.NODE_ENV === "production",
Expand Down

0 comments on commit 7e56895

Please sign in to comment.