using Connected.Extensions; using Connected.Utilities; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; namespace Connected.Components; public partial class Input : InputBase { protected string Classname => InputCssHelper.GetClassname(this, () => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder)); protected string InputClassname => InputCssHelper.GetInputClassname(this); protected string AdornmentClassname => InputCssHelper.GetAdornmentClassname(this); protected string ClearButtonClassname => new CssBuilder() .AddClass("me-n1", Adornment == Adornment.End && HideSpinButtons == false) .AddClass("mud-icon-button-edge-end", Adornment == Adornment.End && HideSpinButtons == true) .AddClass("me-6", Adornment != Adornment.End && HideSpinButtons == false) .AddClass("mud-icon-button-edge-margin-end", Adornment != Adornment.End && HideSpinButtons == true) .Build(); /// /// Type of the input element. It should be a valid HTML5 input type. /// [Parameter] public InputType InputType { get; set; } = InputType.Text; internal override InputType GetInputType() => InputType; protected string InputTypeString => InputType.ToDescriptionString(); protected Task OnInput(ChangeEventArgs args) { if (!Immediate) return Task.CompletedTask; _isFocused = true; return SetTextAsync(args?.Value as string); } protected async Task OnChange(ChangeEventArgs args) { _internalText = args?.Value as string; await OnInternalInputChanged.InvokeAsync(args); if (!Immediate) { await SetTextAsync(args?.Value as string); } } /// /// Paste hook for descendants. /// #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously protected virtual async Task OnPaste(ClipboardEventArgs args) #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { // do nothing return; } /// /// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null. /// [Parameter] public RenderFragment ChildContent { get; set; } public ElementReference ElementReference { get; private set; } private ElementReference _elementReference1; public override async ValueTask FocusAsync() { try { if (InputType == InputType.Hidden && ChildContent != null) await _elementReference1.FocusAsync(); else await ElementReference.FocusAsync(); } catch (Exception e) { Console.WriteLine("Input.FocusAsync: " + e.Message); } } public override ValueTask BlurAsync() { return ElementReference.BlurAsync(); } public override ValueTask SelectAsync() { return ElementReference.SelectAsync(); } public override ValueTask SelectRangeAsync(int pos1, int pos2) { return ElementReference.SelectRangeAsync(pos1, pos2); } /// /// Invokes the callback when the Up arrow button is clicked when the input is set to . /// Note: use the optimized control if you need to deal with numbers. /// [Parameter] public EventCallback OnIncrement { get; set; } /// /// Invokes the callback when the Down arrow button is clicked when the input is set to . /// Note: use the optimized control if you need to deal with numbers. /// [Parameter] public EventCallback OnDecrement { get; set; } /// /// Hides the spin buttons for /// [Parameter] public bool HideSpinButtons { get; set; } = true; /// /// Show clear button. /// [Parameter] public bool Clearable { get; set; } = false; /// /// Button click event for clear button. Called after text and value has been cleared. /// [Parameter] public EventCallback OnClearButtonClick { get; set; } /// /// Mouse wheel event for input. /// [Parameter] public EventCallback OnMouseWheel { get; set; } /// /// Custom clear icon. /// [Parameter] public string ClearIcon { get; set; } = Icons.Material.Filled.Clear; /// /// Custom numeric up icon. /// [Parameter] public string NumericUpIcon { get; set; } = Icons.Material.Filled.KeyboardArrowUp; /// /// Custom numeric down icon. /// [Parameter] public string NumericDownIcon { get; set; } = Icons.Material.Filled.KeyboardArrowDown; private Size GetButtonSize() => Margin == Margin.Dense ? Size.Small : Size.Medium; private bool _showClearable; private void UpdateClearable(object value) { var showClearable = Clearable && ((value is string stringValue && !string.IsNullOrWhiteSpace(stringValue)) || (value is not string && value is not null)); if (_showClearable != showClearable) _showClearable = showClearable; } protected override async Task UpdateTextPropertyAsync(bool updateValue) { await base.UpdateTextPropertyAsync(updateValue); if (Clearable) UpdateClearable(Text); } protected override async Task UpdateValuePropertyAsync(bool updateText) { await base.UpdateValuePropertyAsync(updateText); if (Clearable) UpdateClearable(Value); } protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e) { await SetTextAsync(string.Empty, updateValue: true); await ElementReference.FocusAsync(); await OnClearButtonClick.InvokeAsync(e); } private string _internalText; public override async Task SetParametersAsync(ParameterView parameters) { await base.SetParametersAsync(parameters); //if (!_isFocused || _forceTextUpdate) // _internalText = Text; if (RuntimeLocation.IsServerSide && TextUpdateSuppression) { // Text update suppression, only in BSS (not in WASM). // This is a fix for #1012 if (!_isFocused || _forceTextUpdate) _internalText = Text; } else { // in WASM (or in BSS with TextUpdateSuppression==false) we always update _internalText = Text; } } /// /// Sets the input text from outside programmatically /// /// /// public Task SetText(string text) { _internalText = text; return SetTextAsync(text); } // Certain HTML5 inputs (dates and color) have a native placeholder private bool HasNativeHtmlPlaceholder() { return GetInputType() is InputType.Color or InputType.Date or InputType.DateTimeLocal or InputType.Month or InputType.Time or InputType.Week; } } public class InputString : Input { }