import Image from 'next/image' import Link from 'next/link' import {usePathname} from 'next/navigation' import {Fragment, useEffect, useRef} from 'react' import {Popover, Transition} from '@headlessui/react' import clsx from 'clsx' import {Container} from './Container' import {MobileNavItem} from './MobileNavItem' import {CloseIcon} from './icons/CloseIcon' import {ChevronDownIcon} from './icons/ChevronDownIcon' import {MoonIcon} from './icons/MoonIcon' import {SunIcon} from './icons/SunIcon' import avatar from '@/public/static/images/avatar.jpg' import type {Props} from 'types' function MobileNavigation(props: Props) { return ( Menu

Navigation

) } function NavItem({href, children}: { href: string } & Props) { let isActive = usePathname() === href return (
  • {children} {isActive && ( )}
  • ) } function DesktopNavigation(props: Props) { return ( ) } function ModeToggle() { function disableTransitionsTemporarily() { document.documentElement.classList.add('[&_*]:!transition-none') window.setTimeout(() => { document.documentElement.classList.remove('[&_*]:!transition-none') }, 0) } function toggleMode() { disableTransitionsTemporarily() let darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)') let isSystemDarkMode = darkModeMediaQuery.matches let isDarkMode = document.documentElement.classList.toggle('dark') if (isDarkMode === isSystemDarkMode) { delete window.localStorage.isDarkMode } else { window.localStorage.isDarkMode = isDarkMode } } return ( ) } function clamp(num: number, a: number, b: number) { let min = Math.min(a, b) let max = Math.max(a, b) return Math.min(Math.max(num, min), max) } function AvatarContainer({className, ...props}: { style?: Object } & Props) { return (
    ) } function Avatar({large = false, className, ...props}: { large?: boolean, style?: Object } & Props) { return ( ) } export function Header() { const isHomePage = usePathname() === '/' const headerRef = useRef(null) const avatarRef = useRef(null) const isInitial = useRef(true) const headerPosition: Object = { position: 'var(--header-position)' } const headerInnerPosition: Object = { position: 'var(--header-inner-position)' } useEffect(() => { let downDelay = avatarRef.current?.offsetTop ?? 0 let upDelay = 64 function setProperty(property: string, value: string) { document.documentElement.style.setProperty(property, value.toString()) } function removeProperty(property: string) { document.documentElement.style.removeProperty(property) } function updateHeaderStyles() { const headerBoundingRect = headerRef.current?.getBoundingClientRect() let top = headerBoundingRect?.top! let height = headerBoundingRect?.height! let scrollY = clamp( window.scrollY, 0, document.body.scrollHeight - window.innerHeight ) if (isInitial.current) { setProperty('--header-position', 'sticky') } setProperty('--content-offset', `${downDelay}px`) if (isInitial.current || scrollY < downDelay) { setProperty('--header-height', `${downDelay + height}px`) setProperty('--header-mb', `${-downDelay}px`) } else if (top + height < -upDelay) { let offset = Math.max(height, scrollY - upDelay) setProperty('--header-height', `${offset}px`) setProperty('--header-mb', `${height - offset}px`) } else if (top === 0) { setProperty('--header-height', `${scrollY + height}px`) setProperty('--header-mb', `${-scrollY}px`) } if (top === 0 && scrollY > 0 && scrollY >= downDelay) { setProperty('--header-inner-position', 'fixed') removeProperty('--header-top') removeProperty('--avatar-top') } else { removeProperty('--header-inner-position') setProperty('--header-top', '0px') setProperty('--avatar-top', '0px') } } function updateAvatarStyles() { if (!isHomePage) { return } let fromScale = 1 let toScale = 36 / 64 let fromX = 0 let toX = 2 / 16 let scrollY = downDelay - window.scrollY let scale = (scrollY * (fromScale - toScale)) / downDelay + toScale scale = clamp(scale, fromScale, toScale) let x = (scrollY * (fromX - toX)) / downDelay + toX x = clamp(x, fromX, toX) setProperty( '--avatar-image-transform', `translate3d(${x}rem, 0, 0) scale(${scale})` ) let borderScale = 1 / (toScale / scale) let borderX = (-toX + x) * borderScale let borderTransform = `translate3d(${borderX}rem, 0, 0) scale(${borderScale})` setProperty('--avatar-border-transform', borderTransform) setProperty('--avatar-border-opacity', (scale === toScale ? 1 : 0).toString()) } function updateStyles() { updateHeaderStyles() updateAvatarStyles() isInitial.current = false } updateStyles() const opts: AddEventListenerOptions & EventListenerOptions = {passive: true} window.addEventListener('scroll', updateStyles, opts) window.addEventListener('resize', updateStyles) return () => { window.removeEventListener('scroll', updateStyles, opts) window.removeEventListener('resize', updateStyles) } }, [isHomePage]) return ( <>
    {isHomePage && ( <>
    )}
    {!isHomePage && ( )}
    {isHomePage &&
    } ) }