@seqera/docusaurus-theme-seqera 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,5 +3,8 @@ interface VersionSwitcherProps {
3
3
  isOpen: boolean;
4
4
  setIsOpen: Dispatch<SetStateAction<boolean>>;
5
5
  }
6
+ /**
7
+ * Main VersionSwitcher component that detects active plugin and delegates to inner component
8
+ */
6
9
  declare const VersionSwitcher: React.FC<VersionSwitcherProps>;
7
10
  export default VersionSwitcher;
@@ -1,38 +1,52 @@
1
- import React, {useState, useRef, useEffect} from 'react';
1
+ import React, {useRef, useEffect} from 'react';
2
2
  import {
3
3
  useVersions,
4
4
  useDocsVersion,
5
5
  useDocsPreferredVersion,
6
+ useActiveDocContext,
6
7
  } from '@docusaurus/plugin-content-docs/client';
7
- import {usePluginData} from '@docusaurus/useGlobalData';
8
+ import {useAllPluginInstancesData} from '@docusaurus/useGlobalData';
8
9
  import {useLocation} from '@docusaurus/router';
9
10
  import Link from '@docusaurus/Link';
10
- const VersionSwitcher = ({isOpen, setIsOpen}) => {
11
- const dropdownRef = useRef(null);
11
+ /**
12
+ * Detects which docs plugin is active based on the current pathname
13
+ */
14
+ function useActiveDocsPlugin() {
12
15
  const location = useLocation();
13
- // check if the plugin exists first
14
- let pluginData;
15
- try {
16
- pluginData = usePluginData(
17
- 'docusaurus-plugin-content-docs',
18
- 'platform-enterprise',
19
- );
20
- } catch (e) {
21
- return null;
16
+ const allDocsData = useAllPluginInstancesData(
17
+ 'docusaurus-plugin-content-docs',
18
+ );
19
+ // Find the plugin whose path matches the current pathname
20
+ for (const [pluginId, pluginData] of Object.entries(allDocsData)) {
21
+ if (pluginData?.path && location.pathname.startsWith(pluginData.path)) {
22
+ return pluginId;
23
+ }
22
24
  }
23
- const {savePreferredVersionName} = useDocsPreferredVersion(
24
- 'platform-enterprise',
25
+ return null;
26
+ }
27
+ /**
28
+ * Helper functions to get version documents
29
+ */
30
+ function getVersionMainDoc(version) {
31
+ return version.docs.find((doc) => doc.id === version.mainDocId);
32
+ }
33
+ function getVersionTargetDoc(version, activeDocContext) {
34
+ // Try to link to the same doc in another version
35
+ // When not possible, fallback to the "main doc" of the version
36
+ return (
37
+ activeDocContext.alternateDocVersions[version.name] ??
38
+ getVersionMainDoc(version)
25
39
  );
26
- const versions = useVersions('platform-enterprise');
40
+ }
41
+ const VersionSwitcherInner = ({isOpen, setIsOpen, pluginId}) => {
42
+ const dropdownRef = useRef(null);
43
+ // Always call hooks unconditionally - this component only renders when pluginId exists
44
+ const versions = useVersions(pluginId);
45
+ const {savePreferredVersionName} = useDocsPreferredVersion(pluginId);
27
46
  const currentVersion = useDocsVersion();
28
- const [isEnterprisePage, setEnterprisePage] = useState(false);
29
- useEffect(() => {
30
- if (location.pathname.startsWith('/platform-enterprise')) {
31
- setEnterprisePage(true);
32
- } else {
33
- setEnterprisePage(false);
34
- }
35
- }, [location.pathname]);
47
+ const activeDocContext = useActiveDocContext(pluginId);
48
+ // Only show version switcher if there is at least 1 version
49
+ if (!versions || versions.length === 0) return null;
36
50
  useEffect(() => {
37
51
  const handleClickOutside = (event) => {
38
52
  if (dropdownRef.current?.contains(event.target)) return;
@@ -47,20 +61,9 @@ const VersionSwitcher = ({isOpen, setIsOpen}) => {
47
61
  function handleSelectVersion(version) {
48
62
  savePreferredVersionName(version);
49
63
  }
50
- if (typeof window === 'undefined') return null;
51
- if (!versions || versions.length === 0) return null;
52
- if (!isEnterprisePage) return null;
53
64
  const items = versions.filter(
54
65
  (version) => version.label !== currentVersion?.label,
55
66
  );
56
- let urlSuffix = '';
57
- if (
58
- currentVersion &&
59
- location.pathname.startsWith(`/platform-enterprise/${currentVersion.label}`)
60
- ) {
61
- const currentVersionPrefix = `/platform-enterprise/${currentVersion.label}`;
62
- urlSuffix = location.pathname.replace(currentVersionPrefix, '');
63
- }
64
67
  return (
65
68
  <div ref={dropdownRef} className="relative px-4">
66
69
  <div
@@ -89,23 +92,44 @@ const VersionSwitcher = ({isOpen, setIsOpen}) => {
89
92
 
90
93
  {isOpen && (
91
94
  <div className="absolute left-4 right-4 top-full -mt-0.5 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 border-t-gray-200 dark:border-t-gray-600 rounded-b-lg overflow-hidden z-50 transition-all duration-100">
92
- {items?.map((version) => (
93
- <div
94
- key={version.name}
95
- className="w-full"
96
- onClick={() => handleSelectVersion(version.name)}>
97
- <Link
98
- to={`${version.path}${urlSuffix}`}
99
- className="h-9 w-full flex items-center justify-between px-3 text-sm bg-transparent cursor-pointer text-gray-900 dark:text-white transition-colors hover:bg-gray-100 dark:hover:bg-gray-800 no-underline border-t border-gray-200 dark:border-gray-700 first:border-t-0">
100
- v{version.label}{' '}
101
- {version.label === versions[0]?.label ? '(current)' : ''}
102
- </Link>
103
- </div>
104
- ))}
95
+ {items?.map((version) => {
96
+ const targetDoc = getVersionTargetDoc(version, activeDocContext);
97
+ return (
98
+ <div
99
+ key={version.name}
100
+ className="w-full"
101
+ onClick={() => handleSelectVersion(version.name)}>
102
+ <Link
103
+ to={targetDoc.path}
104
+ className="h-9 w-full flex items-center justify-between px-3 text-sm bg-transparent cursor-pointer text-gray-900 dark:text-white transition-colors hover:bg-gray-100 dark:hover:bg-gray-800 no-underline border-t border-gray-200 dark:border-gray-700 first:border-t-0">
105
+ v{version.label}{' '}
106
+ {version.label === versions[0]?.label ? '(current)' : ''}
107
+ </Link>
108
+ </div>
109
+ );
110
+ })}
105
111
  </div>
106
112
  )}
107
113
  </div>
108
114
  </div>
109
115
  );
110
116
  };
117
+ /**
118
+ * Main VersionSwitcher component that detects active plugin and delegates to inner component
119
+ */
120
+ const VersionSwitcher = ({isOpen, setIsOpen}) => {
121
+ const activePluginId = useActiveDocsPlugin();
122
+ // SSR guard
123
+ if (typeof window === 'undefined') return null;
124
+ // No active docs plugin found
125
+ if (!activePluginId) return null;
126
+ // Render the inner component with the detected plugin ID
127
+ return (
128
+ <VersionSwitcherInner
129
+ isOpen={isOpen}
130
+ setIsOpen={setIsOpen}
131
+ pluginId={activePluginId}
132
+ />
133
+ );
134
+ };
111
135
  export default VersionSwitcher;
@@ -1,7 +1,6 @@
1
1
  import React, {useState} from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {useThemeConfig} from '@docusaurus/theme-common';
4
- import {useLocation} from '@docusaurus/router';
5
4
  import Logo from '@theme/Logo';
6
5
  import CollapseButton from '@theme/DocSidebar/Desktop/CollapseButton';
7
6
  import Content from '@theme/DocSidebar/Desktop/Content';
@@ -14,12 +13,7 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) {
14
13
  sidebar: {hideable},
15
14
  },
16
15
  } = useThemeConfig();
17
- const location = useLocation();
18
16
  const [isOpen, setIsOpen] = useState(false);
19
- // Check if URL contains /platform-enterprise
20
- const showVersionSwitcher = location.pathname.includes(
21
- '/platform-enterprise',
22
- );
23
17
  return (
24
18
  <div
25
19
  className={clsx(
@@ -29,9 +23,7 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}) {
29
23
  'h-full relative w-full',
30
24
  )}>
31
25
  {hideOnScroll && <Logo tabIndex={-1} className={styles.sidebarLogo} />}
32
- {showVersionSwitcher && (
33
- <VersionSwitcher isOpen={isOpen} setIsOpen={setIsOpen} />
34
- )}
26
+ <VersionSwitcher isOpen={isOpen} setIsOpen={setIsOpen} />
35
27
  <Content path={path} sidebar={sidebar} />
36
28
  {hideable && (
37
29
  <div className="absolute right-0 top-[3.75rem]">
@@ -33,3 +33,8 @@
33
33
  -webkit-box-orient: vertical;
34
34
  -webkit-line-clamp: 2;
35
35
  }
36
+
37
+ /* Sidebar alignment - match category items with link items indentation */
38
+ :global(.theme-doc-sidebar-item-category-level-2.menu__list-item) {
39
+ margin-left: 1rem !important;
40
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seqera/docusaurus-theme-seqera",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "Seqera docs theme for Docusaurus",
5
5
  "author": "Seqera docs team <education@seqera.io>",
6
6
  "license": "Apache-2.0",
@@ -3,8 +3,14 @@ import {
3
3
  useVersions,
4
4
  useDocsVersion,
5
5
  useDocsPreferredVersion,
6
+ useActiveDocContext,
6
7
  } from "@docusaurus/plugin-content-docs/client";
7
- import { usePluginData } from "@docusaurus/useGlobalData";
8
+ import type {
9
+ GlobalVersion,
10
+ GlobalDoc,
11
+ ActiveDocContext,
12
+ } from "@docusaurus/plugin-content-docs/client";
13
+ import { useAllPluginInstancesData } from "@docusaurus/useGlobalData";
8
14
  import { useLocation } from "@docusaurus/router";
9
15
  import Link from "@docusaurus/Link";
10
16
 
@@ -13,30 +19,66 @@ interface VersionSwitcherProps {
13
19
  setIsOpen: Dispatch<SetStateAction<boolean>>;
14
20
  }
15
21
 
16
- const VersionSwitcher: React.FC<VersionSwitcherProps> = ({ isOpen, setIsOpen }) => {
17
- const dropdownRef = useRef<HTMLDivElement>(null);
22
+ interface DocsPluginData {
23
+ path: string;
24
+ versions: any[];
25
+ [key: string]: any;
26
+ }
27
+
28
+ /**
29
+ * Detects which docs plugin is active based on the current pathname
30
+ */
31
+ function useActiveDocsPlugin(): string | null {
18
32
  const location = useLocation();
19
-
20
- // check if the plugin exists first
21
- let pluginData;
22
- try {
23
- pluginData = usePluginData('docusaurus-plugin-content-docs', 'platform-enterprise');
24
- } catch (e) {
25
- return null;
33
+ const allDocsData = useAllPluginInstancesData('docusaurus-plugin-content-docs') as Record<string, DocsPluginData>;
34
+
35
+ // Find the plugin whose path matches the current pathname
36
+ for (const [pluginId, pluginData] of Object.entries(allDocsData)) {
37
+ if (pluginData?.path && location.pathname.startsWith(pluginData.path)) {
38
+ return pluginId;
39
+ }
26
40
  }
27
41
 
28
- const { savePreferredVersionName } = useDocsPreferredVersion("platform-enterprise");
29
- const versions = useVersions("platform-enterprise");
42
+ return null;
43
+ }
44
+
45
+ /**
46
+ * Helper functions to get version documents
47
+ */
48
+ function getVersionMainDoc(version: GlobalVersion): GlobalDoc {
49
+ return version.docs.find((doc) => doc.id === version.mainDocId)!;
50
+ }
51
+
52
+ function getVersionTargetDoc(
53
+ version: GlobalVersion,
54
+ activeDocContext: ActiveDocContext,
55
+ ): GlobalDoc {
56
+ // Try to link to the same doc in another version
57
+ // When not possible, fallback to the "main doc" of the version
58
+ return (
59
+ activeDocContext.alternateDocVersions[version.name] ??
60
+ getVersionMainDoc(version)
61
+ );
62
+ }
63
+
64
+ /**
65
+ * Inner component that handles version switching for a specific plugin
66
+ */
67
+ interface VersionSwitcherInnerProps extends VersionSwitcherProps {
68
+ pluginId: string;
69
+ }
70
+
71
+ const VersionSwitcherInner: React.FC<VersionSwitcherInnerProps> = ({ isOpen, setIsOpen, pluginId }) => {
72
+ const dropdownRef = useRef<HTMLDivElement>(null);
73
+
74
+ // Always call hooks unconditionally - this component only renders when pluginId exists
75
+ const versions = useVersions(pluginId);
76
+ const { savePreferredVersionName } = useDocsPreferredVersion(pluginId);
30
77
  const currentVersion = useDocsVersion();
31
- const [isEnterprisePage, setEnterprisePage] = useState(false);
78
+ const activeDocContext = useActiveDocContext(pluginId);
32
79
 
33
- useEffect(() => {
34
- if (location.pathname.startsWith('/platform-enterprise')) {
35
- setEnterprisePage(true);
36
- } else {
37
- setEnterprisePage(false);
38
- }
39
- }, [location.pathname]);
80
+ // Only show version switcher if there is at least 1 version
81
+ if (!versions || versions.length === 0) return null;
40
82
 
41
83
  useEffect(() => {
42
84
  const handleClickOutside = (event: MouseEvent) => {
@@ -56,24 +98,10 @@ const VersionSwitcher: React.FC<VersionSwitcherProps> = ({ isOpen, setIsOpen })
56
98
  savePreferredVersionName(version);
57
99
  }
58
100
 
59
- if (typeof window === "undefined") return null;
60
- if (!versions || versions.length === 0) return null;
61
- if (!isEnterprisePage) return null;
62
-
63
101
  const items = versions.filter(
64
102
  (version) => version.label !== currentVersion?.label,
65
103
  );
66
104
 
67
- let urlSuffix = "";
68
-
69
- if (
70
- currentVersion &&
71
- location.pathname.startsWith(`/platform-enterprise/${currentVersion.label}`)
72
- ) {
73
- const currentVersionPrefix = `/platform-enterprise/${currentVersion.label}`;
74
- urlSuffix = location.pathname.replace(currentVersionPrefix, "");
75
- }
76
-
77
105
  return (
78
106
  <div ref={dropdownRef} className="relative px-4">
79
107
  <div className={`bg-white dark:bg-gray-900 rounded-lg border border-gray-300 dark:border-gray-700 overflow-hidden ${isOpen ? 'rounded-b-none' : ''}`}>
@@ -87,33 +115,36 @@ const VersionSwitcher: React.FC<VersionSwitcherProps> = ({ isOpen, setIsOpen })
87
115
  ? "(current)"
88
116
  : ""}
89
117
  </span>
90
- <svg
118
+ <svg
91
119
  className={`w-5 h-5 transition-transform duration-200 ${isOpen ? 'rotate-0' : '-rotate-90'}`}
92
- xmlns="http://www.w3.org/2000/svg"
120
+ xmlns="http://www.w3.org/2000/svg"
93
121
  viewBox="4 4 16 16"
94
122
  fill="currentColor"
95
123
  >
96
124
  <path d="M11.8152 13.1989L10.0167 11.1432C9.80447 10.9013 9.97697 10.5214 10.2991 10.5214H13.8961C13.9682 10.5214 14.0388 10.5421 14.0994 10.5811C14.16 10.6201 14.2081 10.6758 14.2379 10.7414C14.2677 10.8071 14.2779 10.8799 14.2674 10.9512C14.2569 11.0226 14.226 11.0893 14.1785 11.1435L12.38 13.1985C12.3448 13.2388 12.3014 13.2711 12.2527 13.2932C12.204 13.3153 12.1511 13.3268 12.0976 13.3268C12.0441 13.3268 11.9912 13.3153 11.9425 13.2932C11.8938 13.2711 11.8504 13.2388 11.8152 13.1985V13.1989Z" />
97
125
  </svg>
98
126
  </button>
99
-
127
+
100
128
  {isOpen && (
101
129
  <div className="absolute left-4 right-4 top-full -mt-0.5 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 border-t-gray-200 dark:border-t-gray-600 rounded-b-lg overflow-hidden z-50 transition-all duration-100">
102
- {items?.map((version) => (
103
- <div
104
- key={version.name}
105
- className="w-full"
106
- onClick={() => handleSelectVersion(version.name)}
107
- >
108
- <Link
109
- to={`${version.path}${urlSuffix}`}
110
- className="h-9 w-full flex items-center justify-between px-3 text-sm bg-transparent cursor-pointer text-gray-900 dark:text-white transition-colors hover:bg-gray-100 dark:hover:bg-gray-800 no-underline border-t border-gray-200 dark:border-gray-700 first:border-t-0"
130
+ {items?.map((version) => {
131
+ const targetDoc = getVersionTargetDoc(version, activeDocContext);
132
+ return (
133
+ <div
134
+ key={version.name}
135
+ className="w-full"
136
+ onClick={() => handleSelectVersion(version.name)}
111
137
  >
112
- v{version.label}{" "}
113
- {version.label === versions[0]?.label ? "(current)" : ""}
114
- </Link>
115
- </div>
116
- ))}
138
+ <Link
139
+ to={targetDoc.path}
140
+ className="h-9 w-full flex items-center justify-between px-3 text-sm bg-transparent cursor-pointer text-gray-900 dark:text-white transition-colors hover:bg-gray-100 dark:hover:bg-gray-800 no-underline border-t border-gray-200 dark:border-gray-700 first:border-t-0"
141
+ >
142
+ v{version.label}{" "}
143
+ {version.label === versions[0]?.label ? "(current)" : ""}
144
+ </Link>
145
+ </div>
146
+ );
147
+ })}
117
148
  </div>
118
149
  )}
119
150
  </div>
@@ -121,4 +152,20 @@ const VersionSwitcher: React.FC<VersionSwitcherProps> = ({ isOpen, setIsOpen })
121
152
  );
122
153
  };
123
154
 
155
+ /**
156
+ * Main VersionSwitcher component that detects active plugin and delegates to inner component
157
+ */
158
+ const VersionSwitcher: React.FC<VersionSwitcherProps> = ({ isOpen, setIsOpen }) => {
159
+ const activePluginId = useActiveDocsPlugin();
160
+
161
+ // SSR guard
162
+ if (typeof window === "undefined") return null;
163
+
164
+ // No active docs plugin found
165
+ if (!activePluginId) return null;
166
+
167
+ // Render the inner component with the detected plugin ID
168
+ return <VersionSwitcherInner isOpen={isOpen} setIsOpen={setIsOpen} pluginId={activePluginId} />;
169
+ };
170
+
124
171
  export default VersionSwitcher;
@@ -1,7 +1,6 @@
1
1
  import React, { useState } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {useThemeConfig} from '@docusaurus/theme-common';
4
- import {useLocation} from '@docusaurus/router';
5
4
  import Logo from '@theme/Logo';
6
5
  import CollapseButton from '@theme/DocSidebar/Desktop/CollapseButton';
7
6
  import Content from '@theme/DocSidebar/Desktop/Content';
@@ -17,12 +16,8 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}: Props) {
17
16
  },
18
17
  } = useThemeConfig();
19
18
 
20
- const location = useLocation();
21
19
  const [isOpen, setIsOpen] = useState(false);
22
20
 
23
- // Check if URL contains /platform-enterprise
24
- const showVersionSwitcher = location.pathname.includes('/platform-enterprise');
25
-
26
21
  return (
27
22
  <div
28
23
  className={clsx(
@@ -32,9 +27,7 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}: Props) {
32
27
  'h-full relative w-full'
33
28
  )}>
34
29
  {hideOnScroll && <Logo tabIndex={-1} className={styles.sidebarLogo} />}
35
- {showVersionSwitcher && (
36
- <VersionSwitcher isOpen={isOpen} setIsOpen={setIsOpen} />
37
- )}
30
+ <VersionSwitcher isOpen={isOpen} setIsOpen={setIsOpen} />
38
31
  <Content path={path} sidebar={sidebar} />
39
32
  {hideable && <div className="absolute right-0 top-[3.75rem]"><CollapseButton onClick={onCollapse} /></div>}
40
33
  </div>
@@ -33,3 +33,8 @@
33
33
  -webkit-box-orient: vertical;
34
34
  -webkit-line-clamp: 2;
35
35
  }
36
+
37
+ /* Sidebar alignment - match category items with link items indentation */
38
+ :global(.theme-doc-sidebar-item-category-level-2.menu__list-item) {
39
+ margin-left: 1rem !important;
40
+ }
@@ -51,6 +51,7 @@ declare module '@seqera/docusaurus-theme-seqera' {
51
51
  footer: {
52
52
  socialLinks?: SocialLink[];
53
53
  };
54
+ docs?: {};
54
55
  };
55
56
  };
56
57