@@ -10,6 +10,7 @@ import {
1010 buildDocTree ,
1111 collectDemoFiles ,
1212 collectDocFiles ,
13+ collectMigrationDocFiles ,
1314 ensureGitignoreEntry ,
1415 generateHerouiMdIndex ,
1516 getHerouiVersions ,
@@ -25,6 +26,13 @@ import {compareVersions} from 'src/scripts/helpers';
2526
2627const DOCS_DIR_NAME = '.heroui-docs' ;
2728
29+ function formatSelectionText ( selection : DocSelection ) : string {
30+ if ( selection === 'react' ) return 'HeroUI React v3' ;
31+ if ( selection === 'native' ) return 'HeroUI Native' ;
32+
33+ return 'HeroUI Migration (v2→v3)' ;
34+ }
35+
2836function formatSize ( bytes : number ) : string {
2937 if ( bytes < 1024 ) return `${ bytes } B` ;
3038 const kb = bytes / 1024 ;
@@ -84,7 +92,7 @@ function validateRequirements(cwd: string, selection: DocSelection): ValidationR
8492 }
8593
8694 // For React docs: Check React >= 19.0.0
87- if ( selection === 'react' || selection === 'both' ) {
95+ if ( selection === 'react' ) {
8896 const reactVersion = allDeps . react ;
8997
9098 if ( reactVersion ) {
@@ -172,19 +180,23 @@ export async function docsAction(options: DocsOptions) {
172180 try {
173181 // Mode logic:
174182 // 1. No flags → autodetect package, prompt only if neither found (or if both found)
175- // 2. Library flags (--react, --native) → use that selection, prompt for output file if --output not provided
183+ // 2. Library flags (--react, --native, --migration ) → use that selection, prompt for output file if --output not provided
176184 // 3. --output alone → autodetect package, use provided output file
177185
178186 let selection : DocSelection ;
179187 let outputFiles : string [ ] | undefined ;
180188
181- // Determine selection from flags
182- if ( options . react && options . native ) {
183- selection = 'both' ;
184- } else if ( options . react ) {
185- selection = 'react' ;
186- } else if ( options . native ) {
187- selection = 'native' ;
189+ // Determine selection from flags (only one library at a time)
190+ const flagCount = [ options . react , options . native , options . migration ] . filter ( Boolean ) . length ;
191+
192+ if ( flagCount > 1 ) {
193+ throw new ValidationError (
194+ 'Only one library option is supported at a time. Use --react, --native, or --migration (not in combination).'
195+ ) ;
196+ }
197+
198+ if ( options . react || options . native || options . migration ) {
199+ selection = options . migration ? 'migration' : options . native ? 'native' : 'react' ;
188200 } else {
189201 // Autodetect installed packages
190202 const { hasNative, hasReact} = detectInstalledPackages ( cwd ) ;
@@ -194,18 +206,21 @@ export async function docsAction(options: DocsOptions) {
194206 if ( options . output ) {
195207 selection = await promptForLibrarySelection ( false ) ;
196208 } else {
197- const promptedOptions = await promptForOptions ( ) ;
209+ const promptedOptions = await promptForOptions ( false ) ;
198210
199211 selection = promptedOptions . selection ;
200212 outputFiles = promptedOptions . targetFiles ;
201213 }
202214 } else if ( hasReact ) {
215+ // Only React found - use it automatically
203216 selection = 'react' ;
204217 Logger . log ( chalk . dim ( 'Detected @heroui/react, using HeroUI React v3 docs' ) ) ;
205218 } else if ( hasNative ) {
219+ // Only Native found - use it automatically
206220 selection = 'native' ;
207221 Logger . log ( chalk . dim ( 'Detected heroui-native, using HeroUI Native docs' ) ) ;
208222 } else {
223+ // Neither found - prompt for selection with warning
209224 if ( options . output ) {
210225 selection = await promptForLibrarySelection ( true ) ;
211226 } else {
@@ -242,12 +257,7 @@ export async function docsAction(options: DocsOptions) {
242257
243258 const docsPath = path . join ( cwd , DOCS_DIR_NAME ) ;
244259
245- const selectionText =
246- selection === 'both'
247- ? 'HeroUI React v3 and HeroUI Native'
248- : selection === 'react'
249- ? 'HeroUI React v3'
250- : 'HeroUI Native' ;
260+ const selectionText = formatSelectionText ( selection ) ;
251261
252262 Logger . log ( `\nDownloading ${ selectionText } documentation to ${ chalk . cyan ( DOCS_DIR_NAME ) } ...` ) ;
253263
@@ -265,9 +275,10 @@ export async function docsAction(options: DocsOptions) {
265275 // Collect and build trees for selected docs
266276 let reactSections : ReturnType < typeof buildDocTree > | undefined ;
267277 let nativeSections : ReturnType < typeof buildDocTree > | undefined ;
278+ let migrationSections : ReturnType < typeof buildDocTree > | undefined ;
268279 let reactDemoFiles : { relativePath : string } [ ] | undefined ;
269280
270- if ( selection === 'react' || selection === 'both' ) {
281+ if ( selection === 'react' ) {
271282 const reactDocsPath = path . join ( docsPath , 'react' ) ;
272283
273284 if ( fs . existsSync ( reactDocsPath ) ) {
@@ -276,15 +287,14 @@ export async function docsAction(options: DocsOptions) {
276287 reactSections = buildDocTree ( reactDocFiles ) ;
277288 }
278289
279- // Collect demo files
280290 const reactDemosPath = path . join ( docsPath , 'react' , 'demos' ) ;
281291
282292 if ( fs . existsSync ( reactDemosPath ) ) {
283293 reactDemoFiles = collectDemoFiles ( reactDemosPath ) ;
284294 }
285295 }
286296
287- if ( selection === 'native' || selection === 'both' ) {
297+ if ( selection === 'native' ) {
288298 const nativeDocsPath = path . join ( docsPath , 'native' ) ;
289299
290300 if ( fs . existsSync ( nativeDocsPath ) ) {
@@ -294,10 +304,20 @@ export async function docsAction(options: DocsOptions) {
294304 }
295305 }
296306
297- const reactDocsLinkPath =
298- selection === 'react' || selection === 'both' ? `./${ DOCS_DIR_NAME } /react` : undefined ;
299- const nativeDocsLinkPath =
300- selection === 'native' || selection === 'both' ? `./${ DOCS_DIR_NAME } /native` : undefined ;
307+ if ( selection === 'migration' ) {
308+ const migrationDocsPath = path . join ( docsPath , 'migration' ) ;
309+
310+ if ( fs . existsSync ( migrationDocsPath ) ) {
311+ const migrationDocFiles = collectMigrationDocFiles ( migrationDocsPath ) ;
312+
313+ migrationSections = buildDocTree ( migrationDocFiles ) ;
314+ }
315+ }
316+
317+ const reactDocsLinkPath = selection === 'react' ? `./${ DOCS_DIR_NAME } /react` : undefined ;
318+ const nativeDocsLinkPath = selection === 'native' ? `./${ DOCS_DIR_NAME } /native` : undefined ;
319+ const migrationDocsLinkPath =
320+ selection === 'migration' ? `./${ DOCS_DIR_NAME } /migration` : undefined ;
301321
302322 // Generate index content once (reused for all output files)
303323 const indexData : Parameters < typeof generateHerouiMdIndex > [ 0 ] = {
@@ -307,19 +327,19 @@ export async function docsAction(options: DocsOptions) {
307327
308328 if ( nativeDocsLinkPath ) indexData . nativeDocsPath = nativeDocsLinkPath ;
309329 if ( nativeSections ) indexData . nativeSections = nativeSections ;
330+ if ( migrationDocsLinkPath ) indexData . migrationDocsPath = migrationDocsLinkPath ;
331+ if ( migrationSections ) indexData . migrationSections = migrationSections ;
310332 if ( reactDocsLinkPath ) indexData . reactDocsPath = reactDocsLinkPath ;
311333 if ( reactSections ) indexData . reactSections = reactSections ;
312334 if ( reactDemoFiles ) indexData . reactDemoFiles = reactDemoFiles ;
313335
314- // Generate separate index content for React and Native
336+ // Generate index content for the selected library only
315337 const reactIndexContent =
316- selection === 'react' || selection === 'both'
317- ? generateHerouiMdIndex ( indexData , 'react' )
318- : undefined ;
338+ selection === 'react' ? generateHerouiMdIndex ( indexData , 'react' ) : undefined ;
319339 const nativeIndexContent =
320- selection === 'native' || selection === 'both'
321- ? generateHerouiMdIndex ( indexData , 'native' )
322- : undefined ;
340+ selection === 'native' ? generateHerouiMdIndex ( indexData , 'native' ) : undefined ;
341+ const migrationIndexContent =
342+ selection === 'migration' ? generateHerouiMdIndex ( indexData , 'migration' ) : undefined ;
323343
324344 // Write to all output files
325345 const gitignoreResult = ensureGitignoreEntry ( cwd ) ;
@@ -336,7 +356,12 @@ export async function docsAction(options: DocsOptions) {
336356 isNewFile = false ;
337357 }
338358
339- const newContent = injectIntoClaudeMd ( existingContent , reactIndexContent , nativeIndexContent ) ;
359+ const newContent = injectIntoClaudeMd (
360+ existingContent ,
361+ reactIndexContent ,
362+ nativeIndexContent ,
363+ migrationIndexContent
364+ ) ;
340365
341366 fs . writeFileSync ( filePath , newContent , 'utf-8' ) ;
342367
@@ -359,7 +384,7 @@ export async function docsAction(options: DocsOptions) {
359384 Logger . log ( chalk . cyan ( '📚 What was installed:' ) ) ;
360385 Logger . log ( ` • Documentation files downloaded to ${ chalk . bold ( `.${ DOCS_DIR_NAME } /` ) } ` ) ;
361386 Logger . log ( ` • Index generated in ${ chalk . bold ( outputFiles . join ( ', ' ) ) } ` ) ;
362- if ( selection === 'react' || selection === 'both' ) {
387+ if ( selection === 'react' ) {
363388 Logger . log ( ` • Demo files included for React code examples` ) ;
364389 }
365390 Logger . newLine ( ) ;
@@ -405,7 +430,7 @@ async function promptForLibrarySelection(neitherFound: boolean = false): Promise
405430 const selection = await getSelect ( 'Select docs to include' , [
406431 { title : 'HeroUI React v3' , value : 'react' } ,
407432 { title : 'HeroUI Native' , value : 'native' } ,
408- { title : 'Both ' , value : 'both ' }
433+ { title : 'HeroUI Migration (v2→v3) ' , value : 'migration ' }
409434 ] ) ;
410435
411436 if ( selection === undefined ) {
0 commit comments