"use client"; import { useCallback, useMemo, useRef, useState } from "react"; import Link from "next/link"; import { usePathname, useSearchParams } from "next/navigation"; import { ArrowDownAZ, ArrowDownUp, ArrowUpAZ, Check, ChevronDown, Clock, Hash } from "lucide-react"; import { useClickOutside } from "@/lib/hooks/useClickOutside"; import { SORT_OPTIONS, labelFor, type SortKey } from "@/lib/sort"; import { cn } from "@/lib/utils"; const ICONS: Record> = { newest: Clock, oldest: Clock, az: ArrowDownAZ, za: ArrowUpAZ, "code-az": Hash, "code-za": Hash, }; export function SortMenu({ activeSort }: { activeSort: SortKey }) { const [open, setOpen] = useState(false); const ref = useRef(null); useClickOutside(ref, useCallback(() => setOpen(false), []), open); const pathname = usePathname(); const params = useSearchParams(); const hrefFor = useMemo(() => (next: SortKey) => { const sp = new URLSearchParams(params); sp.set("sort", next); return `${pathname}?${sp.toString()}`; }, [pathname, params]); const Icon = ICONS[activeSort] ?? ArrowDownUp; return (
{open && (
{SORT_OPTIONS.map((o, i) => { const OptIcon = ICONS[o.value]; const active = o.value === activeSort; const prev = SORT_OPTIONS[i - 1]; // Group divider whenever the underlying sort dimension // changes (date → title → code). newest/oldest share the // date dimension; az/za and code-az/code-za each share theirs. const groupOf = (v: string) => v === "newest" || v === "oldest" ? "date" : v.replace(/-?(az|za)$/, "") || "title"; const showDivider = prev && groupOf(prev.value) !== groupOf(o.value); return (
{showDivider && (
)} setOpen(false)} className={cn( "flex items-center gap-2 px-3 py-1.5 rounded-md text-sm hover:bg-[var(--color-glass)]", active && "text-[var(--color-cyan)]" )} > {o.label} {active && }
); })}
)}
); }