/ docs / src / components / NavbarItems / VersionSelector.tsx
VersionSelector.tsx
 1  import React, { useState, useEffect } from 'react';
 2  import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
 3  import BrowserOnly from '@docusaurus/BrowserOnly';
 4  import { LinkLikeNavbarItemProps } from '@theme/NavbarItem';
 5  
 6  interface VersionSelectorProps {
 7    mobile?: boolean;
 8    position?: 'left' | 'right';
 9    label?: string;
10    [key: string]: any;
11  }
12  
13  function getLabel(currentVersion: string, versions: string[]): string {
14    if (currentVersion === 'latest' && versions.length > 0) {
15      // version list is sorted in descending order, so the first one is the latest
16      return `Version: ${versions[0]} (latest)`;
17    }
18  
19    return `Version: ${currentVersion}`;
20  }
21  
22  function VersionSelectorImpl({ mobile, label = 'Version', ...props }: VersionSelectorProps): JSX.Element {
23    const [versions, setVersions] = useState<string[]>([]);
24    const [loading, setLoading] = useState(true);
25    const versionsUrl = window.location.origin + '/docs/versions.json';
26  
27    // Determine current version from URL or default to latest
28    const docPath = window.location.pathname;
29    const currentVersion = docPath.match(/^\/docs\/([a-zA-Z0-9.]+)/)?.[1];
30  
31    const versionItems: LinkLikeNavbarItemProps[] = versions?.map((version) => ({
32      type: 'default',
33      label: version,
34      to: window.location.origin + `/docs/${version}/`,
35      target: '_self',
36    }));
37  
38    useEffect(() => {
39      const fetchVersions = async () => {
40        try {
41          const response = await fetch(versionsUrl);
42          const data = await response.json();
43          if (data['versions'] != null) {
44            setVersions(data['versions']);
45          }
46        } catch (error) {
47          // do nothing, this can happen in dev where the versions.json file is not available
48        } finally {
49          setLoading(false);
50        }
51      };
52  
53      fetchVersions();
54    }, [versionsUrl]);
55  
56    if (loading || versions == null || versions.length === 0) {
57      return null;
58    }
59  
60    return (
61      <DropdownNavbarItem {...props} mobile={mobile} label={getLabel(currentVersion, versions)} items={versionItems} />
62    );
63  }
64  
65  export default function VersionSelector(props: VersionSelectorProps): JSX.Element {
66    return <BrowserOnly>{() => <VersionSelectorImpl {...props} />}</BrowserOnly>;
67  }