The Node.js® Website
at main 60 lines 1.5 kB view raw
1import type { Heading } from '@vcarl/remark-headings'; 2import { useTranslations } from 'next-intl'; 3import { Fragment, useMemo } from 'react'; 4import type { FC } from 'react'; 5 6import Link from '@/components/Link'; 7 8import styles from './index.module.css'; 9 10type MetaBarProps = { 11 items: Record<string, React.ReactNode>; 12 headings?: { 13 items: Array<Heading>; 14 minDepth?: number; 15 }; 16}; 17 18const MetaBar: FC<MetaBarProps> = ({ items, headings }) => { 19 const t = useTranslations(); 20 21 // The default depth of headings to display in the table of contents. 22 const { minDepth = 2, items: headingItems = [] } = headings || {}; 23 24 const heading = useMemo( 25 () => headingItems.filter(({ depth }) => depth >= minDepth && depth <= 4), 26 [minDepth, headingItems] 27 ); 28 29 return ( 30 <div className={styles.wrapper}> 31 <dl> 32 {Object.entries(items) 33 .filter(([, value]) => !!value) 34 .map(([key, value]) => ( 35 <Fragment key={key}> 36 <dt>{t(key)}</dt> 37 <dd>{value}</dd> 38 </Fragment> 39 ))} 40 41 {heading.length > 0 && ( 42 <> 43 <dt>{t('components.metabar.tableOfContents')}</dt> 44 <dd> 45 <ol> 46 {heading.map(head => ( 47 <li key={head.value}> 48 <Link href={`#${head?.data?.id}`}>{head.value}</Link> 49 </li> 50 ))} 51 </ol> 52 </dd> 53 </> 54 )} 55 </dl> 56 </div> 57 ); 58}; 59 60export default MetaBar;