Public/View/New-ElmTextInput.ps1
|
function New-ElmTextInput { <# .SYNOPSIS Creates a single-line text input view node. .DESCRIPTION Returns a Text view node representing an editable text field. The caller manages Value and CursorPos in the model; key subscriptions forward character keys and control keys (Backspace, Left, Right, Home, End) to the update function, which mutates Value/CursorPos and passes them here. Rendered example (focused, cursor at position 5): [ hello| world ] When unfocused: [ hello world ] Placeholder text is shown when Value is empty and the field is not focused. .PARAMETER Value Current string value of the input. Default: empty string. .PARAMETER CursorPos Zero-based cursor position within Value. Clamped to [0, Value.Length]. Default: 0. Only rendered when -Focused is present. .PARAMETER Focused When present, renders a cursor character at CursorPos and applies FocusedStyle instead of Style. .PARAMETER Placeholder Text shown when Value is empty and -Focused is not set. Default: ''. .PARAMETER CursorChar Character used to represent the cursor. Default: '|'. .PARAMETER Style Elm style applied when the field is not focused. .PARAMETER FocusedStyle Elm style applied when the field is focused. When omitted and -Focused is set, falls back to Style. .PARAMETER FocusedBoxStyle When provided and -Focused is set, the Text node is wrapped in a Box (Vertical) whose Style is this value. Use to add a visible border around the focused field, e.g.: New-ElmStyle -Border 'Rounded' -Foreground 'BrightWhite' When null (default) or when unfocused, no wrapper Box is added and the node returned is a plain Text node. .OUTPUTS PSCustomObject - Text view node. .EXAMPLE New-ElmTextInput -Value $model.Input -CursorPos $model.Cursor -Focused .EXAMPLE $focStyle = New-ElmStyle -Foreground 'BrightWhite' -Underline New-ElmTextInput -Value $model.Search -CursorPos $model.Cursor ` -Focused:$model.InputFocused ` -Placeholder 'Type to search...' ` -FocusedStyle $focStyle .NOTES This widget is purely a view helper. Use key subscriptions or TickMs to handle Backspace, Delete, character insertion, cursor movement, etc. in the Update function. #> [CmdletBinding()] param( [Parameter()] [AllowEmptyString()] [string]$Value = '', [Parameter()] [int]$CursorPos = 0, [Parameter()] [switch]$Focused, [Parameter()] [AllowEmptyString()] [string]$Placeholder = '', [Parameter()] [ValidateLength(1, 1)] [string]$CursorChar = '|', [Parameter()] [PSCustomObject]$Style = $null, [Parameter()] [PSCustomObject]$FocusedStyle = $null, [Parameter()] [PSCustomObject]$FocusedBoxStyle = $null ) # Clamp cursor $clampedCursor = [math]::Max(0, [math]::Min($CursorPos, $Value.Length)) $activeStyle = if ($Focused.IsPresent -and $null -ne $FocusedStyle) { $FocusedStyle } else { $Style } $content = if ($Focused.IsPresent) { # Insert cursor character at position $before = $Value.Substring(0, $clampedCursor) $after = $Value.Substring($clampedCursor) $before + $CursorChar + $after } elseif ($Value.Length -eq 0 -and $Placeholder.Length -gt 0) { $Placeholder } else { $Value } $textNode = [PSCustomObject]@{ Type = 'Text' Content = $content Style = $activeStyle Width = 'Auto' Height = 'Auto' } # When focused and a FocusedBoxStyle is provided, wrap in a border Box if ($Focused.IsPresent -and $null -ne $FocusedBoxStyle) { return [PSCustomObject]@{ Type = 'Box' Direction = 'Vertical' Children = @($textNode) Style = $FocusedBoxStyle Width = 'Auto' Height = 'Auto' } } return $textNode } |