"use client";
import { BookOpenText, ChevronDown, ExternalLink, Globe2 } from "lucide-react";
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
import {
type ReactNode,
useCallback,
useId,
useState,
} from "react";
import { AgentDisclosure } from "@/components/agents/agent-disclosure";
import { EASE_OUT, SPRING_LAYOUT, SPRING_SWAP } from "@/lib/ease";
import { useFavicon } from "@/lib/hooks/use-favicon";
import { cn } from "@/lib/utils";
export interface CitationItem {
id: string;
title: ReactNode;
domain?: ReactNode;
url?: string;
/**
* Replaces the URL favicon, e.g. a document icon for non-web sources. An svg
* child is sized to match the favicon; falsy values fall back to the favicon.
*/
icon?: ReactNode;
}
export interface CitationsProps {
citations: CitationItem[];
title?: ReactNode;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?: (open: boolean) => void;
idPrefix?: string;
className?: string;
}
export interface CitationProps {
citationId: string;
index: number;
/** Must match the related Citations idPrefix. */
idPrefix: string;
/**
* Accessible name for the marker. Defaults to `View citation {index}`. Include
* the index so voice control users can say the number they see.
*/
label?: string;
className?: string;
}
export interface CitationListProps {
citations: CitationItem[];
idPrefix?: string;
className?: string;
}
export interface CitationStackProps {
citations: CitationItem[];
limit?: number;
className?: string;
}
function citationTargetId(prefix: string, citationId: string) {
return `${prefix}-${citationId.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
}
export function Citation({
citationId,
index,
idPrefix,
label,
className,
}: CitationProps) {
return (
{index}
);
}
export function CitationFavicon({
url,
icon,
className,
}: {
url?: string;
/** Drawn instead of the favicon when truthy. */
icon?: ReactNode;
className?: string;
}) {
const favicon = useFavicon(icon ? undefined : url);
return (
);
}
export function CitationStack({
citations,
limit = 3,
className,
}: CitationStackProps) {
return (
);
}
function CitationRow({
citation,
index,
idPrefix,
}: {
citation: CitationItem;
index: number;
idPrefix: string;
}) {
const content = (
<>