import {useCallback, useEffect, useMemo, useState} from 'react'; import {Link} from 'react-router'; import {motion} from 'motion/react'; import {AbiirProductListItem} from '~/components/AbiirProductListItem'; import type { AbiirProductListItemData, FeaturedProductsCms, } from '~/lib/featuredProducts'; import { MOCK_FEATURED_PRODUCT_ROWS, MOCK_FEATURED_PRODUCTS_CMS, } from '~/lib/featuredProducts'; import {PAGE_TITLE_TYPOGRAPHY_CLASS} from '~/lib/pageTitle'; import {useSwipeNavigate} from '~/lib/useSwipeNavigate'; /** Desktop featured grid matches `ABIIR_PRODUCT_LIST_GRID_CLASS` at `lg:` only (`abiirProductListGrid.ts`). */ const FEATURED_DESKTOP_GRID_CLASS = 'hidden w-full max-w-full lg:grid lg:grid-cols-4 lg:gap-x-[34px] lg:gap-y-10'; /** * GROQ: `home` singleton → featured products (Most Loved) module. * Use with `context.sanity.loadQuery(FEATURED_PRODUCTS_GROQ)` or `useQuery` in the browser. */ export const FEATURED_PRODUCTS_GROQ = `*[_type == "home" && _id == "home"][0].featuredProducts{ eyebrow, title, filterPills[]{label, href}, viewAllLabel, viewAllHref, items[]{ productHandle, hideBadge, cardTitle, subtitle, benefitChips, rating, reviewCount } }` as const; export type {FeaturedProductsCms, AbiirProductListItemData}; export {MOCK_FEATURED_PRODUCTS_CMS, MOCK_FEATURED_PRODUCT_ROWS}; const sectionBg = '#f8f4ef'; const burgundy = '#5d0b24'; const charcoal = '#1a1a18'; /** Mobile / tablet featured strip: auto-advance interval (desktop keeps grid). */ const FEATURED_MOBILE_SLIDE_MS = 4000; function FeaturedProductsMobileSlider({rows}: {rows: AbiirProductListItemData[]}) { const [active, setActive] = useState(0); const rowsKey = useMemo( () => rows.map((r) => r.handle).join('\0'), [rows], ); useEffect(() => { setActive(0); }, [rowsKey]); useEffect(() => { if (rows.length <= 1) return; if (typeof window === 'undefined') return; if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; const id = window.setInterval(() => { setActive((i) => (i + 1) % rows.length); }, FEATURED_MOBILE_SLIDE_MS); return () => window.clearInterval(id); }, [rows.length]); const goPrev = useCallback(() => { if (rows.length <= 1) return; setActive((i) => (i - 1 + rows.length) % rows.length); }, [rows.length]); const goNext = useCallback(() => { if (rows.length <= 1) return; setActive((i) => (i + 1) % rows.length); }, [rows.length]); const swipe = useSwipeNavigate(goPrev, goNext); return (