@@ -15,6 +15,7 @@ type OOBEStep =
1515 | 'docker-setup'
1616 | 'projects'
1717 | 'language-select'
18+ | 'binding-style'
1819 | 'template-select'
1920 | 'complete' ;
2021
@@ -45,6 +46,7 @@ function getWizardStage(step: OOBEStep): WizardStage {
4546 case 'projects' :
4647 return 'identity' ;
4748 case 'language-select' :
49+ case 'binding-style' :
4850 case 'template-select' :
4951 return 'templates' ;
5052 case 'complete' :
@@ -330,7 +332,7 @@ function CheckingPage() {
330332 animate = "animate"
331333 exit = "exit"
332334 transition = { { duration : 0.3 } }
333- className = "flex-1 flex flex-col items-center justify-start pt-[30 %]"
335+ className = "flex-1 flex flex-col items-center justify-start pt-[15 %]"
334336 >
335337 < motion . div
336338 className = "w-12 h-12 border-3 border-gray-300 dark:border-gray-600 border-t-red-500 rounded-full mb-6"
@@ -902,61 +904,145 @@ function LanguageSelectPage({
902904 animate = "animate"
903905 exit = "exit"
904906 transition = { { duration : 0.3 } }
905- className = "flex-1 flex flex-col"
907+ className = "flex-1 flex flex-col items-center justify-center "
906908 >
907- { /* Main content - centered */ }
908- < div className = "flex-1 flex flex-col items-center justify-center" >
909- < h2 className = "text-2xl font-semibold text-gray-900 dark:text-white mb-2 text-center" >
910- Language Preference
911- </ h2 >
912- < p className = "text-gray-500 dark:text-gray-400 mb-8 text-center max-w-md" >
913- Choose your preferred language for new projects
914- </ p >
909+ < h2 className = "text-2xl font-semibold text-gray-900 dark:text-white mb-2 text-center" >
910+ Language Preference
911+ </ h2 >
912+ < p className = "text-gray-500 dark:text-gray-400 mb-8 text-center max-w-md" >
913+ Choose your preferred language for new projects
914+ </ p >
915915
916- < div className = "flex gap-4" >
917- { /* JavaScript card */ }
918- < button
919- onClick = { ( ) => onSelect ( false ) }
920- className = { `w-40 h-48 rounded-xl p-5 flex flex-col items-center justify-center gap-3 transition-all border-2 ${
921- ! preferTypeScript
922- ? 'border-yellow-400 bg-yellow-400/10 shadow-lg shadow-yellow-400/20'
923- : 'border-white/10 bg-white/5 hover:bg-white/10'
924- } `}
925- >
926- < div className = "w-16 h-16 flex items-center justify-center" >
927- < img src = "/logos/javascript.svg" alt = "JavaScript" className = "w-14 h-14" />
928- </ div >
929- < span className = "text-lg font-semibold text-white" > JavaScript</ span >
930- < span className = "text-xs text-white/50" > Dynamic typing</ span >
931- </ button >
916+ < div className = "flex gap-4 mb-8 " >
917+ { /* JavaScript card */ }
918+ < button
919+ onClick = { ( ) => onSelect ( false ) }
920+ className = { `w-40 h-48 rounded-xl p-5 flex flex-col items-center justify-center gap-3 transition-all border-2 ${
921+ ! preferTypeScript
922+ ? 'border-yellow-400 bg-yellow-400/10 shadow-lg shadow-yellow-400/20'
923+ : 'border-white/10 bg-white/5 hover:bg-white/10'
924+ } `}
925+ >
926+ < div className = "w-16 h-16 flex items-center justify-center" >
927+ < img src = "/logos/javascript.svg" alt = "JavaScript" className = "w-14 h-14" />
928+ </ div >
929+ < span className = "text-lg font-semibold text-white" > JavaScript</ span >
930+ < span className = "text-xs text-white/50" > Dynamic typing</ span >
931+ </ button >
932932
933- { /* TypeScript card */ }
934- < button
935- onClick = { ( ) => onSelect ( true ) }
936- className = { `w-40 h-48 rounded-xl p-5 flex flex-col items-center justify-center gap-3 transition-all border-2 ${
937- preferTypeScript
938- ? 'border-blue-400 bg-blue-400/10 shadow-lg shadow-blue-400/20'
939- : 'border-white/10 bg-white/5 hover:bg-white/10'
940- } `}
941- >
942- < div className = "w-16 h-16 flex items-center justify-center" >
943- < img src = "/logos/typescript.svg" alt = "TypeScript" className = "w-14 h-14" />
944- </ div >
945- < span className = "text-lg font-semibold text-white" > TypeScript</ span >
946- < span className = "text-xs text-white/50" > Type safety</ span >
947- </ button >
948- </ div >
933+ { /* TypeScript card */ }
934+ < button
935+ onClick = { ( ) => onSelect ( true ) }
936+ className = { `w-40 h-48 rounded-xl p-5 flex flex-col items-center justify-center gap-3 transition-all border-2 ${
937+ preferTypeScript
938+ ? 'border-blue-400 bg-blue-400/10 shadow-lg shadow-blue-400/20'
939+ : 'border-white/10 bg-white/5 hover:bg-white/10'
940+ } `}
941+ >
942+ < div className = "w-16 h-16 flex items-center justify-center" >
943+ < img src = "/logos/typescript.svg" alt = "TypeScript" className = "w-14 h-14" />
944+ </ div >
945+ < span className = "text-lg font-semibold text-white" > TypeScript</ span >
946+ < span className = "text-xs text-white/50" > Type safety</ span >
947+ </ button >
949948 </ div >
950949
951- { /* Button area - sibling below main content */ }
952- < div className = "flex justify-center pb-6" >
950+ < button
951+ onClick = { onNext }
952+ className = "px-6 py-2.5 rounded-lg border border-red-500 text-red-600 dark:text-red-400 text-sm font-medium hover:bg-red-500/10 transition-colors"
953+ >
954+ Continue
955+ </ button >
956+ </ motion . div >
957+ ) ;
958+ }
959+
960+ // Binding Style Select Page - Classes vs Interfaces (TypeScript only)
961+ function BindingStylePage ( {
962+ useInterfaces,
963+ onSelect,
964+ onNext,
965+ } : {
966+ useInterfaces : boolean ;
967+ onSelect : ( useInterfaces : boolean ) => void ;
968+ onNext : ( ) => void ;
969+ } ) {
970+ return (
971+ < motion . div
972+ variants = { pageVariants }
973+ initial = "initial"
974+ animate = "animate"
975+ exit = "exit"
976+ transition = { { duration : 0.3 } }
977+ className = "flex-1 flex flex-col items-center justify-center px-4 overflow-hidden"
978+ >
979+ < h2 className = "text-2xl font-semibold text-gray-900 dark:text-white mb-2 text-center" >
980+ TypeScript Binding Style
981+ </ h2 >
982+ < p className = "text-gray-500 dark:text-gray-400 mb-6 text-center max-w-lg" >
983+ Choose how Go structs are represented in TypeScript
984+ </ p >
985+
986+ < div className = "flex gap-4 mb-8 max-w-full overflow-x-auto" >
987+ { /* Interfaces option */ }
953988 < button
954- onClick = { onNext }
955- className = "px-5 py-2 rounded-lg border border-red-500 text-red-600 dark:text-red-400 text-sm font-medium hover:bg-red-500/10 transition-colors"
989+ onClick = { ( ) => onSelect ( true ) }
990+ className = { `w-56 shrink-0 rounded-xl p-4 flex flex-col items-start gap-2 transition-all border-2 text-left ${
991+ useInterfaces
992+ ? 'border-blue-400 bg-blue-400/10 shadow-lg shadow-blue-400/20'
993+ : 'border-white/10 bg-white/5 hover:bg-white/10'
994+ } `}
956995 >
957- Continue
996+ < span className = "text-base font-semibold text-gray-900 dark:text-white" > Interfaces</ span >
997+ < pre className = "text-[10px] leading-tight text-gray-700 dark:text-white/70 font-mono bg-gray-100 dark:bg-black/30 p-2 rounded-lg w-full overflow-x-auto" >
998+ { `interface Person {
999+ name: string;
1000+ age: number;
1001+ }` }
1002+ </ pre >
1003+ < ul className = "text-[10px] text-gray-500 dark:text-white/50 space-y-0.5" >
1004+ < li > • Lightweight types</ li >
1005+ < li > • No runtime code</ li >
1006+ < li > • Simpler output</ li >
1007+ </ ul >
1008+ </ button >
1009+
1010+ { /* Classes option */ }
1011+ < button
1012+ onClick = { ( ) => onSelect ( false ) }
1013+ className = { `w-56 shrink-0 rounded-xl p-4 flex flex-col items-start gap-2 transition-all border-2 text-left ${
1014+ ! useInterfaces
1015+ ? 'border-purple-400 bg-purple-400/10 shadow-lg shadow-purple-400/20'
1016+ : 'border-white/10 bg-white/5 hover:bg-white/10'
1017+ } `}
1018+ >
1019+ < span className = "text-base font-semibold text-gray-900 dark:text-white" > Classes</ span >
1020+ < pre className = "text-[10px] leading-tight text-gray-700 dark:text-white/70 font-mono bg-gray-100 dark:bg-black/30 p-2 rounded-lg w-full overflow-x-auto" >
1021+ { `class Person {
1022+ name: string;
1023+ age: number;
1024+ constructor(src) {
1025+ Object.assign(this, src);
1026+ }
1027+ static createFrom(src) {
1028+ return new Person(src);
1029+ }
1030+ }` }
1031+ </ pre >
1032+ < ul className = "text-[10px] text-gray-500 dark:text-white/50 space-y-0.5" >
1033+ < li > • Factory methods</ li >
1034+ < li > • Default initialization</ li >
1035+ < li > • More verbose</ li >
1036+ </ ul >
9581037 </ button >
9591038 </ div >
1039+
1040+ < button
1041+ onClick = { onNext }
1042+ className = "px-6 py-2.5 rounded-lg border border-red-500 text-red-600 dark:text-red-400 text-sm font-medium hover:bg-red-500/10 transition-colors"
1043+ >
1044+ Continue
1045+ </ button >
9601046 </ motion . div >
9611047 ) ;
9621048}
@@ -1004,9 +1090,6 @@ function TemplateSelectPage({
10041090 </ button >
10051091 ) ) }
10061092 </ div >
1007- < p className = "text-xs text-white/40 mt-4 text-center" >
1008- This sets the default template for new projects
1009- </ p >
10101093 </ PageTemplate >
10111094 ) ;
10121095}
@@ -1182,13 +1265,15 @@ export default function App() {
11821265 defaultTemplate : 'vanilla' ,
11831266 copyrightTemplate : '(c) {year}, {company}' ,
11841267 descriptionTemplate : 'A {name} application' ,
1185- defaultVersion : '0.1.0'
1268+ defaultVersion : '0.1.0' ,
1269+ useInterfaces : true
11861270 }
11871271 } ) ;
11881272 const [ savingDefaults , setSavingDefaults ] = useState ( false ) ;
11891273 const [ backgroundDockerStarted , setBackgroundDockerStarted ] = useState ( false ) ;
11901274 const [ preferTypeScript , setPreferTypeScript ] = useState ( true ) ;
11911275 const [ selectedFramework , setSelectedFramework ] = useState ( 'vanilla' ) ;
1276+ const [ useInterfaces , setUseInterfaces ] = useState ( true ) ;
11921277 const [ theme , setTheme ] = useState < Theme > ( ( ) => {
11931278 if ( typeof window !== 'undefined' ) {
11941279 const saved = localStorage . getItem ( 'wails-setup-theme' ) ;
@@ -1275,6 +1360,7 @@ export default function App() {
12751360 // Load defaults and go to projects
12761361 const loadedDefaults = await getDefaults ( ) ;
12771362 setDefaults ( loadedDefaults ) ;
1363+ setUseInterfaces ( loadedDefaults . project ?. useInterfaces ?? true ) ;
12781364 setStep ( 'projects' ) ;
12791365 } ;
12801366
@@ -1307,12 +1393,14 @@ export default function App() {
13071393 // Load defaults and go to projects
13081394 const loadedDefaults = await getDefaults ( ) ;
13091395 setDefaults ( loadedDefaults ) ;
1396+ setUseInterfaces ( loadedDefaults . project ?. useInterfaces ?? true ) ;
13101397 setStep ( 'projects' ) ;
13111398 } ;
13121399
13131400 const handleDockerSkip = async ( ) => {
13141401 const loadedDefaults = await getDefaults ( ) ;
13151402 setDefaults ( loadedDefaults ) ;
1403+ setUseInterfaces ( loadedDefaults . project ?. useInterfaces ?? true ) ;
13161404 setStep ( 'projects' ) ;
13171405 } ;
13181406
@@ -1325,6 +1413,14 @@ export default function App() {
13251413 } ;
13261414
13271415 const handleLanguageSelectNext = ( ) => {
1416+ if ( preferTypeScript ) {
1417+ setStep ( 'binding-style' ) ;
1418+ } else {
1419+ setStep ( 'template-select' ) ;
1420+ }
1421+ } ;
1422+
1423+ const handleBindingStyleNext = ( ) => {
13281424 setStep ( 'template-select' ) ;
13291425 } ;
13301426
@@ -1336,12 +1432,13 @@ export default function App() {
13361432 ? 'vanilla-ts'
13371433 : selectedFramework ;
13381434
1339- // Update defaults with selected template
1435+ // Update defaults with selected template and binding style
13401436 const updatedDefaults = {
13411437 ...defaults ,
13421438 project : {
13431439 ...defaults . project ,
1344- defaultTemplate : templateName
1440+ defaultTemplate : templateName ,
1441+ useInterfaces : preferTypeScript ? useInterfaces : true , // Only relevant for TypeScript
13451442 }
13461443 } ;
13471444
@@ -1352,8 +1449,16 @@ export default function App() {
13521449 } ;
13531450
13541451 const handleTemplateSelectSkip = async ( ) => {
1452+ // Save defaults with binding style preference
1453+ const updatedDefaults = {
1454+ ...defaults ,
1455+ project : {
1456+ ...defaults . project ,
1457+ useInterfaces : preferTypeScript ? useInterfaces : true ,
1458+ }
1459+ } ;
13551460 setSavingDefaults ( true ) ;
1356- await saveDefaults ( defaults ) ;
1461+ await saveDefaults ( updatedDefaults ) ;
13571462 setSavingDefaults ( false ) ;
13581463 setStep ( 'complete' ) ;
13591464 } ;
@@ -1449,6 +1554,14 @@ export default function App() {
14491554 onNext = { handleLanguageSelectNext }
14501555 />
14511556 ) }
1557+ { step === 'binding-style' && (
1558+ < BindingStylePage
1559+ key = "binding-style"
1560+ useInterfaces = { useInterfaces }
1561+ onSelect = { setUseInterfaces }
1562+ onNext = { handleBindingStyleNext }
1563+ />
1564+ ) }
14521565 { step === 'template-select' && (
14531566 < TemplateSelectPage
14541567 key = "template-select"
0 commit comments