@@ -6,6 +6,7 @@ const props = defineProps<{
66 packageName: string
77 requestedVersion? : string | null
88 jsrInfo? : JsrPackageInfo | null
9+ readmeHtml? : string | null
910 typesPackageName? : string | null
1011 executableInfo? : { hasExecutable: boolean ; primaryCommand? : string } | null
1112 createPackageInfo? : { packageName: string } | null
@@ -28,6 +29,20 @@ function getInstallPartsForPM(pmId: PackageManagerId) {
2829 })
2930}
3031
32+ const devDependencySuggestion = computed (() =>
33+ getDevDependencySuggestion (props .packageName , props .readmeHtml ),
34+ )
35+
36+ function getDevInstallPartsForPM(pmId : PackageManagerId ) {
37+ return getInstallCommandParts ({
38+ packageName: props .packageName ,
39+ packageManager: pmId ,
40+ version: props .requestedVersion ,
41+ jsrInfo: props .jsrInfo ,
42+ dev: true ,
43+ })
44+ }
45+
3146// Generate run command parts for a specific package manager
3247function getRunPartsForPM(pmId : PackageManagerId , command ? : string ) {
3348 return getRunCommandParts ({
@@ -66,7 +81,7 @@ function getTypesInstallPartsForPM(pmId: PackageManagerId) {
6681 const pm = packageManagers .find (p => p .id === pmId )
6782 if (! pm ) return []
6883
69- const devFlag = pmId === ' bun ' ? ' -d ' : ' -D '
84+ const devFlag = getDevDependencyFlag ( pmId )
7085 const pkgSpec = pmId === ' deno' ? ` npm:${props .typesPackageName } ` : props .typesPackageName
7186
7287 return [pm .label , pm .action , devFlag , pkgSpec ]
@@ -93,6 +108,18 @@ const copyRunCommand = (command?: string) => copyRun(getFullRunCommand(command))
93108
94109const { copied : createCopied, copy : copyCreate } = useClipboard ({ copiedDuring: 2000 })
95110const copyCreateCommand = () => copyCreate (getFullCreateCommand ())
111+
112+ const { copied : devInstallCopied, copy : copyDevInstall } = useClipboard ({ copiedDuring: 2000 })
113+ const copyDevInstallCommand = () =>
114+ copyDevInstall (
115+ getInstallCommand ({
116+ packageName: props .packageName ,
117+ packageManager: selectedPM .value ,
118+ version: props .requestedVersion ,
119+ jsrInfo: props .jsrInfo ,
120+ dev: true ,
121+ }),
122+ )
96123 </script >
97124
98125<template >
@@ -131,6 +158,41 @@ const copyCreateCommand = () => copyCreate(getFullCreateCommand())
131158 </button >
132159 </div >
133160
161+ <!-- Suggested dev dependency install command -->
162+ <template v-if =" devDependencySuggestion .recommended " >
163+ <div class =" flex items-center gap-2 pt-1 select-none" >
164+ <span class =" text-fg-subtle font-mono text-sm"
165+ ># {{ $t('package.get_started.dev_dependency_hint') }}</span
166+ >
167+ </div >
168+ <div
169+ v-for =" pm in packageManagers"
170+ :key =" `install-dev-${pm.id}`"
171+ :data-pm-cmd =" pm.id"
172+ class =" flex items-center gap-2 group/devinstallcmd min-w-0"
173+ >
174+ <span class =" text-fg-subtle font-mono text-sm select-none shrink-0" >$</span >
175+ <code class =" font-mono text-sm min-w-0"
176+ ><span
177+ v-for =" (part, i) in getDevInstallPartsForPM(pm.id)"
178+ :key =" i"
179+ :class =" i === 0 ? 'text-fg' : 'text-fg-muted'"
180+ >{{ i > 0 ? ' ' : '' }}{{ part }}</span
181+ ></code
182+ >
183+ <button
184+ type =" button"
185+ class =" px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/devinstallcmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-accent/70 select-none"
186+ :aria-label =" $t('package.get_started.copy_dev_command')"
187+ @click.stop =" copyDevInstallCommand"
188+ >
189+ <span aria-live =" polite" >{{
190+ devInstallCopied ? $t('common.copied') : $t('common.copy')
191+ }}</span >
192+ </button >
193+ </div >
194+ </template >
195+
134196 <!-- @types package install - render all PM variants when types package exists -->
135197 <template v-if =" typesPackageName && showTypesInInstall " >
136198 <div
0 commit comments