mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-06-24 13:59:38 -05:00
60 lines
1.2 KiB
TypeScript
60 lines
1.2 KiB
TypeScript
// adapted from https://github.com/cedricdelpoux/react-responsive-masonry
|
|
|
|
import React from "react";
|
|
import { useWindowSize } from "~/hooks/useWindowSize";
|
|
import Masonry from "./Masonry";
|
|
|
|
const COLUMN_COUNTS = {
|
|
L: 3,
|
|
M: 2,
|
|
S: 1,
|
|
};
|
|
|
|
const BREAKPOINTS = {
|
|
L: 900,
|
|
M: 750,
|
|
S: 350,
|
|
} as const;
|
|
|
|
type Breakpoint = keyof typeof BREAKPOINTS;
|
|
|
|
const MasonryResponsive = ({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode | React.ReactNode[];
|
|
}) => {
|
|
const breakpoint = useBreakpoint();
|
|
|
|
const columnsCount = COLUMN_COUNTS[breakpoint];
|
|
|
|
return (
|
|
<div>
|
|
{React.Children.map(children, (child, index) =>
|
|
React.cloneElement(child as React.ReactElement<any>, {
|
|
key: index,
|
|
columnsCount,
|
|
}),
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export function ResponsiveMasonry({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<MasonryResponsive>
|
|
<Masonry gutter="1rem">{children}</Masonry>
|
|
</MasonryResponsive>
|
|
);
|
|
}
|
|
|
|
function useBreakpoint(): Breakpoint {
|
|
const { width } = useWindowSize();
|
|
|
|
const ascending = Object.entries(BREAKPOINTS).sort((a, b) => a[1] - b[1]);
|
|
return ascending.reduce<Breakpoint>(
|
|
(current, [name, minWidth]) =>
|
|
width >= minWidth ? (name as Breakpoint) : current,
|
|
ascending[0][0] as Breakpoint,
|
|
);
|
|
}
|