UI/Components/Menu/MenuScreenBuilder.cs

Fluent builder for a menu screen. Collects metadata (id, label, icon, subtitle, order, visibility) and a list of MenuWidget entries, and exposes WithXxx methods returning widget-specific builders or adding simple widgets. EndScreen packages a MenuScreen and adds it to the parent MenuBuilder.

namespace Sunless.Libraries.UI;

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;

// Generic screen builder. Layer 1 of the menu API. Every widget gets its own
// fluent builder returned by a WithXxx() — the builder configures the widget
// and EndXxx() returns to the parent screen so chains read top-to-bottom.
public class MenuScreenBuilder
{
	internal readonly MenuBuilder _parent;
	internal readonly string _id;
	internal readonly string _label;
	internal readonly string _icon;
	internal readonly List<MenuWidget> _widgets = new();
	internal int _order;
	internal bool _showInNav = true;
	internal Func<bool> _visible;
	internal string _subtitle;

	internal MenuScreenBuilder( MenuBuilder parent, string id, string label, string icon )
	{
		_parent = parent;
		_id = id;
		_label = label;
		_icon = icon;
	}

	public MenuScreenBuilder WithSubtitle( string subtitle ) { _subtitle = subtitle; return this; }
	public MenuScreenBuilder WithOrder( int order )          { _order = order; return this; }
	public MenuScreenBuilder HideFromNav()                   { _showInNav = false; return this; }
	public MenuScreenBuilder WhenVisible( Func<bool> v )     { _visible = v; return this; }

	internal void AddWidget( MenuWidget w ) => _widgets.Add( w );

	public MenuScreenBuilder WithSection( string label )
	{
		_widgets.Add( new MenuSectionWidget { Label = label } );
		return this;
	}

	public MenuScreenBuilder WithText( string text )
	{
		_widgets.Add( new MenuTextWidget { Text = text } );
		return this;
	}

	public MenuScreenBuilder WithComponent( RenderFragment content, string label = null, string hint = null )
	{
		_widgets.Add( new MenuComponentWidget { Label = label, Hint = hint, Content = content } );
		return this;
	}

	public MenuLinkBuilder         WithLink( string label, string icon = null )       => new( this, label, icon );
	public MenuToggleBuilder       WithToggle( string label )                          => new( this, label );
	public MenuRangeBuilder        WithRange( string label )                           => new( this, label );
	public MenuSegmentedBuilder    WithSegmented( string label, params string[] opts ) => new( this, label, opts );
	public MenuRadioBuilder        WithRadio( string label = null )                    => new( this, label );
	public MenuInfoBuilder         WithInfo( string label )                            => new( this, label );
	public MenuTextFieldBuilder    WithTextField( string label )                       => new( this, label );

	public MenuHeroCardBuilder     WithHeroCard()                                      => new( this );
	public MenuMapCardBuilder      WithMapCard()                                       => new( this );
	public MenuMapGridBuilder      WithMapGrid()                                       => new( this );
	public MenuTileGridBuilder     WithTileGrid()                                      => new( this );
	public MenuPlayerListBuilder   WithPlayerList()                                    => new( this );
	public MenuKeyBindingsBuilder  WithKeyBindings()                                   => new( this );
	public MenuPromptCardBuilder   WithPromptCard()                                    => new( this );

	public MenuActionRowBuilder    WithActionRow()                                     => new( this );

	public MenuBuilder EndScreen()
	{
		_parent.AddScreen( new MenuScreen
		{
			Id = _id,
			Label = _label,
			Icon = _icon,
			Subtitle = _subtitle,
			Order = _order,
			ShowInNav = _showInNav,
			Widgets = _widgets,
			VisibleWhen = _visible,
		} );
		return _parent;
	}
}