added project gallery behavior
This commit is contained in:
@@ -2,13 +2,94 @@
|
||||
|
||||
import { PROJECTS } from "@/data/content";
|
||||
import { useStaggerReveal } from "@/hooks/useAnimations";
|
||||
import ProjectCard from "./ProjectCard";
|
||||
import React, { useState, useCallback } from 'react';
|
||||
|
||||
import ProjectCard from "@/components/ProjectCard";
|
||||
|
||||
import { Layout, Responsive, useContainerWidth, horizontalCompactor, verticalCompactor, DefaultBreakpoints } from "react-grid-layout";
|
||||
|
||||
import "react-grid-layout/css/styles.css";
|
||||
import "react-resizable/css/styles.css";
|
||||
|
||||
export default function Projects() {
|
||||
const visible = useStaggerReveal(PROJECTS.length, 100);
|
||||
|
||||
const rowHeight = 250;
|
||||
const defaultExpandedHeightUnits = 2;
|
||||
const visible = useStaggerReveal(PROJECTS.length, 100);
|
||||
const [selectedProject, setSelectedProject] = useState<number>(1);
|
||||
|
||||
const { width, containerRef, mounted } = useContainerWidth();
|
||||
|
||||
const [topCellHeight, setTopCellHeight] = useState(defaultExpandedHeightUnits);
|
||||
const [layouts, setLayouts] = useState<Record<DefaultBreakpoints, Layout>>(updateLayout(1));
|
||||
|
||||
function setExpandedHeight(height: number) {
|
||||
const gridUnits = height === 0 ? defaultExpandedHeightUnits : Math.ceil(height / rowHeight);
|
||||
setTopCellHeight(gridUnits);
|
||||
setLayouts(updateLayout(selectedProject, gridUnits)); // pass both
|
||||
}
|
||||
|
||||
function setSelectedHandler(projectId: number) {
|
||||
const id = Number(projectId);
|
||||
setSelectedProject(id);
|
||||
setLayouts(updateLayout(id, topCellHeight)); // pass both
|
||||
}
|
||||
|
||||
function updateLayout(activeId: number, cellHeight?: number) : Record<DefaultBreakpoints, Layout> {
|
||||
const currentSelected = activeId ?? selectedProject;
|
||||
const currentCellHeight = cellHeight ?? topCellHeight;
|
||||
let isSelected = (projectId: number) => projectId === currentSelected;
|
||||
return {
|
||||
"sm": PROJECTS.map((project, i) => {
|
||||
return {
|
||||
i: project.id.toString(),
|
||||
x: isSelected(project.id) ? 0 : (i % 2) + 1,
|
||||
y: isSelected(project.id) ? 0 : Math.floor(i / 2) + (!isSelected(project.id) ? 1 : 0),
|
||||
w: isSelected(project.id) ? 2 : 1,
|
||||
h: project.images && project.images.length > 0 ? currentCellHeight : 1
|
||||
};
|
||||
}),
|
||||
"xs": PROJECTS.map((project, i) => {
|
||||
return {
|
||||
i: project.id.toString(),
|
||||
x: 0,
|
||||
y: i,
|
||||
w: 2,
|
||||
h: project.images && project.images.length > 0 ? currentCellHeight : 1
|
||||
};
|
||||
}),
|
||||
"xxs": PROJECTS.map((project, i) => {
|
||||
return {
|
||||
i: project.id.toString(),
|
||||
x: 0,
|
||||
y: i,
|
||||
w: 2,
|
||||
h: project.images && project.images.length > 0 ? currentCellHeight : 1
|
||||
};
|
||||
}),
|
||||
"md": PROJECTS.map((project, i) => {
|
||||
return {
|
||||
i: project.id.toString(),
|
||||
x: isSelected(project.id) ? 0 : (i % 2) + 1,
|
||||
y: isSelected(project.id) ? 0 : Math.floor(i / 2) + (!isSelected(project.id) ? 1 : 0),
|
||||
w: isSelected(project.id) ? 2 : 1,
|
||||
h: project.images && project.images.length > 0 ? currentCellHeight : 1
|
||||
};
|
||||
}),
|
||||
"lg": PROJECTS.map((project, i) => {
|
||||
return {
|
||||
i: project.id.toString(),
|
||||
x: isSelected(project.id) ? 0 : (i % 2) + 1,
|
||||
y: isSelected(project.id) ? 0 : Math.floor(i / 2) + (!isSelected(project.id) ? 1 : 0),
|
||||
w: isSelected(project.id) ? 2 : 1,
|
||||
h: project.images && project.images.length > 0 ? currentCellHeight : 1
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: "48px 0" }}>
|
||||
<div style={{ padding: "48px 0"}}>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 8,
|
||||
@@ -33,21 +114,33 @@ export default function Projects() {
|
||||
>
|
||||
{"Things I've built"}
|
||||
</h2>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))",
|
||||
gap: 16,
|
||||
}}
|
||||
>
|
||||
|
||||
<div ref={containerRef}>
|
||||
{mounted && (<Responsive
|
||||
layouts={layouts}
|
||||
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
|
||||
cols={{ lg: 2, md: 2, sm: 2, xs: 2, xxs: 2 }}
|
||||
width={width}
|
||||
compactor={horizontalCompactor}
|
||||
rowHeight={rowHeight}
|
||||
dragConfig={{enabled:false}}
|
||||
>
|
||||
{PROJECTS.map((project, i) => (
|
||||
<ProjectCard
|
||||
key={project.id}
|
||||
<div key={project.id} style={{pointerEvents: "none"}}>
|
||||
<ProjectCard
|
||||
project={project}
|
||||
visible={visible.has(i)}
|
||||
selected={selectedProject === project.id}
|
||||
setSelected={setSelectedHandler}
|
||||
setExpandedHeight={setExpandedHeight}
|
||||
/>
|
||||
</div>
|
||||
|
||||
))}
|
||||
</Responsive>)}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user