{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "portfolio-chart", "type": "registry:component", "registryDependencies": [], "files": [ { "path": "components/domain-ui/experimental/portfolio-chart.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Area, AreaChart, ResponsiveContainer, XAxis, YAxis } from \"recharts\"\nimport { cn } from \"@/lib/utils\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/components/ui/chart\"\n\nexport interface PortfolioDataPoint {\n timestamp: number\n value: number\n}\n\nexport interface PortfolioChartProps {\n data: PortfolioDataPoint[]\n className?: string\n height?: number\n showGrid?: boolean\n showTooltip?: boolean\n timePeriods?: Array<{\n label: string\n value: string\n days: number\n }>\n onTimePeriodChange?: (period: string) => void\n selectedTimePeriod?: string\n}\n\nconst DEFAULT_TIME_PERIODS = [\n { label: \"1D\", value: \"1D\", days: 1 },\n { label: \"1W\", value: \"1W\", days: 7 },\n { label: \"1M\", value: \"1M\", days: 30 },\n { label: \"3M\", value: \"3M\", days: 90 },\n { label: \"1Y\", value: \"1Y\", days: 365 },\n { label: \"ALL\", value: \"ALL\", days: -1 }\n]\n\nconst chartConfig = {\n value: {\n label: \"Portfolio Value\",\n color: \"hsl(var(--chart-1))\",\n },\n} satisfies ChartConfig\n\nexport function PortfolioChart({\n data,\n className,\n height = 200,\n showGrid = true,\n showTooltip = true,\n timePeriods = DEFAULT_TIME_PERIODS,\n onTimePeriodChange,\n selectedTimePeriod = \"1D\"\n}: PortfolioChartProps) {\n // Transform data for Recharts\n const chartData = React.useMemo(() => {\n return data.map((point) => ({\n timestamp: point.timestamp,\n value: point.value,\n date: new Date(point.timestamp).toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric'\n }),\n time: new Date(point.timestamp).toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit'\n })\n }))\n }, [data])\n\n // Determine if portfolio is up or down\n const isPositive = data.length > 1 && \n data[data.length - 1]?.value !== undefined && \n data[0]?.value !== undefined && \n data[data.length - 1].value >= data[0].value\n const currentColor = isPositive ? \"#00C805\" : \"#FF3B30\"\n\n // Format currency\n const formatCurrency = (value: number) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n minimumFractionDigits: 2\n }).format(value)\n }\n\n // Calculate percentage change\n const calculateChange = () => {\n if (data.length < 2) return { amount: 0, percentage: 0 }\n const start = data[0]?.value || 0\n const end = data[data.length - 1]?.value || 0\n const amount = end - start\n const percentage = start !== 0 ? (amount / start) * 100 : 0\n return { amount, percentage }\n }\n\n const change = calculateChange()\n const currentValue = data[data.length - 1]?.value || 0\n\n return (\n