Compare commits
	
		
			No commits in common. "edcc8661e391f12743c2faecf25dba895f89d2b7" and "25606b926b9d53576a8d2f5801547be1a49fb6e3" have entirely different histories.
		
	
	
		
			edcc8661e3
			...
			25606b926b
		
	
		
@ -143,7 +143,7 @@ public abstract class FormComponent<T, U> : UIComponent, IFormComponent, IDispos
 | 
			
		||||
	 /// Return the validation error text or the conversion error message.
 | 
			
		||||
	 /// </summary>
 | 
			
		||||
	 /// <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
 | 
			
		||||
		  if (!IsNullOrWhiteSpace(ErrorText))
 | 
			
		||||
@ -152,8 +152,6 @@ public abstract class FormComponent<T, U> : UIComponent, IFormComponent, IDispos
 | 
			
		||||
		  if (!IsNullOrWhiteSpace(ConversionErrorMessage))
 | 
			
		||||
				return ConversionErrorMessage;
 | 
			
		||||
 | 
			
		||||
			if (test) return "Error: test";
 | 
			
		||||
 | 
			
		||||
		  return null;
 | 
			
		||||
	 }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
using System.Timers;
 | 
			
		||||
using Connected.Annotations;
 | 
			
		||||
using Connected.Utilities.BindingConverters;
 | 
			
		||||
using Microsoft.AspNetCore.Components;
 | 
			
		||||
 | 
			
		||||
namespace Connected.Components;
 | 
			
		||||
 | 
			
		||||
@ -3,23 +3,6 @@
 | 
			
		||||
@inherits InputBase<T>
 | 
			
		||||
 | 
			
		||||
<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)
 | 
			
		||||
	{
 | 
			
		||||
	    <InputAdornment Class="@AdornmentClassname" 
 | 
			
		||||
@ -32,7 +15,7 @@
 | 
			
		||||
                AriaLabel="@AdornmentAriaLabel"
 | 
			
		||||
        />
 | 
			
		||||
	}
 | 
			
		||||
    <InputContent>
 | 
			
		||||
 | 
			
		||||
	@if (Lines > 1)
 | 
			
		||||
	{
 | 
			
		||||
	    <textarea class="@InputClassname"
 | 
			
		||||
@ -63,7 +46,6 @@
 | 
			
		||||
        > 
 | 
			
		||||
            @Text
 | 
			
		||||
        </textarea>
 | 
			
		||||
        
 | 
			
		||||
        @*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*@
 | 
			
		||||
	}
 | 
			
		||||
@ -122,10 +104,15 @@
 | 
			
		||||
 | 
			
		||||
	@if (_showClearable && !Disabled)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        <IconButton Class="@ClearButtonClassname"
 | 
			
		||||
                    Color="@ThemeColor.Default" 
 | 
			
		||||
                    Icon="@ClearIcon" 
 | 
			
		||||
                    Size="@Size.Small" 
 | 
			
		||||
                    OnClick="@ClearButtonClickHandlerAsync"
 | 
			
		||||
                    tabindex="-1"
 | 
			
		||||
                />
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	@if (Adornment == Adornment.End)
 | 
			
		||||
	{
 | 
			
		||||
	    <InputAdornment Class="@AdornmentClassname" 
 | 
			
		||||
@ -155,12 +142,4 @@
 | 
			
		||||
            </Button>
 | 
			
		||||
	    </div>
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        </InputContent>
 | 
			
		||||
        
 | 
			
		||||
    </CascadingValue>  
 | 
			
		||||
   
 | 
			
		||||
    </InputControl>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,191 +2,11 @@
 | 
			
		||||
using Connected.Utilities;
 | 
			
		||||
using Microsoft.AspNetCore.Components;
 | 
			
		||||
using Microsoft.AspNetCore.Components.Web;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Timers;
 | 
			
		||||
 | 
			
		||||
namespace Connected.Components;
 | 
			
		||||
 | 
			
		||||
public partial class Input<T> : InputBase<T>
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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));
 | 
			
		||||
 | 
			
		||||
