"use client"; /** * Catalog detail-pane previews โ€” compose real DS components (no bespoke stand-ins). */ import * as React from "react"; import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"; import { ChartCard, ChartLeoPlotInsightOverlay, type ChartCardVariant, } from "@/components/charts-core"; import { CATALOG_PREVIEW_CHART_LEO } from "@/lib/catalog-preview-chart-leo"; import { KeyMetrics, type MetricItem } from "@/components/key-metrics"; import { LibraryBoardCard, LibraryBoardView, LibraryListRowCard, } from "@/components/library-board-view"; import { buildLibraryHubColumnDefs } from "@/components/library-table"; import { PageHeader } from "@/components/page-header"; import { Button } from "@/components/ui/button"; import { ColumnTypesRuleDemoTable } from "@/components/column-types-rule-demo-client"; import { DataTable } from "@/components/data-table"; import { useTableState } from "@/components/data-table/use-table-state"; import type { ColumnDef } from "@/components/data-table/types"; import { HubTable } from "@/components/data-views"; import { ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart"; import { ViewSegmentedControl } from "@/components/ui/view-segmented-control"; import { CHART_AXIS_TICK } from "@/lib/chart-typography"; import { toggleLibraryItemFavorite } from "@/lib/library-nav"; import { LIBRARY_ITEMS, type LibraryItem } from "@/lib/mock/library"; import { cn } from "@/lib/utils"; const CATALOG_LIBRARY_ROWS: LibraryItem[] = LIBRARY_ITEMS.slice(0, 9); const CATALOG_METRICS: MetricItem[] = [ { id: "published", label: "Published", value: 128, delta: "+6", trend: "up", trendPolarity: "higher_is_better", href: "#published", chart: { kind: "sparkline", series: [ { value: 98, label: "Jan" }, { value: 104, label: "Feb" }, { value: 110, label: "Mar" }, { value: 116, label: "Apr" }, { value: 122, label: "May" }, { value: 128, label: "Jun" }, ], }, }, { id: "draft", label: "Draft", value: 14, delta: "-2", trend: "down", trendPolarity: "higher_is_better", href: "#draft", chart: { kind: "bars", tone: "info", series: [ { value: 18, label: "Mon" }, { value: 16, label: "Tue" }, { value: 15, label: "Wed" }, { value: 17, label: "Thu" }, { value: 14, label: "Fri" }, { value: 14, label: "Sat" }, { value: 14, label: "Sun" }, ], }, }, { id: "review", label: "In review", value: 9, delta: "", trend: "neutral", trendPolarity: "informational", href: "#review", progress: 45, }, { id: "flags", label: "Review flags", value: 2, delta: "+1", trend: "up", trendPolarity: "lower_is_better", href: "#flags", alert: "danger", chart: { kind: "sparkline", tone: "danger", series: [ { value: 1, label: "Week 1" }, { value: 0, label: "Week 2" }, { value: 1, label: "Week 3" }, { value: 1, label: "Week 4" }, { value: 2, label: "Week 5" }, ], }, }, ]; const CATALOG_CHART_DATA = [ { month: "Jan", placements: 42 }, { month: "Feb", placements: 58 }, { month: "Mar", placements: 74 }, { month: "Apr", placements: 68 }, { month: "May", placements: 81 }, ]; const catalogChartConfig = { placements: { label: "Placements", color: "var(--brand-color)" }, } as const; const CATALOG_CHART_FILTER_OPTIONS = [ { value: "30d", label: "Last 30 days" }, { value: "90d", label: "Last quarter" }, { value: "1y", label: "Last year" }, ]; const CATALOG_CHART_VARIANT_OPTIONS: { value: ChartCardVariant; label: string; icon: string; }[] = [ { value: "normal", label: "Normal", icon: "fa-light fa-chart-column" }, { value: "tabs", label: "Tabs", icon: "fa-light fa-table-columns" }, { value: "selector", label: "Selector", icon: "fa-light fa-filter" }, { value: "metrics-tabs", label: "Metrics", icon: "fa-light fa-gauge-high" }, { value: "kpi-chart", label: "KPI", icon: "fa-light fa-hashtag" }, ]; function CatalogMiniBarChart() { return (
} />
); } const CATALOG_CHART_MINI_METRICS = [ { label: "Placements", value: "128", trend: "up" as const, trendPolarity: "higher_is_better" as const, }, { label: "Applications", value: "214", trend: "up" as const, trendPolarity: "informational" as const, }, { label: "Reviews", value: "42", trend: "neutral" as const, trendPolarity: "informational" as const, }, ]; export function CatalogChartCardVariantPreview({ variant, className, }: { variant: ChartCardVariant; className?: string; }) { const needsMiniMetrics = variant === "metrics-tabs" || variant === "kpi-chart"; const needsSelectorFilter = variant === "selector"; return ( ); } export function CatalogChartCardPreview({ className }: { className?: string }) { const [variant, setVariant] = React.useState("metrics-tabs"); return (
setVariant(v as ChartCardVariant)} aria-label="ChartCard variant" options={CATALOG_CHART_VARIANT_OPTIONS} />
); } export function CatalogKeyMetricsPreview({ className, }: { className?: string; }) { const [variant, setVariant] = React.useState<"cards" | "card" | "flat">( "cards", ); const [size, setSize] = React.useState<"sm" | "md" | "lg">("md"); return (
); } export function CatalogPageHeaderPreview() { return ( New record } /> ); } export function CatalogBoardCardPreview() { return ( {}} /> ); } export function CatalogLibraryListRowPreview() { return ( {}} /> ); } function CatalogLibraryHubTablePreview({ rows, onRowsChange, }: { rows: LibraryItem[]; onRowsChange: React.Dispatch>; }) { const toggleFavorite = React.useCallback( (row: LibraryItem) => { onRowsChange((prev) => prev.map((item) => item.id === row.id ? toggleLibraryItemFavorite(item) : item, ), ); }, [onRowsChange], ); const columns = React.useMemo( () => buildLibraryHubColumnDefs(rows, toggleFavorite), [rows, toggleFavorite], ); return (
rows={rows} columns={columns} view="table" hubLabel="Question bank" lifecycleTabLabel="All questions" searchAriaLabel="Search questions" getRowId={(row) => row.id} getRowSelectionLabel={(row) => row.stem} defaultSort={{ key: "stem", dir: "asc" }} emptyState="No questions." renderers={{}} supportedViewTypes={["table"]} persistKey="catalog-preview:library-hub-table" pagination={false} />
); } export function CatalogLibraryHubLivePreview({ className, }: { className?: string; }) { const [view, setView] = React.useState<"table" | "board">("board"); const [rows, setRows] = React.useState(CATALOG_LIBRARY_ROWS); const toggleFavorite = React.useCallback((row: LibraryItem) => { setRows((prev) => prev.map((item) => item.id === row.id ? toggleLibraryItemFavorite(item) : item, ), ); }, []); return (
{view === "board" ? (
) : ( )}
); } export function CatalogHubTablePreview({ className }: { className?: string }) { return ( ); } type CatalogGridRow = { id: string; name: string; status: string; updated: string; } & Record; const CATALOG_GRID_ROWS: CatalogGridRow[] = [ { id: "q_101", name: "Diaphragm innervation", status: "Published", updated: "2026-06-01", }, { id: "q_102", name: "Brachial plexus roots", status: "Draft", updated: "2026-06-02", }, { id: "q_103", name: "Cranial nerve functions", status: "In review", updated: "2026-06-03", }, { id: "q_104", name: "Lower limb dermatomes", status: "Published", updated: "2026-06-04", }, { id: "q_105", name: "Spinal cord tracts", status: "Draft", updated: "2026-06-05", }, ]; const CATALOG_GRID_COLUMNS: ColumnDef[] = [ { key: "name", label: "Question", width: 280, filter: { type: "text" }, }, { key: "status", label: "Status", width: 120, filter: { type: "select", options: [ { value: "Published", label: "Published" }, { value: "Draft", label: "Draft" }, { value: "In review", label: "In review" }, ], }, }, { key: "updated", label: "Updated", width: 120, filter: { type: "date" }, }, ]; /** Core grid only โ€” sort, filters, resize. Hubs wrap this in HubTable (+ Properties, views). */ export function CatalogDataTablePreview({ className }: { className?: string }) { const columns = React.useMemo(() => CATALOG_GRID_COLUMNS, []); const state = useTableState(CATALOG_GRID_ROWS, columns, { key: "name", dir: "asc", }); return (

DataTable โ€” the grid primitive. List hubs compose it via{" "} HubTable (toolbar + Properties + board/list/dashboard).

row.id} getRowSelectionLabel={(row) => row.name} state={state} defaultSort={{ key: "name", dir: "asc" }} emptyState="No questions match your filters." />
); }