diff --git a/package-lock.json b/package-lock.json index 1b83a5a..ee74bae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "nanostores": "^0.11.3", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-pageflip": "^2.0.3", "tailwind-merge": "^2.5.5", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", @@ -5176,6 +5177,12 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "node_modules/page-flip": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/page-flip/-/page-flip-2.0.7.tgz", + "integrity": "sha512-96lQFUUz7r/LZzEUZJ3yBIMEKU9+m8HMFDzTvTdD6P7Ag/wXINjp9n0W7b4wanwnDbQETo4uNUoL3zMqpFxwGA==", + "license": "MIT" + }, "node_modules/parse-latin": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", @@ -5669,6 +5676,15 @@ "react": "^19.0.0" } }, + "node_modules/react-pageflip": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/react-pageflip/-/react-pageflip-2.0.3.tgz", + "integrity": "sha512-k81mHhRvUM52y8jyzTCh5t4O0lepkLhp+XGSUzq2C3uD+iW99Cv0jfRlqFCjZbD5N3jKkIFr7/3giucoXKDP3Q==", + "license": "MIT", + "dependencies": { + "page-flip": "latest" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -10291,6 +10307,11 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "page-flip": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/page-flip/-/page-flip-2.0.7.tgz", + "integrity": "sha512-96lQFUUz7r/LZzEUZJ3yBIMEKU9+m8HMFDzTvTdD6P7Ag/wXINjp9n0W7b4wanwnDbQETo4uNUoL3zMqpFxwGA==" + }, "parse-latin": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", @@ -10542,6 +10563,14 @@ "scheduler": "^0.25.0" } }, + "react-pageflip": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/react-pageflip/-/react-pageflip-2.0.3.tgz", + "integrity": "sha512-k81mHhRvUM52y8jyzTCh5t4O0lepkLhp+XGSUzq2C3uD+iW99Cv0jfRlqFCjZbD5N3jKkIFr7/3giucoXKDP3Q==", + "requires": { + "page-flip": "latest" + } + }, "react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", diff --git a/package.json b/package.json index e9eb8bc..6728888 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "nanostores": "^0.11.3", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-pageflip": "^2.0.3", "tailwind-merge": "^2.5.5", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", @@ -40,4 +41,4 @@ "prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-tailwindcss": "^0.6.9" } -} \ No newline at end of file +} diff --git a/public/assets/this-website.png b/public/assets/this-website.png deleted file mode 100644 index 7146b2f..0000000 Binary files a/public/assets/this-website.png and /dev/null differ diff --git a/public/assets/zines-thumbnail.png b/public/assets/zines-thumbnail.png new file mode 100644 index 0000000..652b042 Binary files /dev/null and b/public/assets/zines-thumbnail.png differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/cover.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/cover.jpg new file mode 100644 index 0000000..c4b2f79 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/cover.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-1.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-1.jpg new file mode 100644 index 0000000..c4b2f79 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-1.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-2.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-2.jpg new file mode 100644 index 0000000..d070fc9 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-2.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-3.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-3.jpg new file mode 100644 index 0000000..4657988 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-3.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-4.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-4.jpg new file mode 100644 index 0000000..5d57891 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-4.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-5.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-5.jpg new file mode 100644 index 0000000..c35133b Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-5.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-6.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-6.jpg new file mode 100644 index 0000000..c50957a Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-6.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-7.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-7.jpg new file mode 100644 index 0000000..570b0ec Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-7.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/page-8.jpg b/public/assets/zines/de-monopoly-discotech-101-japanese/page-8.jpg new file mode 100644 index 0000000..5275a73 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/page-8.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101-japanese/printable.pdf b/public/assets/zines/de-monopoly-discotech-101-japanese/printable.pdf new file mode 100644 index 0000000..0bd1017 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101-japanese/printable.pdf differ diff --git a/public/assets/zines/de-monopoly-discotech-101/cover.jpg b/public/assets/zines/de-monopoly-discotech-101/cover.jpg new file mode 100644 index 0000000..9ca6fea Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/cover.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-1.jpg b/public/assets/zines/de-monopoly-discotech-101/page-1.jpg new file mode 100644 index 0000000..9ca6fea Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-1.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-2.jpg b/public/assets/zines/de-monopoly-discotech-101/page-2.jpg new file mode 100644 index 0000000..35fa474 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-2.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-3.jpg b/public/assets/zines/de-monopoly-discotech-101/page-3.jpg new file mode 100644 index 0000000..bf63c79 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-3.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-4.jpg b/public/assets/zines/de-monopoly-discotech-101/page-4.jpg new file mode 100644 index 0000000..a49806d Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-4.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-5.jpg b/public/assets/zines/de-monopoly-discotech-101/page-5.jpg new file mode 100644 index 0000000..38f60ac Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-5.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-6.jpg b/public/assets/zines/de-monopoly-discotech-101/page-6.jpg new file mode 100644 index 0000000..9f57e5e Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-6.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-7.jpg b/public/assets/zines/de-monopoly-discotech-101/page-7.jpg new file mode 100644 index 0000000..b763dae Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-7.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/page-8.jpg b/public/assets/zines/de-monopoly-discotech-101/page-8.jpg new file mode 100644 index 0000000..3dcf8ba Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/page-8.jpg differ diff --git a/public/assets/zines/de-monopoly-discotech-101/printable.pdf b/public/assets/zines/de-monopoly-discotech-101/printable.pdf new file mode 100644 index 0000000..9d66ff6 Binary files /dev/null and b/public/assets/zines/de-monopoly-discotech-101/printable.pdf differ diff --git a/public/assets/zines/internet-for-the-people/cover.jpg b/public/assets/zines/internet-for-the-people/cover.jpg new file mode 100644 index 0000000..652b042 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/cover.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-1.jpg b/public/assets/zines/internet-for-the-people/page-1.jpg new file mode 100644 index 0000000..652b042 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-1.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-2.jpg b/public/assets/zines/internet-for-the-people/page-2.jpg new file mode 100644 index 0000000..f5df2c1 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-2.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-3.jpg b/public/assets/zines/internet-for-the-people/page-3.jpg new file mode 100644 index 0000000..06adba6 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-3.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-4.jpg b/public/assets/zines/internet-for-the-people/page-4.jpg new file mode 100644 index 0000000..8e385a6 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-4.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-5.jpg b/public/assets/zines/internet-for-the-people/page-5.jpg new file mode 100644 index 0000000..58799f4 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-5.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-6.jpg b/public/assets/zines/internet-for-the-people/page-6.jpg new file mode 100644 index 0000000..407b838 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-6.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-7.jpg b/public/assets/zines/internet-for-the-people/page-7.jpg new file mode 100644 index 0000000..9c37dd4 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-7.jpg differ diff --git a/public/assets/zines/internet-for-the-people/page-8.jpg b/public/assets/zines/internet-for-the-people/page-8.jpg new file mode 100644 index 0000000..de95aaa Binary files /dev/null and b/public/assets/zines/internet-for-the-people/page-8.jpg differ diff --git a/public/assets/zines/internet-for-the-people/printable.pdf b/public/assets/zines/internet-for-the-people/printable.pdf new file mode 100644 index 0000000..95c41d9 Binary files /dev/null and b/public/assets/zines/internet-for-the-people/printable.pdf differ diff --git a/src/components/zines/FlipbookViewer.tsx b/src/components/zines/FlipbookViewer.tsx new file mode 100644 index 0000000..9114052 --- /dev/null +++ b/src/components/zines/FlipbookViewer.tsx @@ -0,0 +1,138 @@ +import React, { useRef, useState, useCallback, forwardRef, useEffect } from "react"; +import HTMLFlipBook from "react-pageflip"; +import { ChevronLeft, ChevronRight } from "lucide-react"; +import { Button } from "../ui/button"; + +interface PageProps { + src: string; + pageNumber: number; +} + +const Page = forwardRef(({ src, pageNumber }, ref) => { + return ( +
+ {`Page +
+ ); +}); + +Page.displayName = "Page"; + +interface FlipbookViewerProps { + pages: string[]; + title: string; +} + +export function FlipbookViewer({ pages, title }: FlipbookViewerProps) { + const flipBookRef = useRef(null); + const [currentPage, setCurrentPage] = useState(0); + const totalPages = pages.length; + + const onFlip = useCallback((e: any) => { + setCurrentPage(e.data); + }, []); + + const goToPrevPage = () => { + flipBookRef.current?.pageFlip()?.flipPrev(); + }; + + const goToNextPage = () => { + flipBookRef.current?.pageFlip()?.flipNext(); + }; + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === "ArrowLeft") { + goToPrevPage(); + } else if (e.key === "ArrowRight") { + goToNextPage(); + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, []); + + if (pages.length === 0) { + return ( +
+ No pages available +
+ ); + } + + return ( +
+

{title}

+ +
+ {/* @ts-ignore - react-pageflip types are incomplete */} + + {pages.map((page, index) => ( + + ))} + +
+ +
+ + + + Page {currentPage + 1} of {totalPages} + + + +
+ +

+ Click the page corners or use arrow buttons to turn pages +

+
+ ); +} diff --git a/src/components/zines/ZineCard.tsx b/src/components/zines/ZineCard.tsx new file mode 100644 index 0000000..18aee65 --- /dev/null +++ b/src/components/zines/ZineCard.tsx @@ -0,0 +1,52 @@ +import { Download } from "lucide-react"; +import type { Zine } from "../../data/zines"; +import { Button } from "../ui/button"; + +interface ZineCardProps { + zine: Zine; + onClick: () => void; +} + +export function ZineCard({ zine, onClick }: ZineCardProps) { + const handleDownload = (e: React.MouseEvent) => { + e.stopPropagation(); + }; + + return ( +
+ + +
+ + +
+
+ ); +} diff --git a/src/components/zines/ZineGrid.tsx b/src/components/zines/ZineGrid.tsx new file mode 100644 index 0000000..9cfcf86 --- /dev/null +++ b/src/components/zines/ZineGrid.tsx @@ -0,0 +1,54 @@ +import { useState } from "react"; +import { zines, type Zine } from "../../data/zines"; +import { ZineCard } from "./ZineCard"; +import { FlipbookViewer } from "./FlipbookViewer"; +import { + Dialog, + DialogContent, + DialogTitle, + DialogDescription, +} from "../ui/dialog"; +import * as VisuallyHidden from "@radix-ui/react-visually-hidden"; + +export function ZineGrid() { + const [selectedZine, setSelectedZine] = useState(null); + + const handleOpenZine = (zine: Zine) => { + setSelectedZine(zine); + }; + + const handleCloseZine = () => { + setSelectedZine(null); + }; + + return ( + <> +
+ {zines.map((zine) => ( + handleOpenZine(zine)} + /> + ))} +
+ + + + + {selectedZine?.title} + + Interactive flipbook viewer for {selectedZine?.title} + + + {selectedZine && ( + + )} + + + + ); +} diff --git a/src/data/zines.ts b/src/data/zines.ts new file mode 100644 index 0000000..ac16369 --- /dev/null +++ b/src/data/zines.ts @@ -0,0 +1,62 @@ +export interface Zine { + id: string; + title: string; + description: string; + coverImage: string; + pages: string[]; + printablePdf: string; +} + +export const zines: Zine[] = [ + { + id: "internet-for-the-people", + title: "Internet For the People", + description: "", + coverImage: "/assets/zines/internet-for-the-people/cover.jpg", + pages: [ + "/assets/zines/internet-for-the-people/page-1.jpg", + "/assets/zines/internet-for-the-people/page-2.jpg", + "/assets/zines/internet-for-the-people/page-3.jpg", + "/assets/zines/internet-for-the-people/page-4.jpg", + "/assets/zines/internet-for-the-people/page-5.jpg", + "/assets/zines/internet-for-the-people/page-6.jpg", + "/assets/zines/internet-for-the-people/page-7.jpg", + "/assets/zines/internet-for-the-people/page-8.jpg", + ], + printablePdf: "/assets/zines/internet-for-the-people/printable.pdf", + }, + { + id: "de-monopoly-discotech-101", + title: "De-monopoly DiscoTech 101", + description: "", + coverImage: "/assets/zines/de-monopoly-discotech-101/cover.jpg", + pages: [ + "/assets/zines/de-monopoly-discotech-101/page-1.jpg", + "/assets/zines/de-monopoly-discotech-101/page-2.jpg", + "/assets/zines/de-monopoly-discotech-101/page-3.jpg", + "/assets/zines/de-monopoly-discotech-101/page-4.jpg", + "/assets/zines/de-monopoly-discotech-101/page-5.jpg", + "/assets/zines/de-monopoly-discotech-101/page-6.jpg", + "/assets/zines/de-monopoly-discotech-101/page-7.jpg", + "/assets/zines/de-monopoly-discotech-101/page-8.jpg", + ], + printablePdf: "/assets/zines/de-monopoly-discotech-101/printable.pdf", + }, + { + id: "de-monopoly-discotech-101-japanese", + title: "De-monopoly DiscoTech 101 (Japanese)", + description: "", + coverImage: "/assets/zines/de-monopoly-discotech-101-japanese/cover.jpg", + pages: [ + "/assets/zines/de-monopoly-discotech-101-japanese/page-1.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-2.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-3.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-4.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-5.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-6.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-7.jpg", + "/assets/zines/de-monopoly-discotech-101-japanese/page-8.jpg", + ], + printablePdf: "/assets/zines/de-monopoly-discotech-101-japanese/printable.pdf", + }, +]; diff --git a/src/pages/OurProjects.astro b/src/pages/OurProjects.astro index c982663..c7e7f1e 100644 --- a/src/pages/OurProjects.astro +++ b/src/pages/OurProjects.astro @@ -66,6 +66,7 @@ import "../styles/globals.css";
photo collage of cats
+======= + src="/assets/zines-thumbnail.png" + alt="zines" + width="250" + class="border object-cover w-[250px] h-[250px]" + /> + Zines + +>>>>>>> 01fd965 (add zines to our projects) diff --git a/src/pages/OurProjectsPages/Zines.astro b/src/pages/OurProjectsPages/Zines.astro new file mode 100644 index 0000000..74a4f81 --- /dev/null +++ b/src/pages/OurProjectsPages/Zines.astro @@ -0,0 +1,45 @@ +--- +import Navbar from "../../components/Navbar"; +import Footer from "../../components/Footer"; +import Layout from "../../layouts/Layout.astro"; +import { ZineGrid } from "../../components/zines/ZineGrid"; +import "../../styles/globals.css"; +--- + + +
+
+ +
+

Zines

+

+ We create and share zines about technology, power, and resistance. + Click on a zine to read it in our interactive flipbook viewer! +

+ + +
+
+
+
+
+ +