Compare commits
	
		
			No commits in common. "edcc8661e391f12743c2faecf25dba895f89d2b7" and "25606b926b9d53576a8d2f5801547be1a49fb6e3" have entirely different histories.
		
	
	
		
			edcc8661e3
			...
			25606b926b
		
	
		
@ -139,11 +139,11 @@ public abstract class FormComponent<T, U> : UIComponent, IFormComponent, IDispos
 | 
				
			|||||||
	 /// </summary>
 | 
						 /// </summary>
 | 
				
			||||||
	 public bool HasErrors => HasError || ConversionError || ValidationErrors.Count > 0;
 | 
						 public bool HasErrors => HasError || ConversionError || ValidationErrors.Count > 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// <summary>
 | 
						 /// <summary>
 | 
				
			||||||
	/// Return the validation error text or the conversion error message.
 | 
						 /// Return the validation error text or the conversion error message.
 | 
				
			||||||
	/// </summary>
 | 
						 /// </summary>
 | 
				
			||||||
	/// <returns>Error text/message</returns>
 | 
						 /// <returns>Error text/message</returns>
 | 
				
			||||||
	public string? GetErrorText(bool test = false)
 | 
						 public string? GetErrorText()
 | 
				
			||||||
	 {
 | 
						 {
 | 
				
			||||||
		  // ErrorText is either set from outside or the first validation error
 | 
							  // ErrorText is either set from outside or the first validation error
 | 
				
			||||||
		  if (!IsNullOrWhiteSpace(ErrorText))
 | 
							  if (!IsNullOrWhiteSpace(ErrorText))
 | 
				
			||||||
@ -152,8 +152,6 @@ public abstract class FormComponent<T, U> : UIComponent, IFormComponent, IDispos
 | 
				
			|||||||
		  if (!IsNullOrWhiteSpace(ConversionErrorMessage))
 | 
							  if (!IsNullOrWhiteSpace(ConversionErrorMessage))
 | 
				
			||||||
				return ConversionErrorMessage;
 | 
									return ConversionErrorMessage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (test) return "Error: test";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		  return null;
 | 
							  return null;
 | 
				
			||||||
	 }
 | 
						 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
using System.Timers;
 | 
					using System.Timers;
 | 
				
			||||||
using Connected.Annotations;
 | 
					using Connected.Annotations;
 | 
				
			||||||
 | 
					using Connected.Utilities.BindingConverters;
 | 
				
			||||||
using Microsoft.AspNetCore.Components;
 | 
					using Microsoft.AspNetCore.Components;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.Components;
 | 
					namespace Connected.Components;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,23 +3,6 @@
 | 
				
			|||||||
@inherits InputBase<T>
 | 
					@inherits InputBase<T>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="@Classname">
 | 
					<div class="@Classname">
 | 
				
			||||||
    <InputControl Label="@Label"
 | 
					 | 
				
			||||||
                  Variant="@Variant"
 | 
					 | 
				
			||||||
                  HelperText="@HelperText"
 | 
					 | 
				
			||||||
                  HelperTextOnFocus="@HelperTextOnFocus"
 | 
					 | 
				
			||||||
                  CounterText="@GetCounterText()"
 | 
					 | 
				
			||||||
                  FullWidth="@FullWidth"
 | 
					 | 
				
			||||||
                  Class="@Classname"
 | 
					 | 
				
			||||||
                  Error="@HasErrors"
 | 
					 | 
				
			||||||
                  ErrorText="@ErrorText"
 | 
					 | 
				
			||||||
                  ErrorId="@ErrorId"
 | 
					 | 
				
			||||||
                  Disabled="@Disabled"
 | 
					 | 
				
			||||||
                  Margin="@Margin"
 | 
					 | 
				
			||||||
                  Required="@Required"
 | 
					 | 
				
			||||||
                  ForId="@FieldId">
 | 
					 | 
				
			||||||
    <CascadingValue Name="SubscribeToParentForm" Value="@base.SubscribeToParentForm" IsFixed="true">
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@if (Adornment == Adornment.Start)
 | 
						@if (Adornment == Adornment.Start)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	    <InputAdornment Class="@AdornmentClassname" 
 | 
						    <InputAdornment Class="@AdornmentClassname" 
 | 
				
			||||||
@ -32,135 +15,131 @@
 | 
				
			|||||||
                AriaLabel="@AdornmentAriaLabel"
 | 
					                AriaLabel="@AdornmentAriaLabel"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    <InputContent>
 | 
					
 | 
				
			||||||
	    @if (Lines > 1)
 | 
						@if (Lines > 1)
 | 
				
			||||||
	    {
 | 
						{
 | 
				
			||||||
	        <textarea class="@InputClassname"
 | 
						    <textarea class="@InputClassname"
 | 
				
			||||||
                    @ref="ElementReference" 
 | 
					                @ref="ElementReference" 
 | 
				
			||||||
                    rows="@Lines" 
 | 
					                rows="@Lines" 
 | 
				
			||||||
                    @attributes="CustomAttributes"
 | 
					                @attributes="CustomAttributes"
 | 
				
			||||||
                    type="@InputTypeString"                  
 | 
					                type="@InputTypeString"                  
 | 
				
			||||||
                    placeholder="@Placeholder" 
 | 
					                placeholder="@Placeholder" 
 | 
				
			||||||
                    disabled=@Disabled 
 | 
					                disabled=@Disabled 
 | 
				
			||||||
                    readonly="@ReadOnly" 
 | 
					                readonly="@ReadOnly" 
 | 
				
			||||||
                    inputmode="@InputMode.ToString()"
 | 
					                inputmode="@InputMode.ToString()"
 | 
				
			||||||
			        @oninput="OnInput" 
 | 
								    @oninput="OnInput" 
 | 
				
			||||||
                    @onchange="OnChange" 
 | 
					                @onchange="OnChange" 
 | 
				
			||||||
                    @onblur="@OnBlurred" 
 | 
					                @onblur="@OnBlurred" 
 | 
				
			||||||
                    @onkeydown="@InvokeKeyDown" 
 | 
					                @onkeydown="@InvokeKeyDown" 
 | 
				
			||||||
                    @onkeypress="@InvokeKeyPress" 
 | 
					                @onkeypress="@InvokeKeyPress" 
 | 
				
			||||||
                    @onkeyup="@InvokeKeyUp" 
 | 
					                @onkeyup="@InvokeKeyUp" 
 | 
				
			||||||
                    @onpaste="@OnPaste" 
 | 
					                @onpaste="@OnPaste" 
 | 
				
			||||||
                    value="@_internalText" 
 | 
					                value="@_internalText" 
 | 
				
			||||||
                    maxlength="@MaxLength"
 | 
					                maxlength="@MaxLength"
 | 
				
			||||||
			        @onkeydown:preventDefault="@KeyDownPreventDefault" 
 | 
								    @onkeydown:preventDefault="@KeyDownPreventDefault" 
 | 
				
			||||||
                    @onkeypress:preventDefault="@KeyPressPreventDefault" 
 | 
					                @onkeypress:preventDefault="@KeyPressPreventDefault" 
 | 
				
			||||||
                    @onkeyup:preventDefault="@KeyUpPreventDefault"
 | 
					                @onkeyup:preventDefault="@KeyUpPreventDefault"
 | 
				
			||||||
                    @onmousewheel="@OnMouseWheel" 
 | 
					                @onmousewheel="@OnMouseWheel" 
 | 
				
			||||||
                    @onwheel="@OnMouseWheel"
 | 
					                @onwheel="@OnMouseWheel"
 | 
				
			||||||
                    aria-invalid="@HasError.ToString().ToLower()"
 | 
					                aria-invalid="@HasError.ToString().ToLower()"
 | 
				
			||||||
                    aria-describedby="@ErrorId"
 | 
					                aria-describedby="@ErrorId"
 | 
				
			||||||
            > 
 | 
					        > 
 | 
				
			||||||
                @Text
 | 
					            @Text
 | 
				
			||||||
            </textarea>
 | 
					        </textarea>
 | 
				
			||||||
        
 | 
					        @*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
 | 
				
			||||||
            @*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
 | 
					        @*note: the value="@_internalText" is absolutely essential here. the inner html @Text is needed by tests checking it*@
 | 
				
			||||||
            @*note: the value="@_internalText" is absolutely essential here. the inner html @Text is needed by tests checking it*@
 | 
						}
 | 
				
			||||||
	    }
 | 
						else
 | 
				
			||||||
	    else
 | 
						{
 | 
				
			||||||
	    {
 | 
						    <input class="@InputClassname"
 | 
				
			||||||
	        <input class="@InputClassname"
 | 
					                @ref="ElementReference" 
 | 
				
			||||||
                    @ref="ElementReference" 
 | 
					                @attributes="CustomAttributes" 
 | 
				
			||||||
                    @attributes="CustomAttributes" 
 | 
					                type="@InputTypeString"                  
 | 
				
			||||||
                    type="@InputTypeString"                  
 | 
					                value="@_internalText" 
 | 
				
			||||||
                    value="@_internalText" 
 | 
					                @oninput="OnInput" 
 | 
				
			||||||
                    @oninput="OnInput" 
 | 
					                @onchange="OnChange"
 | 
				
			||||||
                    @onchange="OnChange"
 | 
					                placeholder="@Placeholder" 
 | 
				
			||||||
                    placeholder="@Placeholder" 
 | 
					                disabled=@Disabled 
 | 
				
			||||||
                    disabled=@Disabled 
 | 
					                readonly="@ReadOnly" 
 | 
				
			||||||
                    readonly="@ReadOnly" 
 | 
					                @onblur="@OnBlurred" 
 | 
				
			||||||
                    @onblur="@OnBlurred" 
 | 
					                inputmode="@InputMode.ToString()" 
 | 
				
			||||||
                    inputmode="@InputMode.ToString()" 
 | 
					                pattern="@Pattern"
 | 
				
			||||||
                    pattern="@Pattern"
 | 
					                @onkeydown="@InvokeKeyDown" 
 | 
				
			||||||
                    @onkeydown="@InvokeKeyDown" 
 | 
					                @onkeypress="@InvokeKeyPress" 
 | 
				
			||||||
                    @onkeypress="@InvokeKeyPress" 
 | 
					                @onkeyup="@InvokeKeyUp" 
 | 
				
			||||||
                    @onkeyup="@InvokeKeyUp" 
 | 
					                maxlength="@MaxLength"
 | 
				
			||||||
                    maxlength="@MaxLength"
 | 
					                @onkeydown:preventDefault="KeyDownPreventDefault" 
 | 
				
			||||||
                    @onkeydown:preventDefault="KeyDownPreventDefault" 
 | 
					                @onkeypress:preventDefault="@KeyPressPreventDefault" 
 | 
				
			||||||
                    @onkeypress:preventDefault="@KeyPressPreventDefault" 
 | 
					                @onkeyup:preventDefault="@KeyUpPreventDefault"
 | 
				
			||||||
                    @onkeyup:preventDefault="@KeyUpPreventDefault"
 | 
					                @onmousewheel="@OnMouseWheel" 
 | 
				
			||||||
                    @onmousewheel="@OnMouseWheel" 
 | 
					                @onwheel="@OnMouseWheel"
 | 
				
			||||||
                    @onwheel="@OnMouseWheel"
 | 
					                aria-invalid="@HasError.ToString().ToLower()"
 | 
				
			||||||
                    aria-invalid="@HasError.ToString().ToLower()"
 | 
					                aria-describedby="@ErrorId"
 | 
				
			||||||
                    aria-describedby="@ErrorId"
 | 
					         />
 | 
				
			||||||
             />
 | 
						     @*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
 | 
				
			||||||
	         @*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
             @if (Disabled) {
 | 
					         @if (Disabled) {
 | 
				
			||||||
                 @*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.
 | 
					             @*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.
 | 
				
			||||||
                               In Disabled state the tabindex attribute must NOT be set at all or else it will get focus on click
 | 
					                           In Disabled state the tabindex attribute must NOT be set at all or else it will get focus on click
 | 
				
			||||||
                 *@
 | 
					             *@
 | 
				
			||||||
	            <div class="@InputClassname"
 | 
						        <div class="@InputClassname"
 | 
				
			||||||
                    style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"                  
 | 
					                style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"                  
 | 
				
			||||||
                    @onblur="@OnBlurred" @ref="@_elementReference1" 
 | 
					                @onblur="@OnBlurred" @ref="@_elementReference1" 
 | 
				
			||||||
                >
 | 
					            >
 | 
				
			||||||
                    @ChildContent
 | 
					                @ChildContent
 | 
				
			||||||
                </div>
 | 
					            </div>
 | 
				
			||||||
            } 
 | 
					        } 
 | 
				
			||||||
            else
 | 
					        else
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                 @*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.*@
 | 
					 | 
				
			||||||
                <div class="@InputClassname"
 | 
					 | 
				
			||||||
                     style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"  
 | 
					 | 
				
			||||||
                     tabindex="@(InputType == InputType.Hidden && ChildContent != null ? 0 : -1)" 
 | 
					 | 
				
			||||||
                     @onblur="@OnBlurred" @ref="@_elementReference1" 
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                    @ChildContent
 | 
					 | 
				
			||||||
                </div>            
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	    @if (_showClearable && !Disabled)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					             @*Note: this div must always be there to avoid crashes in WASM, but it is hidden most of the time except if ChildContent should be shown.*@
 | 
				
			||||||
 | 
					            <div class="@InputClassname"
 | 
				
			||||||
 | 
					                 style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"  
 | 
				
			||||||
 | 
					                 tabindex="@(InputType == InputType.Hidden && ChildContent != null ? 0 : -1)" 
 | 
				
			||||||
 | 
					                 @onblur="@OnBlurred" @ref="@_elementReference1" 
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					                @ChildContent
 | 
				
			||||||
 | 
					            </div>            
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    
 | 
					    }
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	    @if (Adornment == Adornment.End)
 | 
					 | 
				
			||||||
	    {
 | 
					 | 
				
			||||||
	        <InputAdornment Class="@AdornmentClassname" 
 | 
					 | 
				
			||||||
                    Icon="@AdornmentIcon" 
 | 
					 | 
				
			||||||
                    Color="@AdornmentColor" 
 | 
					 | 
				
			||||||
                    Size="@IconSize" 
 | 
					 | 
				
			||||||
                    Text="@AdornmentText" 
 | 
					 | 
				
			||||||
                    Edge="@Edge.End" 
 | 
					 | 
				
			||||||
                    AdornmentClick="@OnAdornmentClick" 
 | 
					 | 
				
			||||||
                    AriaLabel="@AdornmentAriaLabel"
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    @if (Variant == Variant.Outlined)
 | 
						@if (_showClearable && !Disabled)
 | 
				
			||||||
	    {
 | 
					    {
 | 
				
			||||||
	        <div class="input-outlined-border"></div>
 | 
					        <IconButton Class="@ClearButtonClassname"
 | 
				
			||||||
	    }
 | 
					                    Color="@ThemeColor.Default" 
 | 
				
			||||||
 | 
					                    Icon="@ClearIcon" 
 | 
				
			||||||
 | 
					                    Size="@Size.Small" 
 | 
				
			||||||
 | 
					                    OnClick="@ClearButtonClickHandlerAsync"
 | 
				
			||||||
 | 
					                    tabindex="-1"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    @if (!HideSpinButtons)
 | 
						@if (Adornment == Adornment.End)
 | 
				
			||||||
	    {
 | 
						{
 | 
				
			||||||
	        <div class="input-numeric-spin">
 | 
						    <InputAdornment Class="@AdornmentClassname" 
 | 
				
			||||||
                <Button Variant="Variant.Text" @onclick="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
 | 
					                Icon="@AdornmentIcon" 
 | 
				
			||||||
                    <Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
 | 
					                Color="@AdornmentColor" 
 | 
				
			||||||
                </Button>
 | 
					                Size="@IconSize" 
 | 
				
			||||||
                <Button Variant="Variant.Text" @onclick="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
 | 
					                Text="@AdornmentText" 
 | 
				
			||||||
                    <Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" />
 | 
					                Edge="@Edge.End" 
 | 
				
			||||||
                </Button>
 | 
					                AdornmentClick="@OnAdornmentClick" 
 | 
				
			||||||
	        </div>
 | 
					                AriaLabel="@AdornmentAriaLabel"
 | 
				
			||||||
	    }
 | 
					        />
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
        </InputContent>
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    </CascadingValue>  
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
    </InputControl>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if (Variant == Variant.Outlined)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						    <div class="input-outlined-border"></div>
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if (!HideSpinButtons)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						    <div class="input-numeric-spin">
 | 
				
			||||||
 | 
					            <Button Variant="Variant.Text" @onclick="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
 | 
				
			||||||
 | 
					                <Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
					            <Button Variant="Variant.Text" @onclick="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
 | 
				
			||||||
 | 
					                <Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" />
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
						    </div>
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
@ -2,192 +2,12 @@
 | 
				
			|||||||
using Connected.Utilities;
 | 
					using Connected.Utilities;
 | 
				
			||||||
using Microsoft.AspNetCore.Components;
 | 
					using Microsoft.AspNetCore.Components;
 | 
				
			||||||
using Microsoft.AspNetCore.Components.Web;
 | 
					using Microsoft.AspNetCore.Components.Web;
 | 
				
			||||||
using System.Numerics;
 | 
					 | 
				
			||||||
using System.Text.RegularExpressions;
 | 
					 | 
				
			||||||
using System.Timers;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.Components;
 | 
					namespace Connected.Components;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public partial class Input<T> : InputBase<T>
 | 
					public partial class Input<T> : InputBase<T>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					   protected string Classname => InputCssHelper.GetClassname(this,
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Debounce
 | 
					 | 
				
			||||||
	 * 
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// The current character counter, displayed below the text field.
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	[Parameter] public string CounterText { get; set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private System.Timers.Timer _timer;
 | 
					 | 
				
			||||||
	private double _debounceInterval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// Interval to be awaited in MILLISECONDS before changing the Text value
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	[Parameter]
 | 
					 | 
				
			||||||
	public double TextChangeDelay
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		get => _debounceInterval;
 | 
					 | 
				
			||||||
		set
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (NumericConverter<double>.AreEqual(_debounceInterval, value))
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			_debounceInterval = value;
 | 
					 | 
				
			||||||
			if (_debounceInterval == 0)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// not debounced, dispose timer if any
 | 
					 | 
				
			||||||
				ClearTimer(suppressTick: false);
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			SetTimer();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// callback to be called when the debounce interval has elapsed
 | 
					 | 
				
			||||||
	/// receives the Text as a parameter
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	[Parameter] public EventCallback<string> OnDebounceIntervalElapsed { get; set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected Task OnDebounceChange()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (TextChangeDelay > 0 && _timer != null)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			_timer.Stop();
 | 
					 | 
				
			||||||
			return base.UpdateValuePropertyAsync(false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return Task.CompletedTask;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected override Task UpdateValuePropertyAsync(bool updateText)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// This method is called when Value property needs to be refreshed from the current Text property, so typically because Text property has changed.
 | 
					 | 
				
			||||||
		// We want to debounce only text-input, not a value being set, so the debouncing is only done when updateText==false (because that indicates the
 | 
					 | 
				
			||||||
		// change came from a Text setter)
 | 
					 | 
				
			||||||
		if (updateText)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// we have a change coming not from the Text setter, no debouncing is needed
 | 
					 | 
				
			||||||
			return base.UpdateValuePropertyAsync(updateText);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// if debounce interval is 0 we update immediately
 | 
					 | 
				
			||||||
		if (TextChangeDelay <= 0 || _timer == null)
 | 
					 | 
				
			||||||
			return base.UpdateValuePropertyAsync(updateText);
 | 
					 | 
				
			||||||
		// If a debounce interval is defined, we want to delay the update of Value property.
 | 
					 | 
				
			||||||
		_timer.Stop();
 | 
					 | 
				
			||||||
		// restart the timer while user is typing
 | 
					 | 
				
			||||||
		_timer.Start();
 | 
					 | 
				
			||||||
		return Task.CompletedTask;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected override void OnParametersSet()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		base.OnParametersSet();
 | 
					 | 
				
			||||||
		// if input is to be debounced, makes sense to bind the change of the text to oninput
 | 
					 | 
				
			||||||
		// so we set Immediate to true
 | 
					 | 
				
			||||||
		if (TextChangeDelay > 0)
 | 
					 | 
				
			||||||
			Immediate = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private void SetTimer()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (_timer == null)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			_timer = new System.Timers.Timer();
 | 
					 | 
				
			||||||
			_timer.Elapsed += OnTimerTick;
 | 
					 | 
				
			||||||
			_timer.AutoReset = false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		_timer.Interval = TextChangeDelay;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private void OnTimerTick(object sender, ElapsedEventArgs e)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		InvokeAsync(OnTimerTickGuiThread).AndForget();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private async Task OnTimerTickGuiThread()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		await base.UpdateValuePropertyAsync(false);
 | 
					 | 
				
			||||||
		await OnDebounceIntervalElapsed.InvokeAsync(Text);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private void ClearTimer(bool suppressTick = false)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (_timer == null)
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		var wasEnabled = _timer.Enabled;
 | 
					 | 
				
			||||||
		_timer.Stop();
 | 
					 | 
				
			||||||
		_timer.Elapsed -= OnTimerTick;
 | 
					 | 
				
			||||||
		_timer.Dispose();
 | 
					 | 
				
			||||||
		_timer = null;
 | 
					 | 
				
			||||||
		if (wasEnabled && !suppressTick)
 | 
					 | 
				
			||||||
			OnTimerTickGuiThread().AndForget();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	*  Debounce end
 | 
					 | 
				
			||||||
	*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected CssBuilder CompiledHelperContainerClassList
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		get
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return new CssBuilder("input-control-helper-container")
 | 
					 | 
				
			||||||
			.AddClass($"px-1", Variant == Variant.Filled)
 | 
					 | 
				
			||||||
			.AddClass($"px-2", Variant == Variant.Outlined)
 | 
					 | 
				
			||||||
			.AddClass($"px-1", Variant == Variant.Text)
 | 
					 | 
				
			||||||
			.AddClass(HelperContainerClassList);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// A space separated list of class names, added on top of the default helper container class list.
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	[Parameter]
 | 
					 | 
				
			||||||
	public string? HelperContainerClassList { get; set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected CssBuilder CompiledHelperClassList
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		get
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return new CssBuilder("input-helper-text")
 | 
					 | 
				
			||||||
			.AddClass("input-helper-onfocus", HelperTextOnFocus)
 | 
					 | 
				
			||||||
			.AddClass(HelperClassList);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// A space separated list of class names, added on top of the default helper class list.
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	[Parameter]
 | 
					 | 
				
			||||||
	public string? HelperClassList { get; set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*protected string HelperContainer =>
 | 
					 | 
				
			||||||
		new CssBuilder("input-control-helper-container")
 | 
					 | 
				
			||||||
		.AddClass($"px-1", Variant == Variant.Filled)
 | 
					 | 
				
			||||||
		.AddClass($"px-2", Variant == Variant.Outlined)
 | 
					 | 
				
			||||||
		.Build();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected string HelperClass =>
 | 
					 | 
				
			||||||
		new CssBuilder("input-helper-text")
 | 
					 | 
				
			||||||
		 .AddClass("input-helper-onfocus", HelperTextOnFocus)
 | 
					 | 
				
			||||||
		.Build();*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private string GetCounterText()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		string result = Text.Length.ToString();
 | 
					 | 
				
			||||||
		if (string.IsNullOrEmpty(Text)) result = "0";
 | 
					 | 
				
			||||||
		return result;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected string Classname => InputCssHelper.GetClassname(this,
 | 
					 | 
				
			||||||
      () => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder));
 | 
					      () => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   protected string InputClassname => InputCssHelper.GetInputClassname(this);
 | 
					   protected string InputClassname => InputCssHelper.GetInputClassname(this);
 | 
				
			||||||
@ -211,89 +31,23 @@ public partial class Input<T> : InputBase<T>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
   protected string InputTypeString => InputType.ToDescription();
 | 
					   protected string InputTypeString => InputType.ToDescription();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					   protected Task OnInput(ChangeEventArgs args)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	private bool IsDecimalNumber(string type)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		switch (type.ToLower())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			case "double":
 | 
					 | 
				
			||||||
			case "float":
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private bool IsNumber(string s)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		bool result = false;
 | 
					 | 
				
			||||||
		try
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			double d;
 | 
					 | 
				
			||||||
			result= double.TryParse(s, out d);
 | 
					 | 
				
			||||||
		} catch
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			result = false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return result;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private string ValidateInput(string value)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		string result = value;
 | 
					 | 
				
			||||||
		if (value is not null)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			var expectedType = typeof(T).Name;
 | 
					 | 
				
			||||||
			if (IsNumericType(expectedType))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (IsNumber(value.ToString()))
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					result = value.ToString();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					if (IsDecimalNumber(value.ToString()))
 | 
					 | 
				
			||||||
						result = Regex.Replace(value.ToString(), "[^0-9.]", "");
 | 
					 | 
				
			||||||
					else result = Regex.Replace(value.ToString(), "[^0-9]", "");
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				result = value;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return result;
 | 
					 | 
				
			||||||
	}*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected Task OnInput(ChangeEventArgs args)
 | 
					 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
      if (!Immediate)
 | 
					      if (!Immediate)
 | 
				
			||||||
         return Task.CompletedTask;
 | 
					         return Task.CompletedTask;
 | 
				
			||||||
      _isFocused = true;
 | 
					      _isFocused = true;
 | 
				
			||||||
		return SetTextAsync(args?.Value as string);
 | 
					      return SetTextAsync(args?.Value as string);
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   protected async Task OnChange(ChangeEventArgs args)
 | 
					   protected async Task OnChange(ChangeEventArgs args)
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
		if (TextChangeDelay > 0 && _timer != null)
 | 
					      _internalText = args?.Value as string;
 | 
				
			||||||
		{
 | 
					      await OnInternalInputChanged.InvokeAsync(args);
 | 
				
			||||||
			_timer.Stop();
 | 
					      if (!Immediate)
 | 
				
			||||||
			await UpdateValuePropertyAsync(false);
 | 
					      {
 | 
				
			||||||
		}
 | 
					         await SetTextAsync(args?.Value as string);
 | 
				
			||||||
		else
 | 
					      }
 | 
				
			||||||
		{
 | 
					   }
 | 
				
			||||||
			_internalText = args?.Value as string;
 | 
					 | 
				
			||||||
			await OnInternalInputChanged.InvokeAsync(args);
 | 
					 | 
				
			||||||
			if (!Immediate)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				await SetTextAsync(args?.Value as string);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /// <summary>
 | 
					   /// <summary>
 | 
				
			||||||
   /// Paste hook for descendants.
 | 
					   /// Paste hook for descendants.
 | 
				
			||||||
@ -410,12 +164,12 @@ public partial class Input<T> : InputBase<T>
 | 
				
			|||||||
         UpdateClearable(Text);
 | 
					         UpdateClearable(Text);
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /*protected override async Task UpdateValuePropertyAsync(bool updateText)
 | 
					   protected override async Task UpdateValuePropertyAsync(bool updateText)
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
      await base.UpdateValuePropertyAsync(updateText);
 | 
					      await base.UpdateValuePropertyAsync(updateText);
 | 
				
			||||||
      if (Clearable)
 | 
					      if (Clearable)
 | 
				
			||||||
         UpdateClearable(Value);
 | 
					         UpdateClearable(Value);
 | 
				
			||||||
   }*/
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
 | 
					   protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
@ -443,41 +197,14 @@ public partial class Input<T> : InputBase<T>
 | 
				
			|||||||
         // in WASM (or in BSS with TextUpdateSuppression==false) we always update
 | 
					         // in WASM (or in BSS with TextUpdateSuppression==false) we always update
 | 
				
			||||||
         _internalText = Text;
 | 
					         _internalText = Text;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					 | 
				
			||||||
		string baseTypeName = typeof(T).Name;
 | 
					 | 
				
			||||||
		if (IsNumericType(baseTypeName) && InputType !=InputType.Number)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			InputType = InputType.Number;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private bool IsNumericType(string type)
 | 
					   /// <summary>
 | 
				
			||||||
	{
 | 
					   /// Sets the input text from outside programmatically
 | 
				
			||||||
		switch (type.ToLower())
 | 
					   /// </summary>
 | 
				
			||||||
		{
 | 
					   /// <param name="text"></param>
 | 
				
			||||||
			case "uint16":
 | 
					   /// <returns></returns>
 | 
				
			||||||
			case "uint32":
 | 
					   public Task SetText(string text)
 | 
				
			||||||
			case "uint64":
 | 
					 | 
				
			||||||
			case "int16":
 | 
					 | 
				
			||||||
			case "int32":
 | 
					 | 
				
			||||||
			case "int64":
 | 
					 | 
				
			||||||
			case "int":
 | 
					 | 
				
			||||||
			case "double":
 | 
					 | 
				
			||||||
			case "decimal":
 | 
					 | 
				
			||||||
			case "float":
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// Sets the input text from outside programmatically
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	/// <param name="text"></param>
 | 
					 | 
				
			||||||
	/// <returns></returns>
 | 
					 | 
				
			||||||
	public Task SetText(string text)
 | 
					 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
      _internalText = text;
 | 
					      _internalText = text;
 | 
				
			||||||
      return SetTextAsync(text);
 | 
					      return SetTextAsync(text);
 | 
				
			||||||
 | 
				
			|||||||
@ -211,7 +211,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
   protected virtual async Task SetTextAsync(string text, bool updateValue = true)
 | 
					   protected virtual async Task SetTextAsync(string text, bool updateValue = true)
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
		if (Text != text)
 | 
					      if (Text != text)
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
         Text = text;
 | 
					         Text = text;
 | 
				
			||||||
         if (!string.IsNullOrWhiteSpace(Text))
 | 
					         if (!string.IsNullOrWhiteSpace(Text))
 | 
				
			||||||
@ -220,7 +220,6 @@ public abstract class InputBase<T> : FormComponent<T, string>
 | 
				
			|||||||
            await UpdateValuePropertyAsync(false);
 | 
					            await UpdateValuePropertyAsync(false);
 | 
				
			||||||
         await TextChanged.InvokeAsync(Text);
 | 
					         await TextChanged.InvokeAsync(Text);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /// <summary>
 | 
					   /// <summary>
 | 
				
			||||||
@ -330,11 +329,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
 | 
				
			|||||||
   /// Fired when the Value property changes.
 | 
					   /// Fired when the Value property changes.
 | 
				
			||||||
   /// </summary>
 | 
					   /// </summary>
 | 
				
			||||||
   [Parameter]
 | 
					   [Parameter]
 | 
				
			||||||
   public EventCallback<T> ValueChanged
 | 
					   public EventCallback<T> ValueChanged { get; set; }
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		get;
 | 
					 | 
				
			||||||
		set;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /// <summary>
 | 
					   /// <summary>
 | 
				
			||||||
   /// The value of this input element.
 | 
					   /// The value of this input element.
 | 
				
			||||||
 | 
				
			|||||||
@ -387,7 +387,7 @@ public partial class Picker<T> : FormComponent<T, string>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
   protected override void ResetValue()
 | 
					   protected override void ResetValue()
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
      _inputReference?.InputReference.Reset();
 | 
					      _inputReference?.Reset();
 | 
				
			||||||
      base.ResetValue();
 | 
					      base.ResetValue();
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,15 +1,15 @@
 | 
				
			|||||||
@namespace Connected.Components
 | 
					@namespace Connected.Components
 | 
				
			||||||
@typeparam T
 | 
					@typeparam T
 | 
				
			||||||
@inherits InputBase<T>
 | 
					@inherits DebouncedInput<T>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<CascadingValue Name="SubscribeToParentForm" Value="@base.SubscribeToParentForm" IsFixed="true">
 | 
					<CascadingValue Name="SubscribeToParentForm" Value="@SubscribeToParentForm" IsFixed="true">
 | 
				
			||||||
    <InputControl Label="@Label"
 | 
					    <InputControl Label="@Label"
 | 
				
			||||||
                     Variant="@Variant"
 | 
					                     Variant="@Variant"
 | 
				
			||||||
                     HelperText="@HelperText"
 | 
					                     HelperText="@HelperText"
 | 
				
			||||||
                     HelperTextOnFocus="@HelperTextOnFocus"
 | 
					                     HelperTextOnFocus="@HelperTextOnFocus"
 | 
				
			||||||
                     CounterText="@GetCounterText()"
 | 
					                     CounterText="@GetCounterText()"
 | 
				
			||||||
                     FullWidth="@FullWidth"
 | 
					                     FullWidth="@FullWidth"
 | 
				
			||||||
                     class="@ClassList"
 | 
					                     Class="@ClassList"
 | 
				
			||||||
                     Error="@HasErrors"
 | 
					                     Error="@HasErrors"
 | 
				
			||||||
                     ErrorText="@GetErrorText()"
 | 
					                     ErrorText="@GetErrorText()"
 | 
				
			||||||
                     ErrorId="@ErrorId"
 | 
					                     ErrorId="@ErrorId"
 | 
				
			||||||
@ -48,6 +48,7 @@
 | 
				
			|||||||
                              Margin="@Margin"
 | 
					                              Margin="@Margin"
 | 
				
			||||||
                              OnBlur="@OnBlurred"
 | 
					                              OnBlur="@OnBlurred"
 | 
				
			||||||
                              OnKeyDown="@InvokeKeyDown"
 | 
					                              OnKeyDown="@InvokeKeyDown"
 | 
				
			||||||
 | 
					                              OnInternalInputChanged="OnChange"
 | 
				
			||||||
                              OnKeyPress="@InvokeKeyPress"
 | 
					                              OnKeyPress="@InvokeKeyPress"
 | 
				
			||||||
                              OnKeyUp="@InvokeKeyUp"
 | 
					                              OnKeyUp="@InvokeKeyUp"
 | 
				
			||||||
                              KeyDownPreventDefault="KeyDownPreventDefault"
 | 
					                              KeyDownPreventDefault="KeyDownPreventDefault"
 | 
				
			||||||
@ -56,7 +57,6 @@
 | 
				
			|||||||
                              HideSpinButtons="true"
 | 
					                              HideSpinButtons="true"
 | 
				
			||||||
                              Clearable="@Clearable"
 | 
					                              Clearable="@Clearable"
 | 
				
			||||||
                              OnClearButtonClick="@OnClearButtonClick"
 | 
					                              OnClearButtonClick="@OnClearButtonClick"
 | 
				
			||||||
                              Class="@CompiledClassList.Build()"
 | 
					 | 
				
			||||||
                              Pattern="@Pattern"/>
 | 
					                              Pattern="@Pattern"/>
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
@ -83,10 +83,8 @@
 | 
				
			|||||||
                             OnAdornmentClick="@OnAdornmentClick"
 | 
					                             OnAdornmentClick="@OnAdornmentClick"
 | 
				
			||||||
                             Error="@HasError"
 | 
					                             Error="@HasError"
 | 
				
			||||||
                             Immediate="@Immediate"
 | 
					                             Immediate="@Immediate"
 | 
				
			||||||
                             Margin="@Margin" 
 | 
					                             Margin="@Margin" OnBlur="@OnBlurred"
 | 
				
			||||||
                             OnBlur="@OnBlurred"
 | 
					 | 
				
			||||||
                             Clearable="@Clearable"
 | 
					                             Clearable="@Clearable"
 | 
				
			||||||
                              Class="@CompiledClassList.Build()"
 | 
					 | 
				
			||||||
                             OnClearButtonClick="@OnClearButtonClick"/>
 | 
					                             OnClearButtonClick="@OnClearButtonClick"/>
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            </CascadingValue>
 | 
					            </CascadingValue>
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Components.Web;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Connected.Components;
 | 
					namespace Connected.Components;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public partial class TextField<T> : InputBase<T>
 | 
					public partial class TextField<T> : DebouncedInput<T>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Mask? _maskReference;
 | 
					    private Mask? _maskReference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -19,7 +19,7 @@ public partial class TextField<T> : InputBase<T>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	internal override InputType GetInputType() => InputType;
 | 
						internal override InputType GetInputType() => InputType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private string GetCounterText() => base.Counter == null ? string.Empty : (base.Counter == 0 ? (string.IsNullOrEmpty(base.Text) ? "0" : $"{base.Text.Length}") : ((string.IsNullOrEmpty(base.Text) ? "0" : $"{base.Text.Length}") + $" / {base.Counter}"));
 | 
						private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") : ((string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") + $" / {Counter}"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// <summary>
 | 
						/// <summary>
 | 
				
			||||||
	/// Show clear button.
 | 
						/// Show clear button.
 | 
				
			||||||
@ -32,25 +32,10 @@ public partial class TextField<T> : InputBase<T>
 | 
				
			|||||||
	/// </summary>
 | 
						/// </summary>
 | 
				
			||||||
	[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
 | 
						[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*protected string ClassList =>
 | 
					    protected string ClassList =>
 | 
				
			||||||
		new CssBuilder("input-input-control")
 | 
							new CssBuilder("input-input-control")
 | 
				
			||||||
		.AddClass(base.AdditionalClassList)
 | 
							.AddClass(base.AdditionalClassList)
 | 
				
			||||||
		.Build();*/
 | 
							.Build();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	protected virtual CssBuilder CompiledClassList
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		get
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return new CssBuilder("input-input-control")
 | 
					 | 
				
			||||||
			.AddClass(ClassList);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/// <summary>
 | 
					 | 
				
			||||||
	/// A space separated list of class names, added on top of the default class list.
 | 
					 | 
				
			||||||
	/// </summary>
 | 
					 | 
				
			||||||
	[Parameter]
 | 
					 | 
				
			||||||
	public string? ClassList { get; set; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public override ValueTask FocusAsync()
 | 
						public override ValueTask FocusAsync()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -143,10 +128,10 @@ public partial class TextField<T> : InputBase<T>
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		if (_mask != null)
 | 
							if (_mask != null)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var textValue = base.Converter.Convert(value);
 | 
								var textValue = Converter.Convert(value);
 | 
				
			||||||
			_mask.SetText(textValue);
 | 
								_mask.SetText(textValue);
 | 
				
			||||||
			textValue = Mask.GetCleanText();
 | 
								textValue = Mask.GetCleanText();
 | 
				
			||||||
			value = base.Converter.ConvertBack(textValue);
 | 
								value = Converter.ConvertBack(textValue);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return base.SetValueAsync(value, updateText);
 | 
							return base.SetValueAsync(value, updateText);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user