jamdesk 1.1.110 → 1.1.111

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.1.110",
3
+ "version": "1.1.111",
4
4
  "description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
5
5
  "keywords": [
6
6
  "jamdesk",
@@ -156,7 +156,7 @@ function HttpCodeBlock({ method, url }: { method: string; url: string }) {
156
156
  </span>
157
157
  {/* Copy button - functionality added via client-side script */}
158
158
  <button
159
- className="http-copy-btn p-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] rounded-md transition-colors flex-shrink-0"
159
+ className="http-copy-btn cursor-pointer p-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] rounded-md transition-colors flex-shrink-0"
160
160
  title="Copy"
161
161
  aria-label="Copy"
162
162
  type="button"
@@ -4,12 +4,7 @@ import { useMemo } from 'react';
4
4
  import Link from 'next/link';
5
5
  import { usePathname } from 'next/navigation';
6
6
  // Icons use Font Awesome CSS classes for lightweight rendering
7
- import type {
8
- DocsConfig,
9
- GroupConfig,
10
- NavigationPage,
11
- TabsPosition,
12
- } from '@/lib/docs-types';
7
+ import type { DocsConfig, TabsPosition } from '@/lib/docs-types';
13
8
  import { resolveNavigation } from '@/lib/navigation-resolver';
14
9
  import { getIconClass } from '@/lib/icon-utils';
15
10
  import { getTheme } from '@/themes';
@@ -56,7 +51,7 @@ export function TabsNav({ config, className = '' }: TabsNavProps) {
56
51
  isActive: false,
57
52
  };
58
53
  }
59
-
54
+
60
55
  // For internal tabs, find first page to link to
61
56
  // We need to look into the tab's groups
62
57
  let firstPath: string | null = null;
@@ -86,52 +81,18 @@ export function TabsNav({ config, className = '' }: TabsNavProps) {
86
81
  firstPath = firstPage.page;
87
82
  }
88
83
  }
89
-
90
- // Check if this tab is active by seeing if current path matches any of its pages
91
- // Remove /docs/ prefix if present, then remove leading slash to match page paths in config
92
- const currentPath = pathname.replace(/^\/docs\/?/, '').replace(/^\//, '');
93
- let isActive = false;
94
-
95
- const checkPages = (pages: (NavigationPage | GroupConfig)[]): boolean => {
96
- for (const page of pages) {
97
- const pagePath =
98
- typeof page === 'string'
99
- ? page
100
- : 'page' in page
101
- ? page.page
102
- : 'group' in page
103
- ? page.group
104
- : undefined;
105
- if (pagePath && (pagePath === currentPath || currentPath.startsWith(pagePath + '/'))) {
106
- return true;
107
- }
108
- // Check nested groups
109
- if (typeof page !== 'string' && 'pages' in page && page.pages) {
110
- if (checkPages(page.pages)) return true;
111
- }
112
- }
113
- return false;
114
- };
115
-
116
- if (tab.groups) {
117
- for (const group of tab.groups) {
118
- if (group.pages && checkPages(group.pages)) {
119
- isActive = true;
120
- break;
121
- }
122
- }
123
- }
124
- if (!isActive && tab.pages) {
125
- isActive = checkPages(tab.pages);
126
- }
127
-
84
+
85
+ // Defer to navigation-resolver's findActiveTab single source of truth.
86
+ // Keeps multilingual path-stripping rules and nested-group recursion in one place.
87
+ const isActive = resolved.activeTab === resolvedTab.name;
88
+
128
89
  return {
129
90
  ...resolvedTab,
130
91
  path: firstPath ? `${linkPrefix}/${firstPath}` : '#',
131
92
  isActive,
132
93
  };
133
94
  });
134
- }, [configTabs, resolved.tabs, pathname, linkPrefix, effectiveTabsPosition]);
95
+ }, [configTabs, resolved.tabs, resolved.activeTab, linkPrefix, effectiveTabsPosition]);
135
96
 
136
97
  // TabsNav is only for 'top' position - when tabs should appear below header
137
98
  // When tabsPosition is 'left', tabs are rendered in the Sidebar instead
@@ -146,8 +107,10 @@ export function TabsNav({ config, className = '' }: TabsNavProps) {
146
107
  return (
147
108
  <nav className={`hidden lg:block ${className}`}>
148
109
  {/* flex-wrap so the row degrades to two lines instead of clipping when
149
- the project has many tabs and/or a narrow desktop viewport. */}
150
- <div className="flex flex-wrap items-center gap-x-2 gap-y-1 py-3" style={{ margin: '0 24px', borderBottom: '0.5px solid var(--color-border)' }}>
110
+ the project has many tabs and/or a narrow desktop viewport.
111
+ Left margin is 12px (not 24px) to offset the first tab's `px-3`
112
+ padding so the first tab icon aligns with the sidebar group icons. */}
113
+ <div className="flex flex-wrap items-center gap-x-2 gap-y-1 py-3" style={{ margin: '0 24px 0 12px', borderBottom: '0.5px solid var(--color-border)' }}>
151
114
  {tabsWithPaths.map((tab) => {
152
115
  if (tab.isExternal && tab.href) {
153
116
  return (