import clsx from 'clsx'; import { useInView } from 'motion/react'; import { AnimatePresence, motion, Variants } from 'motion/react'; import { CSSProperties, memo, ReactNode, RefObject, useEffect, useRef } from 'react'; import styles from './page-header.module.css'; import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay'; import { useShouldPadTitlebar } from '/@/renderer/hooks'; import { useWindowSettings } from '/@/renderer/store/settings.store'; import { Flex, FlexProps } from '/@/shared/components/flex/flex'; import { Platform } from '/@/shared/types/types'; export interface PageHeaderProps extends Omit< FlexProps, 'onAnimationStart' | 'onDrag' | 'onDragEnd' | 'onDragStart' > { animated?: boolean; backgroundColor?: string; children?: ReactNode; height?: string; isHidden?: boolean; position?: string; scrollContainerRef?: RefObject; target?: RefObject; } const variants: Variants = { animate: { opacity: 1, transition: { duration: 0.3, ease: 'easeIn', }, }, exit: { opacity: 0 }, initial: { opacity: 0 }, }; const BasePageHeader = ({ animated, backgroundColor, children, height, isHidden, position, scrollContainerRef, target, ...props }: PageHeaderProps) => { const ref = useRef(null); const padRight = useShouldPadTitlebar(); const { windowBarStyle } = useWindowSettings(); const isInView = useInView({ current: target?.current || null, }); useEffect(() => { const headerElement = ref.current as HTMLElement | null; const scrollContainer = scrollContainerRef?.current; if (!scrollContainerRef) { if (headerElement) { headerElement.setAttribute('data-visible', isHidden ? 'false' : 'true'); } return undefined; } if (!scrollContainer || !headerElement) { if (headerElement) { headerElement.setAttribute('data-visible', 'false'); } return undefined; } const updateVisibility = () => { const dataScrolled = scrollContainer.getAttribute('data-scrolled'); const isScrolled = dataScrolled === 'true'; const shouldShow = isScrolled && !isInView; if (shouldShow) { headerElement.setAttribute('data-visible', 'true'); } else { headerElement.setAttribute('data-visible', 'false'); } }; updateVisibility(); const observer = new MutationObserver(updateVisibility); observer.observe(scrollContainer, { attributeFilter: ['data-scrolled'], attributes: true, }); return () => observer.disconnect(); }, [isInView, scrollContainerRef, isHidden]); return ( <>
{children}
{backgroundColor && ( )}
); }; export const PageHeader = memo(BasePageHeader); PageHeader.displayName = 'PageHeader';