forked from TanStack/tanstack.com
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPackageManagerTabs.tsx
More file actions
101 lines (90 loc) · 3.2 KB
/
PackageManagerTabs.tsx
File metadata and controls
101 lines (90 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { useLocalCurrentFramework } from '../FrameworkSelect'
import { useCurrentUserQuery } from '~/hooks/useCurrentUser'
import { useParams } from '@tanstack/react-router'
import { create } from 'zustand'
import { Tabs, type TabDefinition } from './Tabs'
import { CodeBlock } from './CodeBlock'
import type { Framework } from '~/libraries/types'
import {
getInstallCommand,
PACKAGE_MANAGERS,
type PackageManager,
type InstallMode,
} from '~/utils/markdown/installCommand'
// Use zustand for cross-component synchronization
// This ensures all PackageManagerTabs instances on the page stay in sync
const usePackageManagerStore = create<{
packageManager: PackageManager
setPackageManager: (pm: PackageManager) => void
}>((set) => ({
packageManager:
typeof document !== 'undefined'
? (localStorage.getItem('packageManager') as PackageManager) || 'npm'
: 'npm',
setPackageManager: (pm: PackageManager) => {
localStorage.setItem('packageManager', pm)
set({ packageManager: pm })
},
}))
type PackageManagerTabsProps = {
packagesByFramework: Record<string, string[][]>
mode: InstallMode
frameworks: Framework[]
}
export function PackageManagerTabs({
packagesByFramework,
mode,
}: PackageManagerTabsProps) {
const { packageManager: storedPackageManager, setPackageManager } =
usePackageManagerStore()
const { framework: paramsFramework } = useParams({ strict: false })
const localCurrentFramework = useLocalCurrentFramework()
const userQuery = useCurrentUserQuery()
const userFramework = userQuery.data?.lastUsedFramework
const actualFramework = (paramsFramework ||
userFramework ||
localCurrentFramework.currentFramework ||
'react') as Framework
const normalizedFramework = actualFramework.toLowerCase()
const fallbackFramework = Object.keys(packagesByFramework).find(
(framework) => packagesByFramework[framework]?.length,
)
const packageGroups =
packagesByFramework[normalizedFramework] ||
(fallbackFramework ? packagesByFramework[fallbackFramework] : undefined)
// Fall back to the first available framework so single-framework content still renders.
if (!packageGroups || packageGroups.length === 0) {
return null
}
// Use stored package manager if valid, otherwise default to first one
const selectedPackageManager = PACKAGE_MANAGERS.includes(storedPackageManager)
? storedPackageManager
: PACKAGE_MANAGERS[0]
// Generate tabs for each package manager
const tabs: TabDefinition[] = PACKAGE_MANAGERS.map((pm) => ({
slug: pm,
name: pm,
headers: [],
}))
// Generate children (command blocks) for each package manager
const children = PACKAGE_MANAGERS.map((pm) => {
const commands = getInstallCommand(pm, packageGroups, mode)
const commandText = commands.join('\n')
return (
<CodeBlock key={pm}>
<code className="language-bash">{commandText}</code>
</CodeBlock>
)
})
return (
<div className="package-manager-tabs">
<Tabs
tabs={tabs}
/* eslint-disable-next-line react/no-children-prop */
children={children}
activeSlug={selectedPackageManager}
onTabChange={(slug) => setPackageManager(slug as PackageManager)}
/>
</div>
)
}