Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

experimental pagebuilder support #2178

Draft
wants to merge 7 commits into
base: canary
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/framework/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ const { categories, products, ..., stylesheet } = props

```tsx
<CategoryDescription
description={category.description}
category={category}
sx={{ stylesheet, minWidth: '100vw' }}
/>
```
Expand Down
2 changes: 2 additions & 0 deletions examples/magento-graphcms/.meshrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ sources:
Content-Currency: "{context.headers['content-currency']}"
serve:
playground: true
additionalResolvers:
- '@graphcommerce/magento-pagebuilder/mesh.ts'
1 change: 1 addition & 0 deletions examples/magento-graphcms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@graphcommerce/magento-customer": "8.0.0-canary.95",
"@graphcommerce/magento-graphql": "8.0.0-canary.95",
"@graphcommerce/magento-newsletter": "8.0.0-canary.95",
"@graphcommerce/magento-pagebuilder": "8.0.0-canary.95",
"@graphcommerce/magento-payment-included": "8.0.0-canary.95",
"@graphcommerce/magento-product": "8.0.0-canary.95",
"@graphcommerce/magento-product-bundle": "8.0.0-canary.95",
Expand Down
2 changes: 1 addition & 1 deletion examples/magento-graphcms/pages/[...url].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function CategoryPage(props: CategoryProps) {

{isCategory && !isLanding && (
<>
<CategoryDescription description={category.description} />
<CategoryDescription category={category} />
<CategoryChildren params={params}>{category.children}</CategoryChildren>
<CategoryFilterLayout
params={params}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { extendableComponent } from '@graphcommerce/next-ui'
import { Box, SxProps, Theme } from '@mui/material'
import { CategoryDescriptionFragment } from './CategoryDescription.gql'

export type CategoryDescriptionProps = Omit<CategoryDescriptionFragment, 'uid'> & {
export type CategoryDescriptionProps = {
category: CategoryDescriptionFragment
sx?: SxProps<Theme>
}

Expand All @@ -11,7 +12,8 @@ const parts = ['root'] as const
const { classes } = extendableComponent(cmpName, parts)

export function CategoryDescription(props: CategoryDescriptionProps) {
const { name, description, display_mode, sx = [], ...divProps } = props
const { category, sx = [], ...divProps } = props
const { description } = category

return description ? (
// eslint-disable-next-line react/no-danger
Expand Down
2 changes: 1 addition & 1 deletion packages/magento-pagebuilder/ContentTypes/Block/Block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const Block: BlockContentType['component'] = (props) => {
const { content } = additional

return (
<Box style={cssProps} className={cssClasses.join(' ')}>
<Box sx={cssProps} className={cssClasses.join(' ')}>
{content?.map((child, index) => (
// eslint-disable-next-line react/no-array-index-key
<PagebuilderRender contentItem={child} key={index} />
Expand Down
44 changes: 12 additions & 32 deletions packages/magento-pagebuilder/ContentTypes/ButtonItem/ButtonItem.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
/* eslint-disable import/no-extraneous-dependencies */
import { useApolloClient, useQuery } from '@graphcommerce/graphql'
import { productLink, ProductLinkProps } from '@graphcommerce/magento-product'
import { StoreConfigDocument } from '@graphcommerce/magento-store'
import { productLink } from '@graphcommerce/magento-product'
import { Button, ButtonProps } from '@mui/material'
import { useRouter } from 'next/router'
import React from 'react'
import { RouteDocument } from '../../Route.gql'
import { extractAdvancedProps } from '../../utils'
import { ButtonItemContentType } from './types'
import { useQuery } from '@graphcommerce/graphql'
import { StoreConfigDocument } from '@graphcommerce/magento-store'

/**
* Page Builder ButtonItem component.
Expand All @@ -18,9 +15,7 @@ import { ButtonItemContentType } from './types'
export const ButtonItem: ButtonItemContentType['component'] = (props) => {
const [cssProps, cssClasses, additional] = extractAdvancedProps(props)

const config = useQuery(StoreConfigDocument).data?.storeConfig
const client = useApolloClient()
const { locale, push } = useRouter()
const linkBase = useQuery(StoreConfigDocument).data?.storeConfig?.secure_base_link_url

const { buttonType, link, openInNewTab = false, buttonText, linkType } = additional

Expand All @@ -30,32 +25,17 @@ export const ButtonItem: ButtonItemContentType['component'] = (props) => {
color: buttonType === 'primary' ? 'primary' : 'secondary',
}

const handleClick: React.MouseEventHandler<HTMLAnchorElement> = async (e) => {
const { target } = e

const baseUrl = config?.secure_base_link_url ?? 'x'

if (!(target instanceof HTMLAnchorElement)) return
if (!target.href.startsWith(baseUrl)) return
e.preventDefault()
if (!link) return null

const url = target.href.substring(baseUrl.length - 1)

const res = await client.query({ query: RouteDocument, variables: { url } })

const route = res.data?.route
if (!route) {
console.warn('Route not found', url)
return
}

if (route.type === 'PRODUCT') {
await push(productLink(route as ProductLinkProps))
}
}
const relativeUrl = linkBase ? link.replace(linkBase, '').trim() : link

return (
<Button href={link ?? ''} sx={cssProps} {...buttonProps} onClick={handleClick}>
<Button
href={linkType === 'product' ? productLink({ url_key: relativeUrl }) : relativeUrl}
// sx={sx}
{...buttonProps}
target={openInNewTab ? '_blank' : undefined}
>
{buttonText}
</Button>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ButtonsContentType } from './types'
export const Buttons: ButtonsContentType['component'] = (props) => {
const [cssProps, cssClasses, additional] = extractAdvancedProps(props)

const { isSameWidth, children, appearance } = additional
const { isSameWidth, children, appearance, contentType } = additional

const justify = {
left: 'start',
Expand All @@ -27,6 +27,8 @@ export const Buttons: ButtonsContentType['component'] = (props) => {

return (
<Box
data-content-type={contentType}
data-appearance={appearance}
sx={[
cssProps,
(theme) => ({
Expand Down
111 changes: 59 additions & 52 deletions packages/magento-pagebuilder/ContentTypes/Column/Column.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { Box, SxProps, Theme } from '@mui/material'
import React, { useRef } from 'react'
import {
ImageBackground,
ImageBackgroundComponentProps,
} from '../../components/MediaBackground/ImageBackground'
import { extractImageBackgroundProps } from '../../components/MediaBackground/extractImageBackgroundProps'
import { extractAdvancedProps } from '../../utils'
import {
extractAdvancedProps,
extractBorderProps,
extractCssClassesProps,
extractMarginProps,
extractPaddingProps,
extractTextAlignProps,
} from '../../utils'
import { ColumnContentType } from './types'

/**
Expand All @@ -11,19 +22,31 @@ import { ColumnContentType } from './types'
* Builder.
*/
export const Column: ColumnContentType['component'] = (incoming) => {
const [cssProps, cssClasses, additional] = extractAdvancedProps(incoming)
const [imageProps, props] = extractImageBackgroundProps(additional)
const [padding, remainging] = extractPaddingProps(incoming)
const [margin, remainging2] = extractMarginProps(remainging)
const [border, remainging3] = extractBorderProps(remainging2)
const [textAlign, remainging4] = extractTextAlignProps(remainging3)
const [cssClasses, remainging5] = extractCssClassesProps(remainging4)
const [imageProps, props] = extractImageBackgroundProps(remainging5)

const columnElement = useRef(null)
const { backgroundColor, children, minHeight, verticalAlignment, width, appearance } = props
const {
backgroundColor,
children,
minHeight,
verticalAlignment,
width,
appearance,
contentType,
sx,
} = props

// let image = desktopImage
// if (mobileImage && matchMedia && matchMedia('(max-width: 768px)').matches) {
// image = mobileImage
// }

const flexDirection = 'column'
const display = 'flex'

let alignSelf: React.CSSProperties['alignSelf']

Expand Down Expand Up @@ -58,54 +81,38 @@ export const Column: ColumnContentType['component'] = (incoming) => {
break
}

const dynamicStyles: SxProps<Theme> = {
alignSelf,
backgroundColor,
...cssProps,
display,
flexDirection,
justifyContent,
minHeight,
verticalAlignment,
width,
}

// if (image) {
// dynamicStyles.backgroundImage = bgImageStyle
// dynamicStyles.backgroundSize = backgroundSize
// dynamicStyles.backgroundPosition = backgroundPosition
// dynamicStyles.backgroundAttachment = backgroundAttachment
// dynamicStyles.backgroundRepeat = backgroundRepeat
// }

// // Determine the containers width and optimize the image
// useEffect(() => {
// if (image && columnElement.current) {
// if (backgroundSize === 'cover') {
// setBgImageStyle(
// `url(${resourceUrl(image, {
// type: 'image-wysiwyg',
// width: columnElement.current.offsetWidth,
// height: columnElement.current.offsetHeight,
// quality: 85,
// crop: false,
// fit: 'cover',
// })})`,
// )
// } else {
// setBgImageStyle(
// `url(${resourceUrl(image, {
// type: 'image-wysiwyg',
// quality: 85,
// })})`,
// )
// }
// }
// }, [backgroundSize, image, setBgImageStyle])

const hasImage = imageProps.desktopImage || imageProps.mobileImage
const sizes = width?.toString().replace('px', 'vw') as ImageBackgroundComponentProps['sizes']
return (
<Box sx={dynamicStyles} ref={columnElement}>
{children}
<Box
data-appearance={appearance}
data-content-type={contentType}
className={cssClasses.join(' ')}
sx={[
{
alignSelf,
backgroundColor,
...margin,
...border,
...textAlign,
flexDirection,
justifyContent,
minHeight,
verticalAlignment,
width,
},
hasImage ? { display: 'grid' } : { ...padding },
]}
ref={columnElement}
>
{hasImage ? (
<>
<ImageBackground sizes={sizes} {...imageProps} sx={{ gridArea: '1 / 1' }} />
<Box sx={{ gridArea: '1/1', zIndex: 1, p: 1, ...padding }}>{children}</Box>
</>
) : (
<>{children}</>
)}
</Box>
)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { Box } from '@mui/material'
import { ColumnGroupContentType } from './types'
import { extractAdvancedProps } from '../../utils'

/**
* Page Builder ColumnGroup component.
*
* This component is part of the Page Builder / PWA integration. It can be consumed without Page Builder.
*/
export const ColumnGroup: ColumnGroupContentType['component'] = (props) => {
const { display, children } = props
const [cssProps, cssClasses, additional] = extractAdvancedProps(props)
const { children, appearance, contentType } = additional

return <Box sx={{ flexWrap: { xs: 'wrap', md: 'initial' }, display }}>{children}</Box>
return (
<Box
data-appearance={appearance}
data-content-type={contentType}
className={cssClasses.join(' ')}
sx={cssProps}
>
{children}
</Box>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getIsHidden } from '../../utils'
import { ColumnGroupContentType } from './types'
import { getAdvanced } from '../../utils'
import type { ColumnGroupContentType } from './types'

export const columnGroupAggregator: ColumnGroupContentType['configAggregator'] = (node) => ({
display: node.style.display,
...getAdvanced(node),
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ContentType, ContentTypeConfig } from '../../types'
import { AdvancedProps } from '../../utils'

type ColumnGroupConfig = ContentTypeConfig<'column-group'>

export type ButtonItemProps = Pick<React.CSSProperties, 'display'>
export type ColumnGroupProps = AdvancedProps & Pick<React.CSSProperties, 'display'>

export type ColumnGroupContentType = ContentType<ColumnGroupConfig, ButtonItemProps>
export type ColumnGroupContentType = ContentType<ColumnGroupConfig, ColumnGroupProps>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Box } from '@mui/material'
import { extractAdvancedProps } from '../../utils'
import { ColumnLineContentType } from './types'

/**
* Page Builder ColumnGroup component.
*
* This component is part of the Page Builder / PWA integration. It can be consumed without Page Builder.
*/
export const ColumnLine: ColumnLineContentType['component'] = (props) => {
const [cssProps, cssClasses, additional] = extractAdvancedProps(props)
const { children, appearance, contentType, display, width, sx } = additional

return (
<Box
data-appearance={appearance}
data-content-type={contentType}
className={cssClasses.join(' ')}
sx={[...(Array.isArray(sx) ? sx : [sx]), cssProps, { display, width }]}
>
{children}
</Box>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { getAdvanced } from '../../utils'
import type { ColumnLineContentType } from './types'

export const columnLineAggregator: ColumnLineContentType['configAggregator'] = (node) => ({
display: node.style.display,
width: node.style.width,
...getAdvanced(node),
})
8 changes: 8 additions & 0 deletions packages/magento-pagebuilder/ContentTypes/ColumnLine/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ContentType, ContentTypeConfig } from '../../types'
import { AdvancedProps } from '../../utils'

type ColumnLineConfig = ContentTypeConfig<'column-group'>

export type ColumnLineProps = AdvancedProps & Pick<React.CSSProperties, 'display' | 'width'>

export type ColumnLineContentType = ContentType<ColumnLineConfig, ColumnLineProps>
Loading