@ -211,79 +31,15 @@ public partial class Input<T> : InputBase<T>
 | 
			
		||||
 | 
			
		||||
   protected string InputTypeString => InputType.ToDescription();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
         return Task.CompletedTask;
 | 
			
		||||
      _isFocused = true;
 | 
			
		||||
      return SetTextAsync(args?.Value as string);
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected async Task OnChange(ChangeEventArgs args)
 | 
			
		||||
   {
 | 
			
		||||
		if (TextChangeDelay > 0 && _timer != null)
 | 
			
		||||
		{
 | 
			
		||||
			_timer.Stop();
 | 
			
		||||
			await UpdateValuePropertyAsync(false);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
   {
 | 
			
		||||
      _internalText = args?.Value as string;
 | 
			
		||||
      await OnInternalInputChanged.InvokeAsync(args);
 | 
			
		||||
@ -293,8 +49,6 @@ public partial class Input<T> : InputBase<T>
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
   /// <summary>
 | 
			
		||||
   /// Paste hook for descendants.
 | 
			
		||||
   /// </summary>
 | 
			
		||||
@ -410,12 +164,12 @@ public partial class Input<T> : InputBase<T>
 | 
			
		||||
         UpdateClearable(Text);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*protected override async Task UpdateValuePropertyAsync(bool updateText)
 | 
			
		||||
   protected override async Task UpdateValuePropertyAsync(bool updateText)
 | 
			
		||||
   {
 | 
			
		||||
      await base.UpdateValuePropertyAsync(updateText);
 | 
			
		||||
      if (Clearable)
 | 
			
		||||
         UpdateClearable(Value);
 | 
			
		||||
   }*/
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
 | 
			
		||||
   {
 | 
			
		||||
@ -442,33 +196,6 @@ public partial class Input<T> : InputBase<T>
 | 
			
		||||
      {
 | 
			
		||||
         // in WASM (or in BSS with TextUpdateSuppression==false) we always update
 | 
			
		||||
         _internalText = Text;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
		string baseTypeName = typeof(T).Name;
 | 
			
		||||
		if (IsNumericType(baseTypeName) && InputType !=InputType.Number)
 | 
			
		||||
		{
 | 
			
		||||
			InputType = InputType.Number;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
	private bool IsNumericType(string type)
 | 
			
		||||
	{
 | 
			
		||||
		switch (type.ToLower())
 | 
			
		||||
		{
 | 
			
		||||
			case "uint16":
 | 
			
		||||
			case "uint32":
 | 
			
		||||
			case "uint64":
 | 
			
		||||
			case "int16":
 | 
			
		||||
			case "int32":
 | 
			
		||||
			case "int64":
 | 
			
		||||
			case "int":
 | 
			
		||||
			case "double":
 | 
			
		||||
			case "decimal":
 | 
			
		||||
			case "float":
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -220,7 +220,6 @@ public abstract class InputBase<T> : FormComponent<T, string>
 | 
			
		||||
            await UpdateValuePropertyAsync(false);
 | 
			
		||||
         await TextChanged.InvokeAsync(Text);
 | 
			
		||||
      }
 | 
			
		||||
		
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /// <summary>
 | 
			
		||||
@ -330,11 +329,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
 | 
			
		||||
   /// Fired when the Value property changes.
 | 
			
		||||
   /// </summary>
 | 
			
		||||
   [Parameter]
 | 
			
		||||
   public EventCallback<T> ValueChanged
 | 
			
		||||
	{
 | 
			
		||||
		get;
 | 
			
		||||
		set;
 | 
			
		||||
	}
 | 
			
		||||
   public EventCallback<T> ValueChanged { get; set; }
 | 
			
		||||
 | 
			
		||||
   /// <summary>
 | 
			
		||||
   /// The value of this input element.
 | 
			
		||||
 | 
			
		||||
@ -387,7 +387,7 @@ public partial class Picker<T> : FormComponent<T, string>
 | 
			
		||||
 | 
			
		||||
   protected override void ResetValue()
 | 
			
		||||
   {
 | 
			
		||||
      _inputReference?.InputReference.Reset();
 | 
			
		||||
      _inputReference?.Reset();
 | 
			
		||||
      base.ResetValue();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,15 @@
 | 
			
		||||
@namespace Connected.Components
 | 
			
		||||
@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"
 | 
			
		||||
                     Variant="@Variant"
 | 
			
		||||
                     HelperText="@HelperText"
 | 
			
		||||
                     HelperTextOnFocus="@HelperTextOnFocus"
 | 
			
		||||
                     CounterText="@GetCounterText()"
 | 
			
		||||
                     FullWidth="@FullWidth"
 | 
			
		||||
                     class="@ClassList"
 | 
			
		||||
                     Class="@ClassList"
 | 
			
		||||
                     Error="@HasErrors"
 | 
			
		||||
                     ErrorText="@GetErrorText()"
 | 
			
		||||
                     ErrorId="@ErrorId"
 | 
			
		||||
@ -48,6 +48,7 @@
 | 
			
		||||
                              Margin="@Margin"
 | 
			
		||||
                              OnBlur="@OnBlurred"
 | 
			
		||||
                              OnKeyDown="@InvokeKeyDown"
 | 
			
		||||
                              OnInternalInputChanged="OnChange"
 | 
			
		||||
                              OnKeyPress="@InvokeKeyPress"
 | 
			
		||||
                              OnKeyUp="@InvokeKeyUp"
 | 
			
		||||
                              KeyDownPreventDefault="KeyDownPreventDefault"
 | 
			
		||||
@ -56,7 +57,6 @@
 | 
			
		||||
                              HideSpinButtons="true"
 | 
			
		||||
                              Clearable="@Clearable"
 | 
			
		||||
                              OnClearButtonClick="@OnClearButtonClick"
 | 
			
		||||
                              Class="@CompiledClassList.Build()"
 | 
			
		||||
                              Pattern="@Pattern"/>
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
@ -83,10 +83,8 @@
 | 
			
		||||
                             OnAdornmentClick="@OnAdornmentClick"
 | 
			
		||||
                             Error="@HasError"
 | 
			
		||||
                             Immediate="@Immediate"
 | 
			
		||||
                             Margin="@Margin" 
 | 
			
		||||
                             OnBlur="@OnBlurred"
 | 
			
		||||
                             Margin="@Margin" OnBlur="@OnBlurred"
 | 
			
		||||
                             Clearable="@Clearable"
 | 
			
		||||
                              Class="@CompiledClassList.Build()"
 | 
			
		||||
                             OnClearButtonClick="@OnClearButtonClick"/>
 | 
			
		||||
                }
 | 
			
		||||
            </CascadingValue>
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Components.Web;
 | 
			
		||||
 | 
			
		||||
namespace Connected.Components;
 | 
			
		||||
 | 
			
		||||
public partial class TextField<T> : InputBase<T>
 | 
			
		||||
public partial class TextField<T> : DebouncedInput<T>
 | 
			
		||||
{
 | 
			
		||||
    private Mask? _maskReference;
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ public partial class TextField<T> : InputBase<T>
 | 
			
		||||
 | 
			
		||||
	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>
 | 
			
		||||
	/// Show clear button.
 | 
			
		||||
@ -32,25 +32,10 @@ public partial class TextField<T> : InputBase<T>
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
 | 
			
		||||
 | 
			
		||||
    /*protected string ClassList =>
 | 
			
		||||
    protected string ClassList =>
 | 
			
		||||
		new CssBuilder("input-input-control")
 | 
			
		||||
		.AddClass(base.AdditionalClassList)
 | 
			
		||||
		.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; }
 | 
			
		||||
		.Build();
 | 
			
		||||
 | 
			
		||||
	public override ValueTask FocusAsync()
 | 
			
		||||
	{
 | 
			
		||||
@ -143,10 +128,10 @@ public partial class TextField<T> : InputBase<T>
 | 
			
		||||
	{
 | 
			
		||||
		if (_mask != null)
 | 
			
		||||
		{
 | 
			
		||||
			var textValue = base.Converter.Convert(value);
 | 
			
		||||
			var textValue = Converter.Convert(value);
 | 
			
		||||
			_mask.SetText(textValue);
 | 
			
		||||
			textValue = Mask.GetCleanText();
 | 
			
		||||
			value = base.Converter.ConvertBack(textValue);
 | 
			
		||||
			value = Converter.ConvertBack(textValue);
 | 
			
		||||
		}
 | 
			
		||||
		return base.SetValueAsync(value, updateText);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user