export ready
parent
3ec0a3c486
commit
924faf2afd
|
@ -7,7 +7,9 @@
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"bradlc.vscode-tailwindcss"
|
"bradlc.vscode-tailwindcss",
|
||||||
|
"GitHub.copilot",
|
||||||
|
"esbenp.prettier-vscode"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,20 +21,21 @@ 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(
|
||||||
|
(direction: "next" | "prev") => {
|
||||||
const flipbookCurrent = flipbook.current;
|
const flipbookCurrent = flipbook.current;
|
||||||
if (flipbookCurrent) {
|
if (flipbookCurrent) {
|
||||||
const pageFlipObj = flipbookCurrent.pageFlip();
|
const pageFlipObj = flipbookCurrent.pageFlip();
|
||||||
const currentPageIndex = pageFlipObj.getCurrentPageIndex();
|
const currentPageIndex = pageFlipObj.getCurrentPageIndex();
|
||||||
const pageCount = pageFlipObj.getPageCount();
|
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 {
|
||||||
|
@ -42,32 +43,42 @@ export default function Flipbook(props: FlipbookProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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" : ""}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -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,8 +20,8 @@ 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">
|
||||||
|
@ -21,7 +31,7 @@ export default function Home() {
|
||||||
</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={350} src={`/projects/fizik/pdf/page${i + 1}.png`} />
|
<Image key={i} alt="pdf page" height={468} width={mainWidth} src={`/projects/fizik/pdf/page${i + 1}.png`} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div className="bg-gray-300" />
|
<div className="bg-gray-300" />
|
||||||
|
|
Loading…
Reference in New Issue