@@ -498,6 +498,7 @@ function refreshConnectionList(): void {
498498 if ( connectionNames . length === 0 ) {
499499 // Welcome card with warm styling
500500 const welcomeCard = VStack ( 16 , [ ] ) ;
501+ stackSetDistribution ( welcomeCard , - 1 ) ; // GravityAreas — prevent children from expanding
501502 widgetSetBackgroundColor ( welcomeCard , sfR , sfG , sfB , 1.0 ) ;
502503 setCornerRadius ( welcomeCard , 14 ) ;
503504 setPadding ( welcomeCard , mobile ? 20 : 32 , mobile ? 16 : 36 , mobile ? 16 : 28 , mobile ? 16 : 36 ) ;
@@ -538,11 +539,13 @@ function refreshConnectionList(): void {
538539 widgetSetBackgroundColor ( ctaBtn , moR , moG , moB , 1.0 ) ;
539540 setCornerRadius ( ctaBtn , 8 ) ;
540541 setPadding ( ctaBtn , 12 , 20 , 12 , 20 ) ;
542+ const ctaRow = HStack ( 0 , [ ctaBtn , Spacer ( ) ] ) ;
543+ widgetSetHugging ( ctaRow , 750 ) ;
541544
542545 widgetAddChild ( welcomeCard , welcomeTitle ) ;
543546 widgetAddChild ( welcomeCard , welcomeHint ) ;
544547 widgetAddChild ( welcomeCard , pillGrid ) ;
545- widgetAddChild ( welcomeCard , ctaBtn ) ;
548+ widgetAddChild ( welcomeCard , ctaRow ) ;
546549
547550 // First-launch analytics notice
548551 if ( ! getState ( 'analyticsNoticeShown' ) ) {
@@ -557,6 +560,7 @@ function refreshConnectionList(): void {
557560
558561 widgetAddChild ( connListContainer , welcomeCard ) ;
559562 widgetMatchParentWidth ( welcomeCard ) ;
563+ widgetSetHugging ( welcomeCard , 750 ) ;
560564 return ;
561565 }
562566
@@ -818,6 +822,8 @@ refreshConnectionList();
818822// --- Hero banner (full-width via ScrollView Width alignment) ---
819823const heroLogo = ImageFile ( mobile ? 'assets/mango-app-icon-40.png' : 'assets/mango-app-icon-44.png' ) ;
820824heroLogo . setSize ( mobile ? 40 : 44 , mobile ? 40 : 44 ) ;
825+ widgetSetWidth ( heroLogo , mobile ? 40 : 44 ) ;
826+ widgetSetHeight ( heroLogo , mobile ? 40 : 44 ) ;
821827
822828const heroTitle = Text ( 'Mango' ) ;
823829textSetFontSize ( heroTitle , mobile ? 28 : 38 ) ;
@@ -861,6 +867,8 @@ widgetMatchParentWidth(formContainer);
861867
862868// All content in ScrollView — hero + body
863869const connContent = VStack ( 0 , [ heroBox , connBody ] ) ;
870+ stackSetDistribution ( connContent , - 1 ) ; // GravityAreas — children keep intrinsic height inside ScrollView
871+ stackSetDistribution ( connBody , - 1 ) ;
864872
865873const connectionScreen = ScrollView ( ) ;
866874scrollviewSetChild ( connectionScreen , connContent ) ;
@@ -869,6 +877,8 @@ widgetSetBackgroundColor(connectionScreen, bgR, bgG, bgB, 1.0);
869877// Force hero to fill full width
870878widgetMatchParentWidth ( heroBox ) ;
871879widgetMatchParentWidth ( connBody ) ;
880+ widgetSetHugging ( heroBox , 750 ) ;
881+ widgetSetHugging ( connBody , 750 ) ;
872882
873883// ============================================================
874884// BROWSER SCREEN
@@ -922,6 +932,8 @@ const disconnectBtn = makeDangerBtn(t('Disconnect'), async () => {
922932// Browser toolbar — logo + connection name + status
923933const browserLogo = ImageFile ( 'assets/mango-app-icon-24.png' ) ;
924934browserLogo . setSize ( 24 , 24 ) ;
935+ widgetSetWidth ( browserLogo , 24 ) ;
936+ widgetSetHeight ( browserLogo , 24 ) ;
925937
926938const browserTitle = Text ( 'Mango' ) ;
927939textSetFontSize ( browserTitle , 18 ) ;
@@ -1021,12 +1033,9 @@ async function showEditView(docJson: string): Promise<void> {
10211033 ed . setGutterFgColor ( tsR , tsG , tsB ) ;
10221034 ed . setCursorColor ( moR , moG , moB ) ;
10231035 ed . setSelectionColor ( moR , moG , moB , 0.2 ) ;
1024- // Wrap editor in a fixed-height container (embedded NSViews resist height constraints)
1025- const editorBox = VStack ( 0 , [ ] ) ;
1026- widgetSetHeight ( editorBox , 200 ) ;
1027- widgetAddChild ( editorBox , jsonEditor . widget ) ;
1028- widgetMatchParentWidth ( jsonEditor . widget ) ;
1029- widgetMatchParentHeight ( jsonEditor . widget ) ;
1036+ // Editor widget has fills_remaining=true (from embedNSView), so it naturally
1037+ // absorbs remaining space in the editCard VStack with Fill distribution.
1038+ // No wrapper needed — adding directly ensures it's the fill target.
10301039
10311040 const saveBtn = makePrimaryBtn ( t ( 'Save Changes' ) , async ( ) => {
10321041 showStatus ( t ( 'Saving...' ) , false ) ;
@@ -1039,6 +1048,7 @@ async function showEditView(docJson: string): Promise<void> {
10391048 const updateStr = '{"$set":' + compactJson + '}' ;
10401049 await updateDocument ( activeDbName , activeCollName , idFilter , updateStr ) ;
10411050 showStatus ( t ( 'Document saved' ) , false ) ;
1051+ saveState ( 'lastEditDoc' , '' ) ;
10421052 // Switch back to doc list
10431053 widgetSetHidden ( editContainer , 1 ) ;
10441054 widgetSetHidden ( browserBody , 0 ) ;
@@ -1054,13 +1064,15 @@ async function showEditView(docJson: string): Promise<void> {
10541064 } else {
10551065 showStatus ( t ( 'Delete failed' ) , true ) ;
10561066 }
1067+ saveState ( 'lastEditDoc' , '' ) ;
10571068 widgetSetHidden ( editContainer , 1 ) ;
10581069 widgetSetHidden ( browserBody , 0 ) ;
10591070 const result = await queryCollection ( activeDbName , activeCollName , lastQueryFilter ) ;
10601071 displayDocs ( result ) ;
10611072 } ) ;
10621073
10631074 const backBtn = makeGhostBtn ( t ( 'Back to results' ) , ( ) => {
1075+ saveState ( 'lastEditDoc' , '' ) ;
10641076 widgetSetHidden ( editContainer , 1 ) ;
10651077 widgetSetHidden ( browserBody , 0 ) ;
10661078 } ) ;
@@ -1070,17 +1082,17 @@ async function showEditView(docJson: string): Promise<void> {
10701082 widgetSetBackgroundColor ( editCard , sfR , sfG , sfB , 1.0 ) ;
10711083 setCornerRadius ( editCard , 12 ) ;
10721084 setPadding ( editCard , 16 , 20 , 16 , 20 ) ;
1085+ const buttonRow = HStack ( 8 , [ deleteBtn , Spacer ( ) , backBtn , saveBtn ] ) ;
10731086 widgetAddChild ( editCard , editHeader ) ;
10741087 widgetAddChild ( editCard , Divider ( ) ) ;
10751088 widgetAddChild ( editCard , fieldLabel ) ;
1076- widgetAddChild ( editCard , editorBox ) ;
1077- widgetAddChild ( editCard , HStack ( 8 , [ deleteBtn , Spacer ( ) , backBtn , saveBtn ] ) ) ;
1089+ widgetAddChild ( editCard , jsonEditor . widget ) ;
1090+ widgetAddChild ( editCard , buttonRow ) ;
10781091
1079- // editContainer is full-height (HStack .fill), so put card at top + spacer absorbs rest
1092+ // editContainer has Fill distribution — editCard fills remaining space
1093+ // (widgetSetHugging doesn't work inside function bodies due to Perry codegen bug)
10801094 widgetAddChild ( editContainer , editCard ) ;
1081- widgetMatchParentWidth ( editCard ) ; // fill the available width so buttons aren't clipped
1082- widgetSetHugging ( editCard , 750 ) ; // card stays compact vertically
1083- widgetAddChild ( editContainer , Spacer ( ) ) ;
1095+ widgetMatchParentWidth ( editCard ) ;
10841096}
10851097
10861098// --- Document list ---
@@ -1149,7 +1161,7 @@ function displayDocs(jsonStr: string): void {
11491161 // Header: _id + delete/edit buttons
11501162 const idLabel = makeMonoMuted ( idShort , 10 ) ;
11511163
1152- const editBtn = Button ( 'Edit' , async ( ) => { await showEditView ( docJsonStr ) ; } ) ;
1164+ const editBtn = Button ( 'Edit' , async ( ) => { saveState ( 'lastEditDoc' , docJsonStr ) ; await showEditView ( docJsonStr ) ; } ) ;
11531165 buttonSetBordered ( editBtn , 0 ) ;
11541166 buttonSetTextColor ( editBtn , moR , moG , moB , 1.0 ) ;
11551167
@@ -1683,6 +1695,12 @@ async function restoreLastSession(): Promise<void> {
16831695 textfieldSetString ( dbField , lastDb ) ;
16841696 textfieldSetString ( collField , lastColl ) ;
16851697 await runQuery ( lastDb , lastColl , '{}' ) ;
1698+
1699+ // Restore edit view if a document was being edited
1700+ const lastEditDoc = getState ( 'lastEditDoc' ) ;
1701+ if ( lastEditDoc ) {
1702+ await showEditView ( lastEditDoc ) ;
1703+ }
16861704 }
16871705}
16881706// --- Screenshot mode ---
0 commit comments