import React, { ReactNode } from 'react'; import styled from 'styled-components'; import type { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config'; import type { BffCatalogEntity } from '@redocly/theme/core/types'; import { CatalogOwnersCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogOwnersCell'; import { CatalogDomainsCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogDomainsCell'; import { CatalogEntityCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogEntityCell'; import { CatalogTableHeaderCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTableHeaderCell'; import { CatalogTagsCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTagsCell'; import { CatalogTableViewRow } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTableViewRow'; import { CatalogEntityTypeTag } from '@redocly/theme/components/Catalog/CatalogEntityTypeTag'; import { breakpoints } from '@redocly/theme/core'; import { CatalogLastUpdateCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogLastUpdateCell'; export type BaseEntity = { id: string; key: string; type: string; title: string; summary?: string | null; }; export type CatalogTableViewProps = { entities: T[]; entitiesCatalogConfig?: EntitiesCatalogConfig; catalogConfig: CatalogEntityConfig; columns?: CatalogColumn[]; currentSortOption?: string | null; onRowClick?: (entity: T) => void; handleSortClick: (sortKey: string, direction: 'asc' | 'desc') => void; isColumnSorted: (sortKey: string, direction: 'asc' | 'desc') => boolean; style?: React.CSSProperties; contentMinWidth?: number; }; export type CatalogColumn = { key: string; title: string; render: (entity: T) => ReactNode; width?: string; minWidth?: string; sortable?: boolean; sortKey?: string; }; const baseColumns: CatalogColumn[] = [ { key: 'entity', title: 'Entity', render: (entity) => , width: '3fr', minWidth: '164px', sortable: true, sortKey: 'title', }, { key: 'type', title: 'Type', render: (entity) => , width: '2fr', minWidth: '162px', sortable: true, sortKey: 'type', }, { key: 'domains', title: 'Domains', render: (entity) => ( domain.title) || []} /> ), width: '2fr', minWidth: '162px', }, { key: 'owners', title: 'Owners', render: (entity) => ( owner.title) || []} /> ), width: '2fr', minWidth: '162px', }, { key: 'tags', title: 'Tags', render: (entity) => , width: '2fr', minWidth: '160px', }, { key: 'lastUpdate', title: 'Last update', render: (entity) => , width: '1fr', minWidth: '112px', sortable: true, sortKey: 'updated_at', }, ]; export const CatalogTableView = ({ entities, entitiesCatalogConfig, catalogConfig, columns = baseColumns as CatalogColumn[], currentSortOption, onRowClick, handleSortClick, isColumnSorted, style, contentMinWidth, }: CatalogTableViewProps) => { const tableContent = ( <> column.width || '1fr')} columnsMinWidths={columns.map((column) => column.minWidth || 'auto')} > {columns.map((column) => ( key={column.key} column={column} currentSortOption={currentSortOption} handleSortClick={handleSortClick} isColumnSorted={isColumnSorted} /> ))} {entities.map((entity) => ( ))} ); return ( {contentMinWidth != null ? ( {tableContent} ) : ( {tableContent} )} ); }; const CatalogTableWrapper = styled.div` width: 100%; border-bottom: 1px solid var(--catalog-table-border-color); overflow-x: auto; @media screen and (max-width: ${breakpoints.medium}) { margin-top: 0; } `; const CatalogTableScrollContent = styled.div` min-width: min-content; `; const CatalogTableContentInner = styled.div<{ $contentMinWidth: number }>` min-width: ${({ $contentMinWidth }) => $contentMinWidth}px; `; const CatalogTableHeader = styled.div<{ columnsWidths: string[]; columnsMinWidths: string[] }>` display: grid; grid-template-columns: ${({ columnsWidths, columnsMinWidths }) => columnsWidths .map((width, index) => columnsMinWidths[index] !== 'auto' ? `minmax(${columnsMinWidths[index]}, ${width})` : width, ) .join(' ')}; background: var(--catalog-table-header-bg-color); font-weight: var(--catalog-table-header-font-weight); border-radius: var(--border-radius) var(--border-radius) 0 0; `; const CatalogTableBody = styled.div` min-width: min-content; `;