11import type { SupportedIdl } from '@entities/idl' ;
22import { Button } from '@shared/ui/button' ;
3+ import {
4+ Dialog ,
5+ DialogClose ,
6+ DialogContent ,
7+ DialogDescription ,
8+ DialogFooter ,
9+ DialogHeader ,
10+ DialogTitle ,
11+ } from '@shared/ui/dialog' ;
312import { Input } from '@shared/ui/input' ;
413import { Label } from '@shared/ui/label' ;
514import { Switch } from '@shared/ui/switch' ;
6- import { useMemo , useState } from 'react' ;
7- import { Code , Download , Search } from 'react-feather' ;
15+ import { useMemo , useRef , useState } from 'react' ;
16+ import { AlertCircle , Code , Download , ExternalLink , Search } from 'react-feather' ;
817
918import { WalletProvider } from '@/app/providers/wallet-provider' ;
1019import { triggerDownload } from '@/app/shared/lib/triggerDownload' ;
1120
21+ import { Dropdown } from '../../../components/common/Dropdown' ;
22+ import { type IdlVariant } from '../model/use-idl-last-transaction-date' ;
1223import { IdlRenderer } from './IdlRenderer' ;
1324
1425export function IdlSection ( {
1526 idl,
1627 badge,
1728 programId,
29+ idlSource,
1830 searchStr,
1931 onSearchChange,
2032} : {
2133 idl : SupportedIdl ;
2234 badge : React . ReactNode ;
2335 programId : string ;
36+ idlSource : IdlVariant ;
2437 searchStr : string ;
2538 onSearchChange : ( str : string ) => void ;
2639} ) {
2740 const [ isExpanded , setIsExpanded ] = useState ( false ) ;
2841 const [ isRawIdlView , setIsRawIdlView ] = useState ( false ) ;
42+ const [ isCastawayDialogOpen , setIsCastawayDialogOpen ] = useState ( false ) ;
43+ const downloadDropdownRef = useRef < HTMLButtonElement > ( null ) ;
2944
3045 const idlBase64 = useMemo ( ( ) => {
3146 return Buffer . from ( JSON . stringify ( idl , null , 2 ) ) . toString ( 'base64' ) ;
3247 } , [ idl ] ) ;
48+ const castawayUrl = useMemo ( ( ) => {
49+ const params = new URLSearchParams ( { idlSource, program : programId } ) ;
50+ return `https://www.castaway.lol/?${ params . toString ( ) } ` ;
51+ } , [ idlSource , programId ] ) ;
52+ const downloadDropdownOptions = useMemo (
53+ ( ) => ( {
54+ popperConfig ( ) {
55+ return { strategy : 'fixed' as const } ;
56+ } ,
57+ } ) ,
58+ [ ] ,
59+ ) ;
3360
3461 const handleDownloadIdl = ( ) => triggerDownload ( idlBase64 , `${ programId } -idl.json` ) ;
62+ const handleOpenCastawayDialog = ( ) => setIsCastawayDialogOpen ( true ) ;
63+ const handleCastawayContinue = ( ) => {
64+ window . open ( castawayUrl , '_blank' , 'noopener,noreferrer' ) ;
65+ setIsCastawayDialogOpen ( false ) ;
66+ } ;
3567
3668 return (
3769 < >
@@ -58,10 +90,57 @@ export function IdlSection({
5890 </ div >
5991 ) }
6092 < div className = "e-flex e-items-center e-gap-2" >
61- < Button variant = "outline" size = "sm" onClick = { handleDownloadIdl } >
62- < Download size = { 12 } />
63- Download
64- </ Button >
93+ < Dropdown dropdownRef = { downloadDropdownRef } options = { downloadDropdownOptions } >
94+ < div className = "dropdown e-overflow-visible" >
95+ < Button
96+ variant = "outline"
97+ size = "sm"
98+ ref = { downloadDropdownRef }
99+ data-bs-toggle = "dropdown"
100+ type = "button"
101+ aria-label = "Download"
102+ >
103+ < Download size = { 12 } />
104+ Download
105+ </ Button >
106+ < div className = "dropdown-menu-end dropdown-menu e-z-10" >
107+ < div className = "d-flex e-flex-col" >
108+ < Button onClick = { handleDownloadIdl } > Download IDL</ Button >
109+ < Button onClick = { handleOpenCastawayDialog } > Generate SDK</ Button >
110+ </ div >
111+ </ div >
112+ </ div >
113+ </ Dropdown >
114+
115+ < Dialog open = { isCastawayDialogOpen } onOpenChange = { setIsCastawayDialogOpen } >
116+ < DialogContent >
117+ < DialogHeader >
118+ < DialogTitle className = "e-flex e-items-center e-gap-2" >
119+ < AlertCircle className = "e-text-destructive" size = { 16 } />
120+ Leaving Solana Explorer
121+ </ DialogTitle >
122+ </ DialogHeader >
123+ < div className = "e-space-y-2 e-pl-6" >
124+ < DialogDescription >
125+ You are now leaving Explorer and going to Castaway.
126+ </ DialogDescription >
127+ < DialogDescription className = "e-break-all e-font-mono e-text-xs" >
128+ { castawayUrl }
129+ </ DialogDescription >
130+ </ div >
131+ < DialogFooter >
132+ < DialogClose asChild >
133+ < Button variant = "outline" size = "sm" >
134+ Cancel
135+ </ Button >
136+ </ DialogClose >
137+ < Button variant = "default" size = "sm" onClick = { handleCastawayContinue } >
138+ Continue
139+ < ExternalLink size = { 12 } />
140+ </ Button >
141+ </ DialogFooter >
142+ </ DialogContent >
143+ </ Dialog >
65144
66145 < Button
67146 variant = { isRawIdlView ? 'accent' : 'outline' }
0 commit comments