67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
import Item from "./Item"
|
|
|
|
import styles from "./grid.module.css"
|
|
|
|
import type { GridProps, Order, RowSpan } from "./grid"
|
|
|
|
export default function Grid({ children, items, tag = "section" }: GridProps) {
|
|
const Elm = tag
|
|
|
|
const allRows: number[] = items.columns.map((col) => col.rows.length)
|
|
const onlySingleRows = allRows.every((row) => row === 1)
|
|
const oneColumnWithTwoRows = allRows.includes(2)
|
|
const oneColumnWithThreeRows = allRows.includes(3)
|
|
/**
|
|
* When we have one column with 2 rows and another with 3,
|
|
* we have to reach the closest denominator which is 6 to be
|
|
* able to have the column with 2 rows span half the grid each.
|
|
*/
|
|
const doubleTheRows = oneColumnWithTwoRows && oneColumnWithThreeRows
|
|
return (
|
|
<Elm className={styles.grid}>
|
|
{items.columns.map((column, columnIndex) => {
|
|
const rows = column.rows.map((row) => row.rowConnection.edges).flat()
|
|
let rowSpan: RowSpan = 1
|
|
if (!onlySingleRows) {
|
|
if (doubleTheRows) {
|
|
switch (rows.length) {
|
|
case 1:
|
|
rowSpan = 6
|
|
break
|
|
case 2:
|
|
rowSpan = 3
|
|
break
|
|
case 3:
|
|
rowSpan = 2
|
|
break
|
|
}
|
|
} else if (oneColumnWithTwoRows) {
|
|
if (rows.length === 1) {
|
|
rowSpan = 2
|
|
}
|
|
} else if (oneColumnWithThreeRows) {
|
|
if (rows.length === 1) {
|
|
rowSpan = 3
|
|
}
|
|
}
|
|
}
|
|
return rows.map(({ node: row }, rowIndex) => {
|
|
const order = (columnIndex +
|
|
1 +
|
|
rowIndex * items.columns.length) as Order
|
|
return (
|
|
<Item
|
|
key={order}
|
|
columns={column.span}
|
|
order={order}
|
|
rows={rowSpan}
|
|
>
|
|
{children(row)}
|
|
</Item>
|
|
)
|
|
})
|
|
})}
|
|
</Elm>
|
|
)
|
|
}
|