export ready

main
psoubrie 2023-10-31 19:46:35 +00:00
parent 3ec0a3c486
commit 924faf2afd
5 changed files with 79 additions and 135 deletions

View File

@ -7,7 +7,9 @@
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
"bradlc.vscode-tailwindcss" "bradlc.vscode-tailwindcss",
"GitHub.copilot",
"esbenp.prettier-vscode"
] ]
} }
} }

View File

@ -13,9 +13,9 @@ const config = {
* *
* @see https://github.com/vercel/next.js/issues/41980 * @see https://github.com/vercel/next.js/issues/41980
*/ */
i18n: { output: 'export',
locales: ["en"], images: {
defaultLocale: "en", unoptimized: true,
}, },
}; };

View File

@ -1,12 +1,12 @@
import { ChevronLeftIcon, ChevronRightIcon } from '@radix-ui/react-icons'; import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons";
import React, { useRef, useCallback } from 'react'; import React, { useRef, useCallback } from "react";
import HTMLFlipBook from 'react-pageflip'; import HTMLFlipBook from "react-pageflip";
interface FlipbookProps { interface FlipbookProps {
children: React.ReactNode[]; children: React.ReactNode[];
width: number; width: number;
height: number; height: number;
className?: React.ComponentProps<'div'>['className']; className?: React.ComponentProps<"div">["className"];
} }
interface PageFlip { interface PageFlip {
@ -21,53 +21,64 @@ export default function Flipbook(props: FlipbookProps) {
const flipbook = useRef<{ pageFlip(): PageFlip } | null>(null); const flipbook = useRef<{ pageFlip(): PageFlip } | null>(null);
// Function to flip pages // Function to flip pages
const flipPage = useCallback((direction: 'next' | 'prev') => { const flipPage = useCallback(
const flipbookCurrent = flipbook.current; (direction: "next" | "prev") => {
if (flipbookCurrent) { const flipbookCurrent = flipbook.current;
const pageFlipObj = flipbookCurrent.pageFlip(); if (flipbookCurrent) {
const currentPageIndex = pageFlipObj.getCurrentPageIndex(); const pageFlipObj = flipbookCurrent.pageFlip();
const pageCount = pageFlipObj.getPageCount(); const currentPageIndex = pageFlipObj.getCurrentPageIndex();
const pageCount = pageFlipObj.getPageCount();
if (direction === 'next') { if (direction === "next") {
if (currentPageIndex + 2 === pageCount) { if (currentPageIndex + 2 === pageCount) {
pageFlipObj.flip(0); pageFlipObj.flip(0);
} else { } else {
pageFlipObj.flipNext(); pageFlipObj.flipNext();
} }
} else if (direction === 'prev') { } else if (direction === "prev") {
if (currentPageIndex === 0) { if (currentPageIndex === 0) {
pageFlipObj.flip(pageCount - 1); pageFlipObj.flip(pageCount - 1);
} else { } else {
pageFlipObj.flipPrev(); // Add this method to handle the previous page flip pageFlipObj.flipPrev(); // Add this method to handle the previous page flip
}
} }
} }
} },
}, [flipbook]); [flipbook],
);
// Handler for the next button // Handler for the next button
const nextButtonClick = useCallback(() => { const nextButtonClick = useCallback(() => {
flipPage('next'); flipPage("next");
}, [flipPage]); }, [flipPage]);
// Handler for the previous button // Handler for the previous button
const prevButtonClick = useCallback(() => { const prevButtonClick = useCallback(() => {
flipPage('prev'); flipPage("prev");
}, [flipPage]); }, [flipPage]);
return ( return (
<div className={`flex justify-center items-center ${props.className}`}> <div className={`flex items-center justify-center ${props.className}`}>
<button onClick={prevButtonClick}> <button onClick={prevButtonClick}>
<ChevronLeftIcon height={50} width={50}/> <ChevronLeftIcon
height={50}
width={50}
className="max-h-[7vw] max-w-[7vw]"
/>
</button> </button>
<HTMLFlipBook <HTMLFlipBook
usePortrait={false} usePortrait={false}
className="text-black" className="text-black"
width={props.width} height={props.height} width={props.width}
height={props.height}
size="fixed" size="fixed"
style={{}} style={{}}
minHeight={100} maxHeight={500} minHeight={100}
minWidth={100} maxWidth={500} maxHeight={500}
startPage={0} startZIndex={0} minWidth={100}
maxWidth={500}
startPage={0}
startZIndex={0}
drawShadow drawShadow
flippingTime={1000} flippingTime={1000}
autoSize autoSize
@ -84,7 +95,11 @@ export default function Flipbook(props: FlipbookProps) {
{props.children} {props.children}
</HTMLFlipBook> </HTMLFlipBook>
<button onClick={nextButtonClick}> <button onClick={nextButtonClick}>
<ChevronRightIcon height={50} width={50}/> <ChevronRightIcon
height={50}
width={50}
className="max-h-[7vw] max-w-[7vw]"
/>
</button> </button>
</div> </div>
); );

View File

@ -1,83 +0,0 @@
import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons";
import { useKeenSlider } from "keen-slider/react";
import { useState, type MouseEvent } from "react";
interface SliderProps {
className?: React.ComponentProps<'div'>['className'];
children?: React.ReactNode;
}
export default function Slider({ className, children }: SliderProps) {
const [currentSlide, setCurrentSlide] = useState(0);
const [loaded, setLoaded] = useState(false);
const [sliderRef, instanceRef] = useKeenSlider<HTMLDivElement>({
initial: 0,
slideChanged(slider) {
setCurrentSlide(slider.track.details.rel);
},
created() {
setLoaded(true);
},
});
const goPrev = (e: MouseEvent<unknown>) => {
e.stopPropagation();
if (currentSlide !== 0) {
instanceRef.current?.prev();
}
};
const goNext = (e: MouseEvent<unknown>) => {
e.stopPropagation();
if (instanceRef.current && currentSlide !== instanceRef.current.track.details.slides.length - 1) {
instanceRef.current.next();
}
};
return (
<div className={`${className} relative`}>
<div>
<div ref={sliderRef} className="flex overflow-hidden relative w-full">
{children}
</div>
{loaded && instanceRef.current && (
<>
<Arrow left onClick={goPrev} disabled={currentSlide === 0} />
<Arrow onClick={goNext} disabled={instanceRef.current ? currentSlide === instanceRef.current.track.details.slides.length - 1 : true} />
</>
)}
</div>
{loaded && instanceRef.current && (
<div className="flex justify-center py-2">
{Array.from({ length: instanceRef.current.track.details.slides.length }, (_, idx) => (
<button
key={idx}
onClick={() => instanceRef.current?.moveToIdx(idx)}
className={`w-2.5 h-2.5 bg-white rounded-full m-1 cursor-pointer ${currentSlide === idx ? "opacity-30" : ""}`}
></button>
))}
</div>
)}
</div>
);
}
interface ArrowProps {
disabled: boolean;
left?: boolean;
onClick: (e: MouseEvent<unknown>) => void;
}
function Arrow({ disabled, left, onClick }: ArrowProps) {
const Icon = left ? ChevronLeftIcon : ChevronRightIcon;
const position = left ? '-left-10' : 'left-auto -right-10';
return (
<Icon
onClick={onClick}
height={50}
width={50}
className={`absolute ${position} top-1/2 cursor-pointer -translate-y-1/2 ${disabled ? "opacity-30" : ""}`}
/>
);
}

View File

@ -1,8 +1,18 @@
import React, { useRef, useState, useEffect } from 'react';
import Head from "next/head"; import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
import Flipbook from "~/components/Flipbook"; import Flipbook from "~/components/Flipbook";
export default function Home() { export default function Home() {
const mainRef = useRef<HTMLDivElement>(null);
const [mainWidth, setMainWidth] = useState(350); // default value
useEffect(() => {
if (mainRef.current) {
setMainWidth(mainRef.current.offsetWidth/2.3);
}
}, []);
return ( return (
<> <>
<Head> <Head>
@ -10,22 +20,22 @@ export default function Home() {
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
</Head> </Head>
<main className=""> <main className="" ref={mainRef}>
<Flipbook className="" width={350} height={460}> <Flipbook className="" width={mainWidth} height={mainWidth*460/350}>
<div className="bg-gray-300"> <div className="bg-gray-300">
<div className="flex justify-center items-center h-full"> <div className="flex justify-center items-center h-full">
<a href="/download/GabrielDalle_Magazine.pdf" target="_blank" className="border-my-red border-[3px] p-4 rounded-full flex gap-2 cursor-pointer hover:border-black hover:bg-white font-mono font-bold text-sm tracking-wide"> <a href="/download/GabrielDalle_Magazine.pdf" target="_blank" className="border-my-red border-[3px] p-4 rounded-full flex gap-2 cursor-pointer hover:border-black hover:bg-white font-mono font-bold text-sm tracking-wide">
PDF DOWNLOAD PDF DOWNLOAD
</a> </a>
</div>
</div> </div>
</div> {Array.from(Array(24), (_, i) => (
{Array.from(Array(24), (_, i) => ( <div className="bg-white" key={i}>
<div className="bg-white" key={i}> <Image key={i} alt="pdf page" height={468} width={mainWidth} src={`/projects/fizik/pdf/page${i + 1}.png`} />
<Image key={i} alt="pdf page" height={468} width={350} src={`/projects/fizik/pdf/page${i + 1}.png`} /> </div>
</div> ))}
))} <div className="bg-gray-300" />
<div className="bg-gray-300" /> </Flipbook>
</Flipbook>
</main> </main>
</> </>
); );