From 036343a5cdf6592b623d094cc14aebadb6bb823d Mon Sep 17 00:00:00 2001 From: Oliver Bryan Date: Sun, 8 Feb 2026 07:23:36 +0000 Subject: [PATCH] biome: new formatting settings --- biome.json | 14 +- components.json | 42 +- package.json | 80 +-- src/App.tsx | 728 +++++++++++------------ src/components/Demo.tsx | 44 +- src/components/ProjectListItem.tsx | 124 ++-- src/components/ProjectPage.tsx | 266 ++++----- src/components/TravelListItem.tsx | 36 +- src/components/ask-ai.tsx | 146 ++--- src/components/paper-texture-overlay.tsx | 86 +-- src/components/theme-provider.tsx | 88 +-- src/components/theme-toggle.tsx | 24 +- src/components/time-since.tsx | 52 +- src/components/ui/button.tsx | 100 ++-- src/components/ui/tabs.tsx | 152 ++--- src/index.css | 250 ++++---- src/lib/constants.ts | 10 +- src/lib/utils.ts | 2 +- src/main.tsx | 16 +- src/projects/factor-e/index.tsx | 186 +++--- src/projects/flackie/index.tsx | 132 ++-- src/projects/fonts/index.tsx | 56 +- src/projects/glimpse/index.tsx | 188 +++--- src/projects/good-morning/index.tsx | 190 +++--- src/projects/index.ts | 120 ++-- src/projects/mizu/index.tsx | 246 ++++---- src/projects/prayerbud/index.tsx | 178 +++--- src/projects/shleep/index.tsx | 82 +-- src/projects/sprint/index.tsx | 264 ++++---- src/projects/watercooler/index.tsx | 116 ++-- src/projects/wiskatron/index.tsx | 106 ++-- src/travel/index.ts | 24 +- src/travel/metadata.json | 42 +- tsconfig.app.json | 58 +- tsconfig.json | 22 +- tsconfig.node.json | 44 +- vercel.json | 12 +- vite.config.ts | 18 +- 38 files changed, 2174 insertions(+), 2170 deletions(-) diff --git a/biome.json b/biome.json index baabf758..4175e25f 100644 --- a/biome.json +++ b/biome.json @@ -1,7 +1,11 @@ { - "css": { - "parser": { - "tailwindDirectives": true - } - } + "formatter": { + "indentStyle": "space", + "indentWidth": 2 + }, + "css": { + "parser": { + "tailwindDirectives": true + } + } } diff --git a/components.json b/components.json index 753e8a0d..c3085d6c 100644 --- a/components.json +++ b/components.json @@ -1,23 +1,23 @@ { - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": false, - "tsx": true, - "tailwind": { - "config": "", - "css": "src/index.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "" - }, - "iconLibrary": "lucide", - "rtl": false, - "aliases": { - "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" - }, - "registries": {} + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/index.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "rtl": false, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} } diff --git a/package.json b/package.json index 86d56f37..9f68cee6 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,42 @@ { - "name": "ob248.com", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@iconify/react": "^6.0.2", - "@nsmr/pixelart-react": "^2.0.0", - "@paper-design/shaders-react": "0.0.71", - "@tailwindcss/vite": "^4.1.18", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "radix-ui": "^1.4.3", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "react-router-dom": "^6.30.1", - "simple-icons": "^16.7.0", - "tailwind-merge": "^3.4.0", - "tailwindcss": "^4.1.18" - }, - "devDependencies": { - "@eslint/js": "^9.39.1", - "@types/node": "^25.2.1", - "@types/react": "^19.2.5", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "eslint": "^9.39.1", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^16.5.0", - "tw-animate-css": "^1.4.0", - "typescript": "~5.9.3", - "typescript-eslint": "^8.46.4", - "vite": "^7.2.4" - } + "name": "ob248.com", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@iconify/react": "^6.0.2", + "@nsmr/pixelart-react": "^2.0.0", + "@paper-design/shaders-react": "0.0.71", + "@tailwindcss/vite": "^4.1.18", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "radix-ui": "^1.4.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-router-dom": "^6.30.1", + "simple-icons": "^16.7.0", + "tailwind-merge": "^3.4.0", + "tailwindcss": "^4.1.18" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/node": "^25.2.1", + "@types/react": "^19.2.5", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "tw-animate-css": "^1.4.0", + "typescript": "~5.9.3", + "typescript-eslint": "^8.46.4", + "vite": "^7.2.4" + } } diff --git a/src/App.tsx b/src/App.tsx index ff11e88e..6839f961 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,11 +1,11 @@ import { - Downasaur, - Github, - Home as HomeIcon, - Image, - ImageDelete, - Mail, - Notes, + Downasaur, + Github, + Home as HomeIcon, + Image, + ImageDelete, + Mail, + Notes, } from "@nsmr/pixelart-react"; import { useEffect, useState } from "react"; import { Link, Route, Routes, useNavigate, useParams } from "react-router-dom"; @@ -14,374 +14,374 @@ import { ProjectListItem } from "@/components/ProjectListItem"; import { TimeSince } from "@/components/time-since"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { type ProjectEntry, projectList, projects } from "@/projects"; -import { locations, locationPhotos } from "@/travel"; +import { locationPhotos, locations } from "@/travel"; import { TravelListItem } from "./components/TravelListItem"; import { ThemeToggle } from "./components/theme-toggle"; import { Button } from "./components/ui/button"; import { cn } from "./lib/utils"; const asciiFiles = [ - "cat-sleep.txt", - "polar-bear.txt", - "penguin-surfboard.txt", - "cat-shock.txt", - "exclamation.txt", - "fat-cat-head.txt", - "grumpy-dog.txt", - "cat-peek.txt", - "cat-loaf.txt", + "cat-sleep.txt", + "polar-bear.txt", + "penguin-surfboard.txt", + "cat-shock.txt", + "exclamation.txt", + "fat-cat-head.txt", + "grumpy-dog.txt", + "cat-peek.txt", + "cat-loaf.txt", ]; const homeTabs = ["work", "travel"] as const; type HomeTab = (typeof homeTabs)[number]; function App() { - return ( - - } /> - } /> - } /> - - ); + return ( + + } /> + } /> + } /> + + ); } export default App; function Home() { - const isDevMode = import.meta.env.VITE_PUBLIC_DEV === "1"; - const isTabsEnabled = import.meta.env.VITE_TABS === "1"; - const navigate = useNavigate(); - const [asciiArt, setAsciiArt] = useState(""); - const [activeTab, setActiveTab] = useState("work"); - const [activeIndex, setActiveIndex] = useState(null); - const [activeLocation, setActiveLocation] = useState(null); - const [activePhoto, setActivePhoto] = useState(null); - const [hasPointerInteraction, setHasPointerInteraction] = useState(false); - const [asciiFile] = useState( - () => asciiFiles[Math.floor(Math.random() * asciiFiles.length)], - ); - const sortedProjects: ProjectEntry[] = [...projectList].sort( - (a, b) => - parseDate(b.metadata.date).getTime() - - parseDate(a.metadata.date).getTime(), - ); - const visibleProjects = sortedProjects.filter( - (project) => isDevMode || !project.metadata.hidden, - ); + const isDevMode = import.meta.env.VITE_PUBLIC_DEV === "1"; + const isTabsEnabled = import.meta.env.VITE_TABS === "1"; + const navigate = useNavigate(); + const [asciiArt, setAsciiArt] = useState(""); + const [activeTab, setActiveTab] = useState("work"); + const [activeIndex, setActiveIndex] = useState(null); + const [activeLocation, setActiveLocation] = useState(null); + const [activePhoto, setActivePhoto] = useState(null); + const [hasPointerInteraction, setHasPointerInteraction] = useState(false); + const [asciiFile] = useState( + () => asciiFiles[Math.floor(Math.random() * asciiFiles.length)], + ); + const sortedProjects: ProjectEntry[] = [...projectList].sort( + (a, b) => + parseDate(b.metadata.date).getTime() - + parseDate(a.metadata.date).getTime(), + ); + const visibleProjects = sortedProjects.filter( + (project) => isDevMode || !project.metadata.hidden, + ); - useEffect(() => { - let isActive = true; - fetch(`/ascii/${asciiFile}`) - .then((response) => response.text()) - .then((text) => { - if (isActive) setAsciiArt(text); - }); - return () => { - isActive = false; - }; - }, [asciiFile]); + useEffect(() => { + let isActive = true; + fetch(`/ascii/${asciiFile}`) + .then((response) => response.text()) + .then((text) => { + if (isActive) setAsciiArt(text); + }); + return () => { + isActive = false; + }; + }, [asciiFile]); - useEffect(() => { - setActiveIndex((prev) => { - if (visibleProjects.length === 0) return null; - if (prev === null) return null; - return Math.min(prev, visibleProjects.length - 1); - }); - }, [visibleProjects.length]); + useEffect(() => { + setActiveIndex((prev) => { + if (visibleProjects.length === 0) return null; + if (prev === null) return null; + return Math.min(prev, visibleProjects.length - 1); + }); + }, [visibleProjects.length]); - useEffect(() => { - if (visibleProjects.length === 0) return; + useEffect(() => { + if (visibleProjects.length === 0) return; - const handleKeyDown = (event: KeyboardEvent) => { - if (event.defaultPrevented || event.isComposing) return; - if (event.metaKey || event.ctrlKey || event.altKey) return; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.defaultPrevented || event.isComposing) return; + if (event.metaKey || event.ctrlKey || event.altKey) return; - if (isTabsEnabled && event.key === "Tab") { - event.preventDefault(); - setActiveTab((prev) => { - const currentIndex = homeTabs.indexOf(prev); - const safeIndex = currentIndex === -1 ? 0 : currentIndex; - const nextIndex = (safeIndex + 1) % homeTabs.length; - return homeTabs[nextIndex]; - }); - return; - } + if (isTabsEnabled && event.key === "Tab") { + event.preventDefault(); + setActiveTab((prev) => { + const currentIndex = homeTabs.indexOf(prev); + const safeIndex = currentIndex === -1 ? 0 : currentIndex; + const nextIndex = (safeIndex + 1) % homeTabs.length; + return homeTabs[nextIndex]; + }); + return; + } - if (isInteractiveTarget(event.target)) return; + if (isInteractiveTarget(event.target)) return; - const key = event.key.length === 1 ? event.key.toLowerCase() : event.key; - const isDesktop = window.matchMedia("(min-width: 768px)").matches; - const columns = isDesktop ? 2 : 1; + const key = event.key.length === 1 ? event.key.toLowerCase() : event.key; + const isDesktop = window.matchMedia("(min-width: 768px)").matches; + const columns = isDesktop ? 2 : 1; - let delta = 0; - if (key === "ArrowLeft" || key === "h") delta = -1; - if (key === "ArrowRight" || key === "l") delta = 1; - if (key === "ArrowUp" || key === "k") delta = -columns; - if (key === "ArrowDown" || key === "j") delta = columns; + let delta = 0; + if (key === "ArrowLeft" || key === "h") delta = -1; + if (key === "ArrowRight" || key === "l") delta = 1; + if (key === "ArrowUp" || key === "k") delta = -columns; + if (key === "ArrowDown" || key === "j") delta = columns; - if (delta !== 0) { - event.preventDefault(); - setActiveIndex((prev) => { - if (prev === null) return 0; - const next = Math.max( - 0, - Math.min(visibleProjects.length - 1, prev + delta), - ); - return next; - }); - return; - } + if (delta !== 0) { + event.preventDefault(); + setActiveIndex((prev) => { + if (prev === null) return 0; + const next = Math.max( + 0, + Math.min(visibleProjects.length - 1, prev + delta), + ); + return next; + }); + return; + } - if (key === "Enter") { - if (activeIndex === null) return; - event.preventDefault(); - const target = visibleProjects[activeIndex]; - if (!target) return; - navigate(`/projects/${target.metadata.slug}`); - } - }; + if (key === "Enter") { + if (activeIndex === null) return; + event.preventDefault(); + const target = visibleProjects[activeIndex]; + if (!target) return; + navigate(`/projects/${target.metadata.slug}`); + } + }; - window.addEventListener("keydown", handleKeyDown); - return () => { - window.removeEventListener("keydown", handleKeyDown); - }; - }, [activeIndex, navigate, visibleProjects]); + window.addEventListener("keydown", handleKeyDown); + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, [activeIndex, navigate, visibleProjects]); - useEffect(() => { - const enablePointerInteraction = () => { - setHasPointerInteraction(true); - }; + useEffect(() => { + const enablePointerInteraction = () => { + setHasPointerInteraction(true); + }; - window.addEventListener("pointermove", enablePointerInteraction, { - once: true, - }); - window.addEventListener("pointerdown", enablePointerInteraction, { - once: true, - }); + window.addEventListener("pointermove", enablePointerInteraction, { + once: true, + }); + window.addEventListener("pointerdown", enablePointerInteraction, { + once: true, + }); - return () => { - window.removeEventListener("pointermove", enablePointerInteraction); - window.removeEventListener("pointerdown", enablePointerInteraction); - }; - }, []); + return () => { + window.removeEventListener("pointermove", enablePointerInteraction); + window.removeEventListener("pointerdown", enablePointerInteraction); + }; + }, []); - return ( -
-
- {asciiArt ? ( -
-						{asciiArt}
-					
- ) : null} -

- Oliver Bryan -

- -
- Age: -
-
- {isTabsEnabled ? ( - setActiveTab(value as HomeTab)} - className="w-full max-w-5xl gap-0" - > - - - Work - - - Travel - - - -
- {visibleProjects.map((project, index) => ( - - ))} -
-
- -
- {locations.map((location, index) => ( - <> - { - setActivePhoto(null); - setActiveLocation((prev) => - prev === index ? null : index, - ); - }} - /> - {activeLocation === index && - (locationPhotos[location.id].length === 0 ? ( -
-
- -
-
- ) : ( -
-
- {locationPhotos[location.id].map((photo) => ( - - ))} -
- {activePhoto ? ( - {"active-photo"} - ) : ( -
- - No photo selected -
- )} -
- ))} - - ))} -
-
-
- ) : ( -
- {visibleProjects.map((project, index) => ( - - ))} -
- )} -
-
- -
-

