/* eslint-disable import/no-unresolved */ import { MenuOutlined } from '@ant-design/icons'; import { ClassNames, css } from '@emotion/react'; import { Col, Popover, Row, Select } from 'antd'; import classNames from 'classnames'; import { useLocale, useLocation } from 'dumi'; import DumiSearchBar from 'dumi/theme-default/slots/SearchBar'; import React, { useCallback, useContext, useEffect, useState, type FC } from 'react'; import LangSwitch from 'dumi/theme/slots/LangSwitch'; import RtlSwitch from 'dumi/theme/slots/RtlSwitch'; import useAdditionalThemeConfig from '../../hooks/useAdditionalThemeConfig'; import useSiteToken from '../../hooks/useSiteToken'; import type { SiteContextProps } from '../SiteContext'; import SiteContext from '../SiteContext'; import HeaderExtra from './HeaderExtral'; import Logo from './Logo'; import More from './More'; import Navigation from './Navigation'; interface HeaderState { windowWidth: number; menuVisible: boolean; } export type IResponsive = null | 'narrow' | 'crowded'; const RESPONSIVE_XS = 1120; const RESPONSIVE_SM = 1200; const colPropsHome = [ { flex: 'none' }, { flex: 'auto' } ]; const _colProps = [ { xxl: 4, xl: 5, lg: 6, md: 6, sm: 24, xs: 24 }, { xxl: 20, xl: 19, lg: 18, md: 18, sm: 0, xs: 0 } ]; const useStyle = () => { const { token } = useSiteToken(); const searchIconColor = '#ced4d9'; return { header: css` position: sticky; top: 0; z-index: 99; max-width: 100%; background: ${token.colorBgContainer}; box-shadow: ${token.boxShadowTertiary}; @media only screen and (max-width: ${token.mobileMaxWidth}px) { text-align: center; } .nav-search-wrapper { display: flex; flex: auto; } .dumi-default-search-bar { border-inline-start: 1px solid rgba(0, 0, 0, 0.06); > svg { width: 14px; fill: ${searchIconColor}; } > input { height: 22px; border: 0; &:focus { box-shadow: none; } &::placeholder { color: ${searchIconColor}; } } .dumi-default-search-shortcut { color: ${searchIconColor}; background-color: rgba(150, 150, 150, 0.06); border-color: rgba(100, 100, 100, 0.2); border-radius: 4px; } .dumi-default-search-popover { inset-inline-start: 11px; inset-inline-end: unset; &::before { inset-inline-start: 100px; inset-inline-end: unset; } } } `, menuRow: css` display: flex; align-items: center; margin: 0; > * { flex: none; margin: 0 12px 0 0; &:last-child { margin-inline-end: 40px; } } ${token.antCls}-row-rtl & { > * { &:last-child { margin-right: 12px; margin-left: 40px; } } } `, popoverMenu: { width: 300, [`${token.antCls}-popover-inner-content`]: { padding: 0 } } }; }; const Header: FC = () => { const { isMobile } = useContext(SiteContext); const [headerState, setHeaderState] = useState({ windowWidth: 1400, menuVisible: false }); const location = useLocation(); const { docVersions } = useAdditionalThemeConfig(); const onWindowResize = useCallback(() => { if (typeof window === 'undefined') { return; } setHeaderState((prev) => ({ ...prev, windowWidth: window.innerWidth })); }, []); const handleHideMenu = useCallback(() => { setHeaderState((prev) => ({ ...prev, menuVisible: false })); }, []); const onMenuVisibleChange = useCallback((visible: boolean) => { setHeaderState((prev) => ({ ...prev, menuVisible: visible })); }, []); const handleVersionChange = useCallback((url: string) => { if (typeof window === 'undefined') { return; } window.location.href = url; }, []); useEffect(() => { handleHideMenu(); }, [location, handleHideMenu]); useEffect(() => { if (typeof window === 'undefined') { return () => {}; } onWindowResize(); window.addEventListener('resize', onWindowResize); return () => { window.removeEventListener('resize', onWindowResize); }; }, [onWindowResize]); const { pathname } = location; const locale = useLocale(); const suffix: string = (locale as any).suffex || ''; const isHome = ['', `index${suffix}`].includes(pathname); const { windowWidth, menuVisible } = headerState; const style = useStyle(); const headerClassName = classNames({ clearfix: true, 'home-header': isHome }); let responsive: IResponsive = null; if (windowWidth < RESPONSIVE_XS) { responsive = 'crowded'; } else if (windowWidth < RESPONSIVE_SM) { responsive = 'narrow'; } const navigationNode = ; const versionOptions = Object.keys(docVersions ?? {}).map((version) => ({ value: docVersions?.[version], label: version })); let menu: (React.ReactElement | null)[] = [ navigationNode, versionOptions.length > 0 ? (