private/dialogs/New-DialogWindow.ps1

function New-DialogWindow {
    <#
    .SYNOPSIS
        Creates a standard themed dialog window with common boilerplate.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Title,

        [int]$Width = 420,

        [int]$MinWidth = 332,

        [int]$Height,

        [int]$MinHeight = 182,

        [int]$MaxHeight = 600,

        [ValidateSet('Height', 'Manual')]
        [string]$SizeToContent = 'Height',

        # CanResizeWithGrip is out of the set because WPF draws that grip 16px clear of the window, in the window shadow.
        # The grip built further down sits on the chrome instead, and CanResize keeps WS_THICKFRAME so the edges still drag.
        [ValidateSet('NoResize', 'CanResize')]
        [string]$ResizeMode = 'NoResize',

        [string]$AppIdSuffix = 'Dialog',

        [char]$OverlayGlyph,

        [string]$OverlayColor,

        [char]$TitleIcon,

        [object]$ThemeColors
    )

    # First PsUi UI in the process means no Application, so no control styles. Every text and password box draws without a border or a background.
    # Can't fix that by creating one, so it would outlive the dialog owning no windows, and the next New-UiWindow builds on its own STA thread and drops to messed up theming.
    $dialogNeedsOwnTheme = $null -eq [System.Windows.Application]::Current

    $colors = if ($ThemeColors) { $ThemeColors } else { Get-ThemeColors }
    $overlayColorFinal = if ($OverlayColor) { $OverlayColor } else { $colors.Accent }

    if (!$OverlayGlyph) { $OverlayGlyph = [PsUi.ModuleContext]::GetIcon('Info') }

    $window = [System.Windows.Window]@{
        Title                 = $Title
        Width                 = $Width + 32
        MinWidth              = $MinWidth
        MinHeight             = $MinHeight
        MaxHeight             = $MaxHeight + 32
        SizeToContent         = $SizeToContent
        WindowStartupLocation = 'CenterScreen'
        FontFamily            = [System.Windows.Media.FontFamily]::new('Segoe UI')
        Background            = [System.Windows.Media.Brushes]::Transparent
        Foreground            = ConvertTo-UiBrush $colors.ControlFg
        ResizeMode            = $ResizeMode
        WindowStyle           = 'None'
        AllowsTransparency    = $true
        Opacity               = 0
    }

    # Brushes and control styles go straight onto the window when there is no Application to hold them.
    if ($dialogNeedsOwnTheme) { [PsUi.ThemeEngine]::ApplyStandaloneTheme($window, $colors) }

    $null = Set-WindowOwner -Window $window

    [PsUi.WindowManager]::SetWindowAppId($window, "PsUi.$AppIdSuffix")

    # Only the PowerShell view passes one. Everything else sizes to its content.
    if ($Height -gt 0) { $window.Height = $Height }

    # Themed window icon for taskbar
    $dialogIcon = $null
    try {
        $dialogIcon = New-WindowIcon -Colors $colors
        if ($dialogIcon) { $window.Icon = $dialogIcon }
    }
    catch { Write-Debug "Window icon creation failed: $_" }

    # Overlay icon for taskbar
    $overlayIcon = $null
    try {
        $overlayIcon = New-TaskbarOverlayIcon -GlyphChar $OverlayGlyph -Color $overlayColorFinal
    }
    catch { Write-Debug "Overlay icon creation failed: $_" }

    # Both calls below reach for the window handle, and there is none until Loaded.
    $capturedWindow  = $window
    $capturedIcon    = $dialogIcon
    $capturedOverlay = $overlayIcon
    $capturedSuffix  = $AppIdSuffix
    $window.Add_Loaded({
        if ($capturedIcon) {
            [PsUi.WindowManager]::SetTaskbarIcon($capturedWindow, $capturedIcon)
        }
        if ($capturedOverlay) {
            [PsUi.WindowManager]::SetTaskbarOverlay($capturedWindow, $capturedOverlay, $capturedSuffix)
        }
    }.GetNewClosure())

    # Main border with shadow effect
    $mainBorder = [System.Windows.Controls.Border]@{
        Margin          = [System.Windows.Thickness]::new(16)
        BorderBrush     = ConvertTo-UiBrush $colors.Border
        BorderThickness = [System.Windows.Thickness]::new(1)
        Background      = ConvertTo-UiBrush $colors.WindowBg
    }

    $shadow = [System.Windows.Media.Effects.DropShadowEffect]@{
        BlurRadius  = 16
        ShadowDepth = 4
        Opacity     = 0.35
        Color       = [System.Windows.Media.Colors]::Black
        Direction   = 270
    }
    $mainBorder.Effect = $shadow
    $window.Content = $mainBorder

    # Main layout panel
    $mainPanel = [System.Windows.Controls.DockPanel]@{
        LastChildFill = $true
        Margin        = [System.Windows.Thickness]::new(0)
    }

    # Grid rather than DockPanel, so the grip can overlay the chrome's corner
    $chromeGrid = [System.Windows.Controls.Grid]::new()
    [void]$chromeGrid.Children.Add($mainPanel)
    $mainBorder.Child = $chromeGrid

    if ($ResizeMode -ne 'NoResize') {
        $resizeGrip = [System.Windows.Controls.Primitives.ResizeGrip]@{
            HorizontalAlignment = 'Right'
            VerticalAlignment   = 'Bottom'
            Cursor              = [System.Windows.Input.Cursors]::SizeNWSE
        }
        [void]$chromeGrid.Children.Add($resizeGrip)

        # The grip is 17px square, so where you press inside it changes the offset, the mousedown works out the real one.
        $gripGrab      = @{ X = 16; Y = 16 }
        $gripWindow    = $window
        $gripMinWidth  = $MinWidth
        $gripMinHeight = $MinHeight

        $resizeGrip.Add_MouseLeftButtonDown({
            param($sender, $eventArgs)
            # Turn it off first, or SizeToContent overrides every Height written during the drag.
            $gripWindow.SizeToContent = 'Manual'
            $downPos     = [System.Windows.Input.Mouse]::GetPosition($gripWindow)
            $gripGrab.X  = $gripWindow.ActualWidth  - $downPos.X
            $gripGrab.Y  = $gripWindow.ActualHeight - $downPos.Y
            $null = $sender.CaptureMouse()
            $eventArgs.Handled = $true
        }.GetNewClosure())

        $resizeGrip.Add_MouseMove({
            param($sender, $eventArgs)
            if (!$sender.IsMouseCaptured) { return }
            $mousePos          = [System.Windows.Input.Mouse]::GetPosition($gripWindow)
            $gripWindow.Width  = [Math]::Max($gripMinWidth,  $mousePos.X + $gripGrab.X)
            $gripWindow.Height = [Math]::Max($gripMinHeight, $mousePos.Y + $gripGrab.Y)
            $eventArgs.Handled = $true
        }.GetNewClosure())

        $resizeGrip.Add_MouseLeftButtonUp({
            param($sender, $eventArgs)
            $sender.ReleaseMouseCapture()
            $eventArgs.Handled = $true
        })
    }

    # Title bar
    $titleBar = [System.Windows.Controls.Border]@{
        Background = ConvertTo-UiBrush $colors.HeaderBackground
        Height     = 36
        Padding    = [System.Windows.Thickness]::new(12, 8, 12, 8)
    }
    [System.Windows.Controls.DockPanel]::SetDock($titleBar, 'Top')

    # Title bar content - optional icon + text
    if ($TitleIcon) {
        $titleStack = [System.Windows.Controls.StackPanel]@{
            Orientation       = 'Horizontal'
            VerticalAlignment = 'Center'
        }

        $titleIconBlock = [System.Windows.Controls.TextBlock]@{
            Text              = $TitleIcon
            FontFamily        = [PsUi.ModuleContext]::ActiveIconFontFamily
            FontSize          = 14
            Foreground        = ConvertTo-UiBrush $colors.HeaderForeground
            VerticalAlignment = 'Center'
            Margin            = [System.Windows.Thickness]::new(0, 0, 8, 0)
        }
        [void]$titleStack.Children.Add($titleIconBlock)

        $titleText = [System.Windows.Controls.TextBlock]@{
            Text              = $Title
            FontSize          = 14
            FontWeight        = [System.Windows.FontWeights]::SemiBold
            Foreground        = ConvertTo-UiBrush $colors.HeaderForeground
            VerticalAlignment = 'Center'
        }
        [void]$titleStack.Children.Add($titleText)

        $titleBar.Child = $titleStack
    }
    else {
        $titleText = [System.Windows.Controls.TextBlock]@{
            Text              = $Title
            FontSize          = 14
            FontWeight        = [System.Windows.FontWeights]::SemiBold
            Foreground        = ConvertTo-UiBrush $colors.HeaderForeground
            VerticalAlignment = 'Center'
        }
        $titleBar.Child = $titleText
    }

    [void]$mainPanel.Children.Add($titleBar)

    $titleBar.Add_MouseLeftButtonDown({ $capturedWindow.DragMove() }.GetNewClosure())

    # Where each dialog puts its own controls
    $contentPanel = [System.Windows.Controls.DockPanel]@{
        Margin        = [System.Windows.Thickness]::new(16)
        LastChildFill = $true
    }
    [void]$mainPanel.Children.Add($contentPanel)

    return @{
        Window       = $window
        MainBorder   = $mainBorder
        MainPanel    = $mainPanel
        TitleBar     = $titleBar
        ContentPanel = $contentPanel
        Colors       = $colors
    }
}