- arrows or hjkl, then enter -

-
- -
-
-
- ); + return ( +
+
+ {asciiArt ? ( +
+            {asciiArt}
+          
+ ) : null} +

+ Oliver Bryan +

+ +
+ Age: +
+
+ {isTabsEnabled ? ( + setActiveTab(value as HomeTab)} + className="w-full max-w-5xl gap-0" + > + + + Work + + + Travel + + + +
+ {visibleProjects.map((project, index) => ( + + ))} +
+
+ +
+ {locations.map((location, index) => ( + <> + { + setActivePhoto(null); + setActiveLocation((prev) => + prev === index ? null : index, + ); + }} + /> + {activeLocation === index && + (locationPhotos[location.id].length === 0 ? ( +
+
+ +
+
+ ) : ( +
+
+ {locationPhotos[location.id].map((photo) => ( + + ))} +
+ {activePhoto ? ( + {"active-photo"} + ) : ( +
+ + No photo selected +
+ )} +
+ ))} + + ))} +
+
+
+ ) : ( +
+ {visibleProjects.map((project, index) => ( + + ))} +
+ )} +
+
+ +
+

+ arrows or hjkl, then enter +

+
+ +
+
+
+ ); } function isInteractiveTarget(target: EventTarget | null): boolean { - if (!(target instanceof HTMLElement)) return false; - if (target.isContentEditable) return true; - const tagName = target.tagName; - return ( - tagName === "INPUT" || - tagName === "TEXTAREA" || - tagName === "SELECT" || - tagName === "BUTTON" || - tagName === "A" - ); + if (!(target instanceof HTMLElement)) return false; + if (target.isContentEditable) return true; + const tagName = target.tagName; + return ( + tagName === "INPUT" || + tagName === "TEXTAREA" || + tagName === "SELECT" || + tagName === "BUTTON" || + tagName === "A" + ); } function ProjectRoute() { - const { slug } = useParams(); - if (!slug || !projects[slug]) return ; + const { slug } = useParams(); + if (!slug || !projects[slug]) return ; - const { Component } = projects[slug]; - return ; + const { Component } = projects[slug]; + return ; } function NotFound() { - return ( -
- ? - - 404 - Not Found + return ( +
+ ? + + 404 + Not Found - - - -
- ); + + + +
+ ); } // function NotFound() { @@ -396,41 +396,41 @@ function NotFound() { // } function parseDate(dateStr: string): Date { - const lower = dateStr.toLowerCase(); + const lower = dateStr.toLowerCase(); - if (lower.includes("q1")) return new Date("2023-01-01"); - if (lower.includes("q2")) return new Date("2023-04-01"); - if (lower.includes("q3")) return new Date("2023-07-01"); - if (lower.includes("q4")) return new Date("2023-10-01"); + if (lower.includes("q1")) return new Date("2023-01-01"); + if (lower.includes("q2")) return new Date("2023-04-01"); + if (lower.includes("q3")) return new Date("2023-07-01"); + if (lower.includes("q4")) return new Date("2023-10-01"); - const months: Record = { - january: 0, - february: 1, - march: 2, - april: 3, - may: 4, - june: 5, - july: 6, - august: 7, - september: 8, - october: 9, - november: 10, - december: 11, - }; + const months: Record = { + january: 0, + february: 1, + march: 2, + april: 3, + may: 4, + june: 5, + july: 6, + august: 7, + september: 8, + october: 9, + november: 10, + december: 11, + }; - for (const [monthName, monthIndex] of Object.entries(months)) { - if (lower.includes(monthName)) { - const yearMatch = dateStr.match(/\b(20\d{2})\b/); - if (yearMatch) { - return new Date(Number.parseInt(yearMatch[1], 10), monthIndex, 1); - } - } - } + for (const [monthName, monthIndex] of Object.entries(months)) { + if (lower.includes(monthName)) { + const yearMatch = dateStr.match(/\b(20\d{2})\b/); + if (yearMatch) { + return new Date(Number.parseInt(yearMatch[1], 10), monthIndex, 1); + } + } + } - const yearMatch = dateStr.match(/\b(20\d{2})\b/); - if (yearMatch) { - return new Date(Number.parseInt(yearMatch[1], 10), 0, 1); - } + const yearMatch = dateStr.match(/\b(20\d{2})\b/); + if (yearMatch) { + return new Date(Number.parseInt(yearMatch[1], 10), 0, 1); + } - return new Date(0); + return new Date(0); } diff --git a/src/components/Demo.tsx b/src/components/Demo.tsx index 522ecb0f..bfc0f54c 100644 --- a/src/components/Demo.tsx +++ b/src/components/Demo.tsx @@ -2,29 +2,29 @@ import type { ReactNode } from "react"; import { cn } from "@/lib/utils"; type DemoProps = { - image: string; - title: string; - type?: "boxed" | "plain"; - children?: ReactNode; + image: string; + title: string; + type?: "boxed" | "plain"; + children?: ReactNode; }; export function Demo({ image, title, type = "plain", children }: DemoProps) { - return ( -
- {title} -
- {title} - {children} -
-
- ); + return ( +
+ {title} +
+ {title} + {children} +
+
+ ); } diff --git a/src/components/ProjectListItem.tsx b/src/components/ProjectListItem.tsx index f9cf2542..c8a55896 100644 --- a/src/components/ProjectListItem.tsx +++ b/src/components/ProjectListItem.tsx @@ -3,69 +3,69 @@ import { cn } from "@/lib/utils"; import type { ProjectMetadata } from "@/projects"; export function ProjectListItem({ - metadata, - isDevMode = false, - isActive = false, - enableHover = true, + metadata, + isDevMode = false, + isActive = false, + enableHover = true, }: { - metadata: ProjectMetadata; - isDevMode?: boolean; - isActive?: boolean; - enableHover?: boolean; + metadata: ProjectMetadata; + isDevMode?: boolean; + isActive?: boolean; + enableHover?: boolean; }) { - const tags = metadata.tags ? [...metadata.tags].sort() : []; - if (metadata.hidden && !isDevMode) return null; + const tags = metadata.tags ? [...metadata.tags].sort() : []; + if (metadata.hidden && !isDevMode) return null; - return ( - - {metadata.type === "professional" ? ( - - Professional - - ) : null} -
-
- {metadata.image ? ( - {`${metadata.title} - ) : ( -
- )} -
-
-

- {metadata.title} -

-

{metadata.description}

- {tags.length > 0 ? ( -
- {tags.map((tag) => ( - - {tag} - - ))} -
- ) : null} -
-
-
-

{metadata.date}

-
- - ); + return ( + + {metadata.type === "professional" ? ( + + Professional + + ) : null} +
+
+ {metadata.image ? ( + {`${metadata.title} + ) : ( +
+ )} +
+
+

+ {metadata.title} +

+

{metadata.description}

+ {tags.length > 0 ? ( +
+ {tags.map((tag) => ( + + {tag} + + ))} +
+ ) : null} +
+
+
+

{metadata.date}

+
+ + ); } diff --git a/src/components/ProjectPage.tsx b/src/components/ProjectPage.tsx index 9f4bdcae..e7c058ba 100644 --- a/src/components/ProjectPage.tsx +++ b/src/components/ProjectPage.tsx @@ -6,150 +6,150 @@ import type { ProjectMetadata } from "@/projects"; import { AskAI } from "./ask-ai"; export function ProjectPage({ - metadata, - children, + metadata, + children, }: { - metadata: ProjectMetadata; - children: ReactNode; + metadata: ProjectMetadata; + children: ReactNode; }) { - const navigate = useNavigate(); - const tags = metadata.tags ? [...metadata.tags].sort() : []; + const navigate = useNavigate(); + const tags = metadata.tags ? [...metadata.tags].sort() : []; - useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - if (event.defaultPrevented || event.isComposing) return; - if (event.metaKey || event.ctrlKey || event.altKey) return; - if (isInteractiveTarget(event.target)) return; + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.defaultPrevented || event.isComposing) return; + if (event.metaKey || event.ctrlKey || event.altKey) return; + if (isInteractiveTarget(event.target)) return; - if ( - event.key === "Escape" || - event.key === "Backspace" || - event.key === "q" - ) { - event.preventDefault(); - navigate("/"); - } - }; + if ( + event.key === "Escape" || + event.key === "Backspace" || + event.key === "q" + ) { + event.preventDefault(); + navigate("/"); + } + }; - window.addEventListener("keydown", handleKeyDown); - return () => { - window.removeEventListener("keydown", handleKeyDown); - }; - }, [navigate]); + window.addEventListener("keydown", handleKeyDown); + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, [navigate]); - return ( -
-

- esc or backspace to go back -

- - - -
-
-

- {metadata.title} -

- {metadata.image ? ( - {`${metadata.title} - ) : ( -
- )} -
-
- -
-
- {metadata.url ? ( - - ) : null} + return ( +
+

+ esc or backspace to go back +

+ + + +
+
+

+ {metadata.title} +

+ {metadata.image ? ( + {`${metadata.title} + ) : ( +
+ )} +
+
+ +
+
+ {metadata.url ? ( + + ) : null} -

- {metadata.date} - {metadata.github ? ( - <> - {" "} - -{" "} - - Source Code - - - ) : null} -

+

+ {metadata.date} + {metadata.github ? ( + <> + {" "} + -{" "} + + Source Code + + + ) : null} +

- {tags.length > 0 ? ( -
- {tags.map((tag: string) => ( - - {tag} - - ))} -
- ) : null} + {tags.length > 0 ? ( +
+ {tags.map((tag: string) => ( + + {tag} + + ))} +
+ ) : null} -
{children}
+
{children}
-

- Oliver Bryan - {metadata.date} - {metadata.github ? ( - <> - {" "} - -{" "} - - Source Code - - - ) : null} -

-
- ); +

+ Oliver Bryan - {metadata.date} + {metadata.github ? ( + <> + {" "} + -{" "} + + Source Code + + + ) : null} +

+
+ ); } function isInteractiveTarget(target: EventTarget | null): boolean { - if (!(target instanceof HTMLElement)) return false; - if (target.isContentEditable) return true; - const tagName = target.tagName; - return ( - tagName === "INPUT" || - tagName === "TEXTAREA" || - tagName === "SELECT" || - tagName === "BUTTON" || - tagName === "A" - ); + if (!(target instanceof HTMLElement)) return false; + if (target.isContentEditable) return true; + const tagName = target.tagName; + return ( + tagName === "INPUT" || + tagName === "TEXTAREA" || + tagName === "SELECT" || + tagName === "BUTTON" || + tagName === "A" + ); } diff --git a/src/components/TravelListItem.tsx b/src/components/TravelListItem.tsx index c28b3c33..dba4fb23 100644 --- a/src/components/TravelListItem.tsx +++ b/src/components/TravelListItem.tsx @@ -1,25 +1,25 @@ -import type { TravelMetadata } from "@/travel"; -import { Button } from "./ui/button"; import type { MouseEventHandler } from "react"; import { cn } from "@/lib/utils"; +import type { TravelMetadata } from "@/travel"; +import { Button } from "./ui/button"; export function TravelListItem({ - metadata, - onClick, + metadata, + onClick, }: { - metadata: TravelMetadata; - onClick: MouseEventHandler; + metadata: TravelMetadata; + onClick: MouseEventHandler; }) { - return ( - - ); + return ( + + ); } diff --git a/src/components/ask-ai.tsx b/src/components/ask-ai.tsx index abb15296..a8cd06ee 100644 --- a/src/components/ask-ai.tsx +++ b/src/components/ask-ai.tsx @@ -8,81 +8,81 @@ const chatGptUrl = "https://chat.openai.com/?q="; const claudeUrl = "https://claude.ai/new?q="; export function AskAI({ - name, - prompt = AI_SUMMARY_PROMPT, - inline = false, + name, + prompt = AI_SUMMARY_PROMPT, + inline = false, }: { - name: string; - prompt?: string; - inline?: boolean; + name: string; + prompt?: string; + inline?: boolean; }) { - const encodedPrompt = encodeURIComponent(prompt); - const [copied, setCopied] = useState(false); - const timeoutRef = useRef(null); + const encodedPrompt = encodeURIComponent(prompt); + const [copied, setCopied] = useState(false); + const timeoutRef = useRef(null); - const handleCopy = async () => { - if (!navigator.clipboard) return; - try { - await navigator.clipboard.writeText(prompt); - setCopied(true); - if (timeoutRef.current) { - window.clearTimeout(timeoutRef.current); - } - timeoutRef.current = window.setTimeout(() => { - setCopied(false); - }, 1500); - } catch { - setCopied(false); - } - }; + const handleCopy = async () => { + if (!navigator.clipboard) return; + try { + await navigator.clipboard.writeText(prompt); + setCopied(true); + if (timeoutRef.current) { + window.clearTimeout(timeoutRef.current); + } + timeoutRef.current = window.setTimeout(() => { + setCopied(false); + }, 1500); + } catch { + setCopied(false); + } + }; - return ( -
-

Ask AI about {name}:

-
- - - - - - -
- - - Copied to clipboard - -
-
-
- ); + return ( +
+

Ask AI about {name}:

+
+ + + + + + +
+ + + Copied to clipboard + +
+
+
+ ); } diff --git a/src/components/paper-texture-overlay.tsx b/src/components/paper-texture-overlay.tsx index 764f001a..b7f09abf 100644 --- a/src/components/paper-texture-overlay.tsx +++ b/src/components/paper-texture-overlay.tsx @@ -2,54 +2,54 @@ import { PaperTexture } from "@paper-design/shaders-react"; import { useTheme } from "@/components/theme-provider"; const lightTexture = { - colorFront: "#5f4a331a", - contrast: 0.3, - roughness: 0.24, - fiber: 0.1, - crumples: 0, - folds: 0, - drops: 0, + colorFront: "#5f4a331a", + contrast: 0.3, + roughness: 0.24, + fiber: 0.1, + crumples: 0, + folds: 0, + drops: 0, }; const darkTexture = { - colorFront: "#f6efe31a", - contrast: 0.3, - roughness: 0.24, - fiber: 0.1, - crumples: 0, - folds: 0, - drops: 0, + colorFront: "#f6efe31a", + contrast: 0.3, + roughness: 0.24, + fiber: 0.1, + crumples: 0, + folds: 0, + drops: 0, }; export function PaperTextureOverlay() { - const { resolvedTheme } = useTheme(); - const isDark = resolvedTheme === "dark"; - const texture = isDark ? darkTexture : lightTexture; + const { resolvedTheme } = useTheme(); + const isDark = resolvedTheme === "dark"; + const texture = isDark ? darkTexture : lightTexture; - return ( -