import { extendableComponent, LazyHydrate, RenderType, responsiveVal, sxx, } from '@graphcommerce/next-ui' import type { BoxProps, Breakpoint, Theme } from '@mui/material' import { Box, useTheme } from '@mui/material' import React from 'react' import { AddProductsToCartForm, useFormAddProductsToCart } from '../AddProductsToCart' import type { ProductListItemProps } from '../ProductListItem/ProductListItem' import type { ProductListItemsFragment } from './ProductListItems.gql' import type { ProductListItemRenderer } from './renderer' type ComponentState = { size?: 'normal' | 'small' } export type ColumnConfig = { /** * The total width of the grid, this is used to provde the correct values to the image sizes prop * so the right image size is loaded. * * @default 'calc(100vw - ${theme.page.horizontal} * 2)' */ maxWidth?: string /** * Gap between the columns/rows * * @default theme.spacings.md */ gap?: string /** Number of columns */ count: number } export type ColumnsConfig = Partial> export type ProductItemsGridProps = ProductListItemsFragment & { renderers: ProductListItemRenderer loadingEager?: number title: string sx?: BoxProps['sx'] columns?: ((theme: Theme) => ColumnsConfig) | ColumnsConfig containerRef?: React.Ref children?: React.ReactNode maxWidth?: string } & Pick & ComponentState const slots = ['root'] as const const name = 'ProductListItemsBase' const { withState } = extendableComponent(name, slots) export function ProductListItemsBase(props: ProductItemsGridProps) { const { items, containerRef, sx = [], renderers, loadingEager = 0, size = 'normal', titleComponent, onClick, columns, children, maxWidth: maxWidthProp, } = props const theme = useTheme() const maxWidth = maxWidthProp ?? `calc(100vw - ${theme.page.horizontal} * 2)` const gap = theme.spacings.md let columnConfig = typeof columns === 'function' ? columns(theme) : columns if (!columnConfig && size === 'small') { columnConfig = { xs: { count: 2 }, md: { count: 3 }, lg: { count: 4, maxWidth: `${theme.breakpoints.values.xl}px` }, } } if (!columnConfig) { columnConfig = { xs: { count: 2 }, md: { count: 3 }, lg: { count: 4 } } } const classes = withState({ size }) const context = useFormAddProductsToCart(true) const MaybeAddProductsToCartForm = context ? React.Fragment : AddProductsToCartForm return ( ({ [theme.breakpoints.up(key as Breakpoint)]: { gap: column.gap ?? gap, // maxWidth: column.maxWidth ?? maxWidth, gridTemplateColumns: `repeat(${column.count}, 1fr)`, }, })), { display: 'grid' }, sx, )} > {items?.map((item, idx) => item ? ( idx ? true : undefined} height={responsiveVal(250, 500)} > { const totalW = column.maxWidth ?? maxWidth const columnGap = column.gap ?? gap return [ theme.breakpoints.values[key as Breakpoint], `calc((${totalW} - (${columnGap} * ${column.count - 1})) / ${column.count})`, ] }), )} {...item} loading={loadingEager > idx ? 'eager' : 'lazy'} titleComponent={titleComponent} onClick={onClick} /> ) : null, )} {children} ) }