import React, { memo, useContext, useMemo, useRef, useState } from 'react'; import type { CSSProperties } from 'react'; import { Link, useIntl, useSidebarData, useLocation } from 'dumi'; import { createStyles, useTheme } from 'antd-style'; import debounce from 'lodash/debounce'; import { SearchOutlined } from '@ant-design/icons'; import { Card, Col, Divider, Input, Row, Space, Tag, Typography, Affix } from 'antd'; import type { Component } from './ProComponentsList'; import proComponentsList from './ProComponentsList'; import SiteContext from '../../slots/SiteContext'; const useStyle = createStyles(({ token, css }) => ({ componentsOverviewGroupTitle: css` margin-bottom: 24px !important; `, componentsOverviewTitle: css` overflow: hidden; color: ${token.colorTextHeading}; text-overflow: ellipsis; `, componentsOverviewImg: css` display: flex; align-items: center; justify-content: center; height: 152px; `, componentsOverviewCard: css` cursor: pointer; transition: all 0.5s; &:hover { box-shadow: 0 6px 16px -8px #00000014, 0 9px 28px #0000000d, 0 12px 48px 16px #00000008; } `, componentsOverviewAffix: css` display: flex; transition: all 0.3s; justify-content: space-between; `, componentsOverviewSearch: css` padding: 0; .anticon-search { color: ${token.colorTextDisabled}; } `, componentsOverviewContent: css` &:empty:after { display: block; padding: 16px 0 40px; color: ${token.colorTextDisabled}; text-align: center; border-bottom: 1px solid ${token.colorSplit}; content: 'Not Found'; } `, })); const onClickCard = (pathname: string) => { if (window.gtag) { window.gtag('event', '点击', { event_category: '组件总览卡片', event_label: pathname, }); } }; const reportSearch = debounce<(value: string) => void>((value) => { if (window.gtag) { window.gtag('event', '搜索', { event_category: '组件总览卡片', event_label: value, }); } }, 2000); const { Title } = Typography; const Overview: React.FC = () => { const { styles } = useStyle(); const { theme } = useContext(SiteContext); const data = useSidebarData(); const [searchBarAffixed, setSearchBarAffixed] = useState(false); const token = useTheme(); const { borderRadius, colorBgContainer, fontSizeXL } = token; const affixedStyle: CSSProperties = { boxShadow: 'rgba(50, 50, 93, 0.25) 0 6px 12px -2px, rgba(0, 0, 0, 0.3) 0 3px 7px -3px', padding: 8, margin: -8, borderRadius, backgroundColor: colorBgContainer, }; const { search: urlSearch } = useLocation(); const { locale, formatMessage } = useIntl(); const [search, setSearch] = useState(() => { const params = new URLSearchParams(urlSearch); if (params.has('s')) { return params.get('s'); } return ''; }); const sectionRef = useRef(null); const onKeyDown: React.KeyboardEventHandler = (event) => { if (event.keyCode === 13 && search.trim().length) { sectionRef.current?.querySelector('.components-overview-card')?.click(); } }; const groups = useMemo<{ title: string; children: Component[] }[]>( () => data .filter((item) => item?.title) .map<{ title: string; children: Component[] }>((item) => ({ title: item?.title, children: item.children.map((child) => ({ title: child.frontmatter?.title, subtitle: child.frontmatter.subtitle, cover: child.frontmatter.cover, coverDark: child.frontmatter.coverDark, link: child.link, })), })) .concat([ { title: locale === 'zh-CN' ? '重型组件' : 'Others', children: locale === 'zh-CN' ? proComponentsList : proComponentsList.map((component) => ({ ...component, subtitle: '' })), }, ]), [data, locale], ); return (
{ setSearch(e.target.value); reportSearch(e.target.value); }} onKeyDown={onKeyDown} bordered={false} suffix={} style={{ fontSize: searchBarAffixed ? fontSizeXL - 2 : fontSizeXL }} />
{groups .filter((i) => i?.title) .map((group) => { const components = group?.children?.filter( (component) => !search.trim() || component?.title?.toLowerCase()?.includes(search.trim().toLowerCase()) || (component?.subtitle || '').toLowerCase().includes(search.trim().toLowerCase()), ); return components?.length ? (
<Space align="center"> <span style={{ fontSize: 24 }}>{group?.title}</span> <Tag style={{ display: 'block' }}>{components.length}</Tag> </Space> {components.map((component) => { /** 是否是外链 */ const isExternalLink = component.link.startsWith('http'); let url = `${component.link}`; if (!isExternalLink) { url += urlSearch; } /** Link 不能跳转到外链 */ const ComponentLink = isExternalLink ? 'a' : Link; return ( onClickCard(url)}> {component?.title} {component.subtitle}
} >
{component?.title}
); })}
) : null; })}
); }; export default memo(Overview);