diff --git a/src/__tests__/mosaic-test.tsx b/src/__tests__/mosaic-test.tsx new file mode 100644 index 000000000..b5b6bb2f6 --- /dev/null +++ b/src/__tests__/mosaic-test.tsx @@ -0,0 +1,90 @@ +import * as React from 'react'; +import {render, screen} from '@testing-library/react'; +import ThemeContextProvider from '../theme-context-provider'; +import {makeTheme} from './test-utils'; +import {HorizontalMosaic, VerticalMosaic} from '../mosaic'; +import {Text2} from '../text'; + +const ITEMS_COUNT = [1, 2, 3, 4, 5, 6]; + +const verticalMosaicItemsGridMode = [ + // 1 item + ['horizontal'], + + // 2 items + ['square', 'square'], + + // 3 items + ['vertical', 'square', 'square'], + + // 4 items + ['vertical', 'square', 'square', 'vertical'], + + // 5 items + ['vertical', 'square', 'square', 'vertical', 'horizontal'], + + // 6 items + ['vertical', 'square', 'square', 'vertical', 'square', 'square'], +]; + +const horizontalMosaicItemsGridMode = [ + // 1 item + ['horizontal'], + + // 2 items + ['horizontal', 'horizontal'], + + // 3 items + ['horizontal', 'square', 'square'], + + // 4 items + ['square', 'square', 'square', 'square'], + + // 5 items + ['horizontal', 'square', 'square', 'horizontal', 'horizontal'], + + // 6 items + ['horizontal', 'square', 'square', 'square', 'square', 'horizontal'], +]; + +test.each(ITEMS_COUNT)( + 'VerticalMosaic - gridMode passed as a function is correct with %s items', + (itemsCount) => { + render( + + ({gridMode}) => ( + {`${index + 1}-${gridMode}`} + ))} + /> + + ); + + const expectedGridModes = verticalMosaicItemsGridMode[itemsCount - 1]; + + expectedGridModes.forEach((gridMode, index) => { + expect(screen.getByText(`${index + 1}-${gridMode}`)).toBeInTheDocument(); + }); + } +); + +test.each(ITEMS_COUNT)( + 'HorizontalMosaic - gridMode passed as a function is correct with %s items', + (itemsCount) => { + render( + + ({gridMode}) => ( + {`${index + 1}-${gridMode}`} + ))} + /> + + ); + + const expectedGridModes = horizontalMosaicItemsGridMode[itemsCount - 1]; + + expectedGridModes.forEach((gridMode, index) => { + expect(screen.getByText(`${index + 1}-${gridMode}`)).toBeInTheDocument(); + }); + } +); diff --git a/src/mosaic.tsx b/src/mosaic.tsx index 71e9f79a4..1e10c7b60 100644 --- a/src/mosaic.tsx +++ b/src/mosaic.tsx @@ -7,20 +7,32 @@ import type {DataAttributes} from './utils/types'; const GRID_GAP = {mobile: 8, desktop: 16} as const; +type MosaicItemGridMode = 'horizontal' | 'square' | 'vertical'; + +type MosaicItem = React.ReactElement | ((config: {gridMode: MosaicItemGridMode}) => React.ReactElement); + type HorizontalMosaicPageProps = { - items: ReadonlyArray; + items: ReadonlyArray; isEven: boolean; }; +const renderItem = (item: MosaicItem, gridMode: MosaicItemGridMode) => { + return typeof item === 'function' ? item({gridMode}) : item; +}; + const HorizontalMosaicPage = ({items, isEven}: HorizontalMosaicPageProps) => { return (
{items.length === 3 ? ( <> - {items[0]} - {items[1]} - {items[2]} + + {renderItem(items[0], isEven ? 'horizontal' : 'square')} + + {renderItem(items[1], 'square')} + + {renderItem(items[2], isEven ? 'square' : 'horizontal')} + ) : ( items.map((item, itemIndex) => ( @@ -29,7 +41,7 @@ const HorizontalMosaicPage = ({items, isEven}: HorizontalMosaicPageProps) => { rowSpan={items.length === 1 ? 2 : undefined} key={itemIndex} > - {item} + {renderItem(item, items.length === 4 ? 'square' : 'horizontal')} )) )} @@ -39,7 +51,7 @@ const HorizontalMosaicPage = ({items, isEven}: HorizontalMosaicPageProps) => { }; type HorizontalMosaicProps = { - items: ReadonlyArray; + items: ReadonlyArray; withBullets?: boolean; free?: boolean; dataAttributes?: DataAttributes; @@ -54,7 +66,7 @@ export const HorizontalMosaic = ({ const itemsCount = items.length; const pagesCount = itemsCount < 5 ? Math.min(itemsCount, 1) : Math.floor((itemsCount + 1) / 3); - const pages = Array.from({length: pagesCount}, () => [] as Array); + const pages = Array.from({length: pagesCount}, () => [] as Array); items.forEach((item, index) => { const itemPageIndex = Math.min(pagesCount - 1, Math.floor(index / 3)); @@ -76,7 +88,7 @@ export const HorizontalMosaic = ({ }; type VerticalMosaicPageProps = { - items: ReadonlyArray; + items: ReadonlyArray; }; const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => { @@ -88,7 +100,7 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => { {items.map((item, itemIndex) => ( - {item} + {renderItem(item, items.length === 2 ? 'square' : 'horizontal')} ))} @@ -101,7 +113,7 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => { {items.map((item, itemIndex) => ( - {item} + {renderItem(item, itemIndex === 0 ? 'vertical' : 'square')} ))} @@ -113,10 +125,10 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => { return (
- {items[0]} - {items[1]} - {items[3]} - {items[2]} + {renderItem(items[0], 'vertical')} + {renderItem(items[1], 'square')} + {renderItem(items[3], 'vertical')} + {renderItem(items[2], 'square')}
); @@ -124,7 +136,7 @@ const VerticalMosaicPage = ({items}: VerticalMosaicPageProps) => { }; type VerticalMosaicProps = { - items: ReadonlyArray; + items: ReadonlyArray; dataAttributes?: DataAttributes; }; @@ -132,7 +144,7 @@ export const VerticalMosaic = ({items, dataAttributes}: VerticalMosaicProps): JS const itemsCount = items.length; const pagesCount = Math.ceil(itemsCount / 4); - const pages = Array.from({length: pagesCount}, () => [] as Array>); + const pages = Array.from({length: pagesCount}, () => [] as Array); items.forEach((item, index) => { const itemPageIndex = Math.floor(index / 4);