import { IconFont, TemplateCard } from '@gpustack/core-ui'; import { useIntl } from '@umijs/max'; import { Tooltip } from 'antd'; import React, { useMemo } from 'react'; import styled from 'styled-components'; import { ProviderType } from '../config'; const Wrapper = styled.div<{ $cols?: number }>` width: 100%; display: grid; grid-template-columns: repeat(${(props) => props.$cols || 3}, 1fr); gap: 16px; .template-card-wrapper { padding: 10px 16px; } .template-card-inner { justify-content: center; } `; const Container = styled.div` display: flex; margin: 0 auto; flex-direction: column; gap: 24px; `; const Title = styled.span` display: flex; gap: 8px; align-items: center; font-weight: 500; font-size: 14px; margin-bottom: 16px; .icon { color: var(--ant-color-text-secondary); border-radius: 4px; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; background-color: var(--ant-color-fill-tertiary); } `; const Header = styled.div` display: flex; flex-direction: column; align-items: flex-start; gap: 4px; .title { font-weight: 500; } .description { font-size: 13px; font-weight: 400; color: var(--ant-color-text-tertiary); } `; const CardBox = styled.div` display: flex; overflow: hidden; `; interface ProviderCatalogProps { onSelect?: (provider: string, item: any) => void; groupIcons?: Record; cols?: number; // Single value (legacy) or array of selected keys for multi-select. current?: ProviderType | string | string[]; clickable?: boolean; height: string | number; showTooltip?: boolean; dataList: { label: string; key: string; locale?: boolean; disabled?: boolean; icon?: React.ReactNode; description?: string; group?: string; }[]; } const ProviderCatalog: React.FC = ({ onSelect, groupIcons, cols = 3, dataList, clickable, height, current, showTooltip = false }) => { const intl = useIntl(); const groupList = useMemo(() => { if (!dataList) return {}; return dataList?.reduce( (acc, item) => { (acc[item.group || 'default'] ??= []).push(item); return acc; }, {} as Record ); }, [dataList]); const renderTitle = (item: any) => { if (item.hiddenTitle) { return <>{item.extra && {item.extra}}; } return (
{item.locale ? intl.formatMessage({ id: item.label }) : item.label} {item.description && ( {intl.formatMessage({ id: item.description })} )} {item.extra && {item.extra}}
); }; return ( {Object.entries(groupList).map(([groupName, items]) => (
{groupName !== 'default' && ( {groupIcons && groupIcons[groupName] && ( <span className="icon"> <IconFont type={groupIcons[groupName]} /> </span> )} <span>{intl.formatMessage({ id: groupName })}</span> )} {items?.map((action) => ( onSelect?.(action.key as string, action)} active={ Array.isArray(current) ? current.includes(action.key) : current === action.key } disabled={action.disabled} clickable={clickable} header={renderTitle(action)} icon={action.icon} > ))}
))}
); }; export default ProviderCatalog;