UNPKG

@redocly/theme

Version:

Shared UI components lib

126 lines (117 loc) 3.62 kB
import type { ResolvedNavItem, Version } from '@redocly/config'; import type { Location } from 'react-router-dom'; import { type Locale, type TFunction } from '../types/l10n'; import { type ItemState } from '../types/sidebar'; import { MenuItemType } from '../constants/common'; import { getPathnameForLocale, withoutPathPrefix, withPathPrefix } from './urls'; const TRANSLATION_KEYS = { version: 'mobileMenu.version', }; export const mapNavbarItems = ( items: ResolvedNavItem[], defaultLocale: string, currentLocale: string, locales: Locale[], location: Location, ): ItemState[] => { return items.map( (navItem) => ({ ...navItem, ...(navItem.items && { items: mapNavbarItems(navItem.items, defaultLocale, currentLocale, locales, location), }), ...('link' in navItem && { link: navItem.link || '/' }), active: 'link' in navItem && isItemActive(navItem, defaultLocale, currentLocale, locales, location), hasActiveSubItem: !!navItem.items?.find((item) => isItemActive(item, defaultLocale, currentLocale, locales, location), ), }) as ItemState, ); }; export const isItemActive = ( item: ResolvedNavItem, defaultLocale: string, currentLocale: string, locales: Locale[], location: Location, ): boolean => { const pathHash = location.pathname + location.hash; const link = item.languageInsensitive ? item.link || '' : getPathnameForLocale(item.link || '/', defaultLocale, currentLocale, locales); return pathHash === withPathPrefix(link); }; export const buildLanguagesGroup = ( locales: Locale[], defaultLocale: string, currentLocale: string, ): ResolvedNavItem | undefined => { if (locales.length < 2) { return; } const locale = locales.find((l) => l.code === currentLocale); return { type: 'group', label: locale?.name || locale?.code, items: locales .filter((locale) => locale.code !== currentLocale) .map((locale) => { const newLangPathname = getPathnameForLocale( withoutPathPrefix(location.pathname), defaultLocale, locale.code, locales, ); const newUrlWithLanguage = `${newLangPathname}${location.search}${location.hash}`; return { type: 'link', label: locale.name || locale.code || '', link: newUrlWithLanguage, active: false, hasActiveSubItem: false, languageInsensitive: true, }; }), }; }; export const buildVersionSection = ( translate: TFunction, versions: Version[], activeVersion?: Version, ): ResolvedNavItem[] => { return [ { type: 'separator', label: translate(TRANSLATION_KEYS.version, 'Version'), }, { type: 'group', label: activeVersion?.label, items: versions .filter((version) => !version.active) .map((version) => { return { type: 'link', label: version.label, link: version.link, active: false, hasActiveSubItem: false, }; }), }, ]; }; export function getMenuItemType(item: ItemState): MenuItemType { if (item.type === MenuItemType.Separator) { return MenuItemType.Separator; } else if (item.menuStyle === 'drilldown') { return MenuItemType.DrillDown; } else if (item.items?.length || (item.type === MenuItemType.Group && item.items?.length)) { return MenuItemType.Group; } else if (item.httpVerb) { return MenuItemType.Operation; } else return MenuItemType.Default; }