/* Copyright 2026 Marimo. All rights reserved. */ "use no memo"; // tanstack/table is not compatible with React compiler // https://github.com/TanStack/table/issues/5567 import { ChevronDownIcon, ChevronRightIcon, EyeIcon, EyeOffIcon, } from "lucide-react"; import { useState } from "react"; import { useLocale } from "react-aria"; import { AddDataframeChart, renderChart, renderPreviewError, renderStats, } from "@/components/datasources/column-preview"; import { ColumnName, ColumnPreviewContainer, EmptyState, ErrorState, LoadingState, } from "@/components/datasources/components"; import { ErrorBoundary } from "@/components/editor/boundary/ErrorBoundary"; import { CopyClipboardIcon } from "@/components/icons/copy-icon"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Tooltip } from "@/components/ui/tooltip"; import type { DataType } from "@/core/kernel/messages"; import { useAsyncData } from "@/hooks/useAsyncData"; import type { PreviewColumn } from "@/plugins/impl/DataTablePlugin"; import { useTheme } from "@/theme/useTheme"; import { NAMELESS_COLUMN_PREFIX } from "../columns"; import { prettifyRowColumnCount } from "../pagination"; import { type FieldTypesWithExternalType, INDEX_COLUMN_NAME, SELECT_COLUMN_ID, } from "../types"; import { smartMatch } from "@/utils/smartMatch"; import type { Column, Table } from "@tanstack/react-table"; import { cn } from "@/utils/cn"; import { getColumnCountForDisplay, getShowOnlyColumnState, getUserColumnVisibilityCounts, isShowingOnlyColumns, type ShowOnlyColumnState, } from "../hooks/use-column-visibility"; import { ShowOnlyColumnButton } from "../show-only-column-button"; interface ColumnExplorerPanelProps { previewColumn: PreviewColumn; fieldTypes: FieldTypesWithExternalType | undefined | null; totalRows: number | "too_many"; totalColumns: number; tableId: string; table: Table; } export function ColumnExplorerPanel({ previewColumn, fieldTypes, totalRows, totalColumns, tableId, table, }: ColumnExplorerPanelProps) { const [searchValue, setSearchValue] = useState(""); const { locale } = useLocale(); const columns = fieldTypes?.filter(([columnName]) => { if ( columnName === SELECT_COLUMN_ID || columnName === INDEX_COLUMN_NAME || columnName.startsWith(NAMELESS_COLUMN_PREFIX) ) { return false; } return true; }); const filteredColumns = columns?.filter(([columnName]) => { return smartMatch(searchValue, columnName); }); const { totalColumns: effectiveTotalColumns, hiddenColumns: hiddenColumnCount, } = getColumnCountForDisplay(table, totalColumns); const { visible: visibleColumnCount } = getUserColumnVisibilityCounts(table); const showOnlyColumnState = getShowOnlyColumnState(table); const { rowsAndColumns, hiddenSuffix } = prettifyRowColumnCount({ numRows: totalRows, totalColumns: effectiveTotalColumns, locale, hiddenColumns: hiddenColumnCount, }); return (
{rowsAndColumns} {hiddenColumnCount > 0 && {hiddenSuffix}} columnName).join(",\n") || ""} className="h-3 w-3" />
setSearchValue(value)} /> No results. {filteredColumns?.map( ([columnName, [dataType, externalType]], index) => { const column = table.getColumn(columnName); return ( ); }, )}
); } function ColumnItem({ columnName, column, dataType, externalType, previewColumn, table, showOnlyColumnState, defaultExpanded = false, }: { columnName: string; column?: Column; dataType: DataType; externalType: string; previewColumn: PreviewColumn; table: Table; showOnlyColumnState: ShowOnlyColumnState; defaultExpanded?: boolean; }) { const [isExpanded, setIsExpanded] = useState(defaultExpanded); const columnText = ( {columnName} ); return ( <> setIsExpanded(!isExpanded)} className="flex flex-row items-center gap-1.5 group w-full cursor-pointer" > {isExpanded ? ( ) : ( )}
{column?.getCanHide() && ( <> )} {externalType}
{isExpanded && ( )} ); } const ColumnPreview = ({ previewColumn, columnName, dataType, }: { previewColumn: PreviewColumn; columnName: string; dataType: DataType; }) => { const { theme } = useTheme(); const { locale } = useLocale(); const { data, error, isPending, refetch: refetchPreview, } = useAsyncData(async () => { const response = await previewColumn({ column: columnName }); return response; }, []); if (error) { return ; } if (isPending) { return ; } if (!data) { return ; } const { chart_spec, chart_code, error: previewError, missing_packages, stats, } = data; const errorState = previewError && renderPreviewError({ error: previewError, missingPackages: missing_packages, refetchPreview, }); const previewStats = stats && renderStats({ stats, dataType, locale }); const chart = chart_spec && renderChart(chart_spec, theme); const addDataframeChart = chart_code && ( ); return ( {errorState} {addDataframeChart} {chart} {previewStats} ); };