77 Check ,
88 ChevronDown ,
99 Download ,
10+ FlaskConical ,
1011 Loader2 ,
1112 Play ,
1213 Plus ,
@@ -20,6 +21,7 @@ import { nanoid } from "nanoid";
2021import { useRouter } from "next/navigation" ;
2122import { useEffect , useRef , useState } from "react" ;
2223import { toast } from "sonner" ;
24+ import { Alert , AlertDescription , AlertTitle } from "@/components/ui/alert" ;
2325import {
2426 AlertDialog ,
2527 AlertDialogAction ,
@@ -450,6 +452,7 @@ function useWorkflowState() {
450452
451453 const [ isDownloading , setIsDownloading ] = useState ( false ) ;
452454 const [ showCodeDialog , setShowCodeDialog ] = useState ( false ) ;
455+ const [ showExportDialog , setShowExportDialog ] = useState ( false ) ;
453456 const [ generatedCode , _setGeneratedCode ] = useState < string > ( "" ) ;
454457 const [ allWorkflows , setAllWorkflows ] = useState <
455458 Array < {
@@ -509,6 +512,8 @@ function useWorkflowState() {
509512 setIsDownloading,
510513 showCodeDialog,
511514 setShowCodeDialog,
515+ showExportDialog,
516+ setShowExportDialog,
512517 generatedCode,
513518 allWorkflows,
514519 setAllWorkflows,
@@ -967,13 +972,13 @@ function ToolbarActions({
967972 { /* Save/Download - Mobile Vertical */ }
968973 < ButtonGroup className = "flex lg:hidden" orientation = "vertical" >
969974 < SaveButton handleSave = { actions . handleSave } state = { state } />
970- < DownloadButton handleDownload = { actions . handleDownload } state = { state } />
975+ < DownloadButton state = { state } />
971976 </ ButtonGroup >
972977
973978 { /* Save/Download - Desktop Horizontal */ }
974979 < ButtonGroup className = "hidden lg:flex" orientation = "horizontal" >
975980 < SaveButton handleSave = { actions . handleSave } state = { state } />
976- < DownloadButton handleDownload = { actions . handleDownload } state = { state } />
981+ < DownloadButton state = { state } />
977982 </ ButtonGroup >
978983
979984 < RunButtonGroup actions = { actions } state = { state } />
@@ -1015,10 +1020,8 @@ function SaveButton({
10151020// Download Button Component
10161021function DownloadButton ( {
10171022 state,
1018- handleDownload,
10191023} : {
10201024 state : ReturnType < typeof useWorkflowState > ;
1021- handleDownload : ( ) => Promise < void > ;
10221025} ) {
10231026 return (
10241027 < Button
@@ -1029,12 +1032,12 @@ function DownloadButton({
10291032 state . isGenerating ||
10301033 ! state . currentWorkflowId
10311034 }
1032- onClick = { handleDownload }
1035+ onClick = { ( ) => state . setShowExportDialog ( true ) }
10331036 size = "icon"
10341037 title = {
10351038 state . isDownloading
10361039 ? "Preparing download..."
1037- : "Download workflow files "
1040+ : "Export workflow as code "
10381041 }
10391042 variant = "secondary"
10401043 >
@@ -1375,6 +1378,76 @@ function WorkflowDialogsComponent({
13751378 </ AlertDialogContent >
13761379 </ AlertDialog >
13771380
1381+ < Dialog
1382+ onOpenChange = { state . setShowExportDialog }
1383+ open = { state . showExportDialog }
1384+ >
1385+ < DialogContent className = "sm:max-w-lg" >
1386+ < DialogHeader >
1387+ < DialogTitle className = "flex items-center gap-2" >
1388+ < Download className = "size-5" />
1389+ Export Workflow as Code
1390+ </ DialogTitle >
1391+ < DialogDescription >
1392+ Export your workflow as a standalone Next.js project that you can
1393+ run independently.
1394+ </ DialogDescription >
1395+ </ DialogHeader >
1396+ < div className = "space-y-4 py-2" >
1397+ < p className = "text-muted-foreground text-sm" >
1398+ This will generate a complete Next.js project containing your
1399+ workflow code. Once exported, you can run your workflow outside of
1400+ the Workflow Builder, deploy it to Vercel, or integrate it into
1401+ your existing applications.
1402+ </ p >
1403+ < Alert >
1404+ < FlaskConical className = "size-4" />
1405+ < AlertTitle > Experimental Feature</ AlertTitle >
1406+ < AlertDescription className = "block" >
1407+ This feature is experimental and may have limitations. If you
1408+ encounter any issues, please{ " " }
1409+ < a
1410+ className = "font-medium text-foreground underline underline-offset-4 hover:text-primary"
1411+ href = "https://github.com/vercel-labs/workflow-builder-template/issues"
1412+ rel = "noopener noreferrer"
1413+ target = "_blank"
1414+ >
1415+ report them on GitHub
1416+ </ a >
1417+ .
1418+ </ AlertDescription >
1419+ </ Alert >
1420+ </ div >
1421+ < DialogFooter >
1422+ < Button
1423+ onClick = { ( ) => state . setShowExportDialog ( false ) }
1424+ variant = "outline"
1425+ >
1426+ Cancel
1427+ </ Button >
1428+ < Button
1429+ disabled = { state . isDownloading }
1430+ onClick = { ( ) => {
1431+ state . setShowExportDialog ( false ) ;
1432+ actions . handleDownload ( ) ;
1433+ } }
1434+ >
1435+ { state . isDownloading ? (
1436+ < >
1437+ < Loader2 className = "mr-2 size-4 animate-spin" />
1438+ Exporting...
1439+ </ >
1440+ ) : (
1441+ < >
1442+ < Download className = "mr-2 size-4" />
1443+ Export Project
1444+ </ >
1445+ ) }
1446+ </ Button >
1447+ </ DialogFooter >
1448+ </ DialogContent >
1449+ </ Dialog >
1450+
13781451 < MissingIntegrationsDialog actions = { actions } />
13791452 </ >
13801453 ) ;
0 commit comments