Prograss - Input field

features/refactor
stm 2 years ago
parent c5e97f9600
commit 3ea88592ce

@ -20,7 +20,7 @@
@if (CloseGlyphVisible)
{
<div class="alert-close">
<GlyphButton ClassList="size-small" Glyph="@CloseGlyph" Clicked="OnCloseGlyphClick" />
<IconButton ClassList="size-small" Icon="@CloseGlyph" Clicked="OnCloseGlyphClick" />
</div>
}
</div>

@ -19,7 +19,7 @@
TextChanged="OnTextChanged" OnBlur="OnInputBlurred"
OnKeyDown="@this.OnInputKeyDown"
OnKeyUp="@this.OnInputKeyUp" autocomplete=@("disabled-"+Guid.NewGuid()) KeyUpPreventDefault="KeyUpPreventDefault"
Placeholder="@Placeholder" Immediate="true"
Placeholder="@Placeholder" ChangeTextImmediately="true"
InputMode="@InputMode" Pattern="@Pattern"
T="string" />

@ -2,20 +2,20 @@
@inherits ButtonBase
@using Connected.Extensions;
@using Connected.Components;
<Element disabled="@Disabled"
title="@GlyphTitle"
type="@ButtonType.ToDescription()"
title="@IconTitle"
type="@ButtonType.ToString()"
ClassList="@CompiledClassList.ToString()"
HtmlTag="@HtmlTag"
PreventOnClickPropagation="PreventOnClickPropagation"
@attributes="CustomAttributes"
@onclick="OnClick">
@if (!String.IsNullOrEmpty(Glyph))
@if (!String.IsNullOrEmpty(Icon))
{
<span name="glyph-container" class="glyph-button-label">
<Icon Glyph="@Glyph" />
<Icon Glyph="@Icon" />
</span>
}
else

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Components;
namespace Connected.Components;
public partial class GlyphButton : ButtonBase
public partial class IconButton : ButtonBase
{
/// <summary>
/// Contains the default container classlist and the user defined classes.
@ -28,16 +28,16 @@ public partial class GlyphButton : ButtonBase
#region Content placeholders
/// <summary>
/// The Glyph that will be used in the component.
/// The Icon that will be used in the component.
/// </summary>
[Parameter]
public string? Glyph { get; set; }
public string? Icon { get; set; }
/// <summary>
/// GlyphTitle of the icon used for accessibility.
/// </summary>
[Parameter]
public string? GlyphTitle { get; set; }
public string? IconTitle { get; set; }
#endregion
#region Styling properties

@ -2,12 +2,12 @@
@inherits UIComponent
<GlyphButton aria-pressed="@Toggled.ToString()"
<IconButton aria-pressed="@Toggled.ToString()"
ClassList="@ClassList"
Clicked="Toggle"
Disabled="Disabled"
Glyph="@(Toggled ? ToggledGlyph : Glyph)"
GlyphTitle="@(Toggled && ToggledGlyphTitle != null ? ToggledGlyphTitle : GlyphTitle)"
Icon="@(Toggled ? ToggledGlyph : Glyph)"
IconTitle="@(Toggled && ToggledGlyphTitle != null ? ToggledGlyphTitle : GlyphTitle)"
Variant="Variant"
@attributes="CustomAttributes"
/>

@ -2,7 +2,7 @@
namespace Connected.Components;
public partial class ToggleGlyphButton : UIComponent
public partial class ToggleIconButton : UIComponent
{
#region EventCallbacks
/// <summary>

@ -31,7 +31,7 @@
{
@if (PreviousButtonTemplate == null)
{
<IconButton tabindex="1" aria-label="Go to previous" Class="@NavigationButtonsClassName" Style="z-index:3;opacity:0.75" Icon="@PreviousIcon" OnClick="Previous" Color="ThemeColor.Inherit" />
<IconButton tabindex="1" aria-label="Go to previous" Class="@NavigationButtonsClassName" Style="z-index:3;opacity:0.75" Icon="@PreviousIcon" Clicked="Previous" Color="ThemeColor.Inherit" />
}
else
{
@ -51,7 +51,7 @@
int current = i;
if (BulletTemplate == null)
{
<IconButton tabindex="@(i+3)" aria-label="@(i+1)" Class="@BulletsButtonsClassName" Style="z-index:3;opacity:0.75" Icon="@(current == SelectedIndex ? CheckedIcon : UncheckedIcon)" OnClick="(() => MoveTo(current))" Color="ThemeColor.Inherit" />
<IconButton tabindex="@(i+3)" aria-label="@(i+1)" Class="@BulletsButtonsClassName" Style="z-index:3;opacity:0.75" Icon="@(current == SelectedIndex ? CheckedIcon : UncheckedIcon)" Clicked="(() => MoveTo(current))" Color="ThemeColor.Inherit" />
}
else
{
@ -69,7 +69,7 @@
{
@if (NextButtonTemplate == null)
{
<IconButton tabindex="2" aria-label="Go to next" Class="@NavigationButtonsClassName" Style="z-index:3;opacity:0.75" Icon="@NextIcon" OnClick="Next" Color="ThemeColor.Inherit" />
<IconButton tabindex="2" aria-label="Go to next" Class="@NavigationButtonsClassName" Style="z-index:3;opacity:0.75" Icon="@NextIcon" Clicked="Next" Color="ThemeColor.Inherit" />
}
else
{

@ -27,7 +27,7 @@
}
@if (OnClose.HasDelegate || ChipSet?.AllClosable==true)
{
<IconButton Class="chip-close-button" Icon="@(String.IsNullOrEmpty(CloseIcon) ? $"{Icons.Material.Filled.Cancel}" : $"{CloseIcon}")" OnClick="OnCloseHandler" Size="Size.Small"/>
<IconButton Class="chip-close-button" Icon="@(String.IsNullOrEmpty(CloseIcon) ? $"{Icons.Material.Filled.Cancel}" : $"{CloseIcon}")" Clicked="OnCloseHandler" Size="Size.Small"/>
}
</span>
</div>

@ -12,12 +12,12 @@
<PickerToolbar DisableToolbar="@DisableToolbar" Class="picker-color-toolbar">
@if (PickerVariant != PickerVariant.Static)
{
<IconButton Class="pa-1 mud-close-picker-button" Size="Size.Small" Color="ThemeColor.Inherit" Icon="@CloseIcon" OnClick="@GetEventCallback()" />
<IconButton Class="pa-1 mud-close-picker-button" Size="Size.Small" Color="ThemeColor.Inherit" Icon="@CloseIcon" Clicked="@GetEventCallback()" />
}
<Spacer />
<IconButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Spectrum)" Icon="@SpectrumIcon" OnClick="(() => ChangeView(ColorPickerView.Spectrum))" />
<IconButton Class="pa-1 mx-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Grid)" Icon="@GridIcon" OnClick="(() => ChangeView(ColorPickerView.Grid))" />
<IconButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Palette)" Icon="@PaletteIcon" OnClick="(() => ChangeView(ColorPickerView.Palette))" />
<IconButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Spectrum)" Icon="@SpectrumIcon" Clicked="(() => ChangeView(ColorPickerView.Spectrum))" />
<IconButton Class="pa-1 mx-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Grid)" Icon="@GridIcon" Clicked="(() => ChangeView(ColorPickerView.Grid))" />
<IconButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Palette)" Icon="@PaletteIcon" Clicked="(() => ChangeView(ColorPickerView.Palette))" />
</PickerToolbar>
<PickerContent Class="picker-color-content">
@if (!DisableColorField)
@ -126,7 +126,7 @@
@if (!DisableModeSwitch)
{
<div class="picker-control-switch">
<IconButton OnClick="ChangeMode" Icon="@ImportExportIcon" Class="pa-1 me-n1"></IconButton>
<IconButton Clicked="ChangeMode" Icon="@ImportExportIcon" Class="pa-1 me-n1"></IconButton>
</div>
}
</div>

@ -129,7 +129,7 @@
<IconButton
Class="table-row-expander"
Icon="@(g.IsExpanded ? Icons.Material.Filled.ExpandMore : Icons.Material.Filled.ChevronRight)"
OnClick="@(() => ToggleGroupExpansion(g))" />
Clicked="@(() => ToggleGroupExpansion(g))" />
@if (GroupedColumn.GroupTemplate == null)
{
@ -377,7 +377,7 @@
@if (column == null)
{
<Item xs="1" Class="d-flex">
<IconButton Class="remove-filter-button" Icon="@Icons.Material.Filled.Close" OnClick="@filter.RemoveFilter" Size="@Size.Small" Style="align-self:flex-end"></IconButton>
<IconButton Class="remove-filter-button" Icon="@Icons.Material.Filled.Close" Clicked="@filter.RemoveFilter" Size="@Size.Small" Style="align-self:flex-end"></IconButton>
</Item>
<Item xs="4">
<Select T="string" Value="@f.Field" ValueChanged="@filter.FieldChanged" FullWidth="true" Label="Column" Dense="true" Margin="@Margin.Dense"
@ -401,12 +401,12 @@
@if (filter.dataType == typeof(string) && !(f.Operator ?? "").EndsWith("empty"))
{
<TextField T="string" Value="@filter._valueString" ValueChanged="@filter.StringValueChanged" FullWidth="true" Label="Value" Placeholder="Filter value" Margin="@Margin.Dense"
Immediate="true" Class="filter-input" />
ChangeTextImmediately="true" Class="filter-input" />
}
else if (filter.isNumber && !(f.Operator ?? "").EndsWith("empty"))
{
<NumericField T="double?" Value="@filter._valueNumber" ValueChanged="@filter.NumberValueChanged" FullWidth="true" Label="Value" Placeholder="Filter value" Margin="@Margin.Dense"
Immediate="true" Class="filter-input" Culture="@filter.filterColumn?.Culture" />
ChangeTextImmediately="true" Class="filter-input" Culture="@filter.filterColumn?.Culture" />
}
else if (filter.isEnum)
{
@ -442,7 +442,7 @@
else if (filter.dataType == typeof(Guid))
{
<TextField T="string" Value="@filter._valueString" ValueChanged="@filter.StringValueChanged" FullWidth="true" Label="Value" Placeholder="Filter value" Margin="@Margin.Dense"
Immediate="true" Class="filter-input" />
ChangeTextImmediately="true" Class="filter-input" />
}
</Item>
}
@ -461,12 +461,12 @@
@if (filter.dataType == typeof(string) && !(f.Operator ?? "").EndsWith("empty"))
{
<TextField T="string" Value="@filter._valueString" ValueChanged="@filter.StringValueChanged" FullWidth="true" Placeholder="Filter value" Margin="@Margin.Dense"
Immediate="true" Class="filter-input" />
ChangeTextImmediately="true" Class="filter-input" />
}
else if (filter.isNumber && !(f.Operator ?? "").EndsWith("empty"))
{
<NumericField T="double?" Value="@filter._valueNumber" ValueChanged="@filter.NumberValueChanged" FullWidth="true" Placeholder="Filter value" Margin="@Margin.Dense"
Immediate="true" Class="filter-input" Culture="@filter.filterColumn?.Culture" />
ChangeTextImmediately="true" Class="filter-input" Culture="@filter.filterColumn?.Culture" />
}
else if (filter.isEnum)
{
@ -502,7 +502,7 @@
else if (filter.dataType == typeof(Guid))
{
<TextField T="string" Value="@filter._valueString" ValueChanged="@filter.StringValueChanged" FullWidth="true" Label="Value" Placeholder="Filter value" Margin="@Margin.Dense"
Immediate="true" Class="filter-input" />
ChangeTextImmediately="true" Class="filter-input" />
}
</Item>
}

@ -20,10 +20,10 @@
@Info
</TextContent>
<div class="table-pagination-actions">
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.FirstPage" Disabled="@BackButtonsDisabled" @onclick="@(() => DataGrid.NavigateTo(Page.First))"/>
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.NavigateBefore" Disabled="@BackButtonsDisabled" @onclick="@(() => DataGrid.NavigateTo(Page.Previous))"/>
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.NavigateNext" Disabled="@ForwardButtonsDisabled" @onclick="@(() => DataGrid.NavigateTo(Page.Next))"/>
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.LastPage" Disabled="@ForwardButtonsDisabled" @onclick="@(() => DataGrid.NavigateTo(Page.Last))"/>
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.FirstPage" Disabled="@BackButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.First))" />
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.NavigateBefore" Disabled="@BackButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Previous))" />
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.NavigateNext" Disabled="@ForwardButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Next))" />
<IconButton Class="flip-x-rtl" Icon="@Icons.Material.Filled.LastPage" Disabled="@ForwardButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Last))" />
</div>
</ToolBar>

@ -14,11 +14,11 @@
<Stack Row="true">
@if (dataType == typeof(string) && !(_operator ?? "").EndsWith("empty"))
{
<TextField T="string" Value="@_valueString" ValueChanged="@StringValueChanged" FullWidth="true" Placeholder="Filter value" Margin="@Margin.Dense" Immediate="true" />
<TextField T="string" Value="@_valueString" ValueChanged="@StringValueChanged" FullWidth="true" Placeholder="Filter value" Margin="@Margin.Dense" ChangeTextImmediately="true" />
}
else if (isNumber && !(_operator ?? "").EndsWith("empty"))
{
<NumericField T="double?" Culture="@Column.Culture" Value="@_valueNumber" ValueChanged="@NumberValueChanged" FullWidth="true" Placeholder="Filter value" Margin="@Margin.Dense" Immediate="true"></NumericField>
<NumericField T="double?" Culture="@Column.Culture" Value="@_valueNumber" ValueChanged="@NumberValueChanged" FullWidth="true" Placeholder="Filter value" Margin="@Margin.Dense" ChangeTextImmediately="true"></NumericField>
}
else if (isEnum)
{
@ -58,7 +58,7 @@
}
}
</Menu>
<GlyphButton Class="align-self-center" Icon="@Icons.Material.Filled.FilterAltOff" Size="@Size.Small" Clicked="@ClearFilter"></GlyphButton>
<IconButton Class="align-self-center" Icon="@Icons.Material.Filled.FilterAltOff" Size="@Size.Small" Clicked="@ClearFilter"></IconButton>
</Stack>
}
}

@ -41,11 +41,11 @@ else if (Column != null && !Column.Hidden)
{
if (_initialDirection == SortDirection.None)
{
<IconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" OnClick="@SortChangedAsync"></IconButton>
<IconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Clicked="@SortChangedAsync"></IconButton>
}
else
{
<IconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" OnClick="@SortChangedAsync"></IconButton>
<IconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Clicked="@SortChangedAsync"></IconButton>
if(DataGrid.SortMode == SortMode.Multiple)
{
<span class="sort-index mud-text-disabled">@(Column.SortIndex + 1)</span>
@ -57,11 +57,11 @@ else if (Column != null && !Column.Hidden)
{
if (hasFilter)
{
<IconButton Class="filter-button filtered" Icon="@Icons.Material.Filled.FilterAlt" Size="@Size.Small" OnClick="@OpenFilters"></IconButton>
<IconButton Class="filter-button filtered" Icon="@Icons.Material.Filled.FilterAlt" Size="@Size.Small" Clicked="@OpenFilters"></IconButton>
}
else if (showFilterIcon)
{
<IconButton Class="filter-button" Icon="@Icons.Material.Outlined.FilterAlt" Size="@Size.Small" OnClick="@AddFilter"></IconButton>
<IconButton Class="filter-button" Icon="@Icons.Material.Outlined.FilterAlt" Size="@Size.Small" Clicked="@AddFilter"></IconButton>
}
}

@ -47,11 +47,11 @@
<div class="picker-calendar-header-switch">
@if (!FixYear.HasValue)
{
<IconButton aria-label="@prevLabel" Icon="@PreviousIcon" OnClick="OnPreviousYearClick" Class="flip-x-rtl" />
<IconButton aria-label="@prevLabel" Icon="@PreviousIcon" Clicked="OnPreviousYearClick" Class="flip-x-rtl" />
<button type="button" class="picker-slide-transition mud-picker-calendar-header-transition" @onclick="OnYearClick" @onclick:stopPropagation="true">
<TextContent Typo="Typo.body1" Align="Align.Center">@calendarYear</TextContent>
</button>
<IconButton aria-label="@nextLabel" Icon="@NextIcon" OnClick="OnNextYearClick" Class="flip-x-rtl" />
<IconButton aria-label="@nextLabel" Icon="@NextIcon" Clicked="OnNextYearClick" Class="flip-x-rtl" />
}
else
{
@ -77,11 +77,11 @@
<div class="picker-calendar-header-switch">
@if (!FixMonth.HasValue)
{
<IconButton aria-label="@prevLabel" Class="picker-nav-button-prev mud-flip-x-rtl" Icon="@PreviousIcon" OnClick="OnPreviousMonthClick" />
<IconButton aria-label="@prevLabel" Class="picker-nav-button-prev mud-flip-x-rtl" Icon="@PreviousIcon" Clicked="OnPreviousMonthClick" />
<button type="button" class="picker-slide-transition mud-picker-calendar-header-transition mud-button-month" @onclick="(() => OnMonthClicked(tempMonth))" @onclick:stopPropagation="true">
<TextContent Typo="Typo.body1" Align="Align.Center">@GetMonthName(tempMonth)</TextContent>
</button>
<IconButton aria-label="@nextLabel" Class="picker-nav-button-next mud-flip-x-rtl" Icon="@NextIcon" OnClick="OnNextMonthClick" />
<IconButton aria-label="@nextLabel" Class="picker-nav-button-next mud-flip-x-rtl" Icon="@NextIcon" Clicked="OnNextMonthClick" />
}
else
{

@ -17,7 +17,7 @@
}
@if (CloseButton)
{
<IconButton aria-label="close" Icon="@CloseIcon" @onclick="Cancel"/>
<IconButton aria-label="close" Icon="@CloseIcon" Clicked="Cancel" />
}
</div>
}

@ -60,7 +60,7 @@ public partial class Form : UIComponent, IDisposable, IForm
/// <summary>
/// Validation debounce delay in milliseconds. This can help improve rendering performance of forms with real-time validation of inputs
/// i.e. when textfields have Immediate="true".
/// i.e. when textfields have ChangeTextImmediately="true".
/// </summary>
[Parameter]
[Category(CategoryTypes.Form.Behavior)]

@ -73,9 +73,9 @@ public abstract class DebouncedInput<T> : InputBase<T>
{
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
// so we set ChangeTextImmediately to true
if (DebounceInterval > 0)
Immediate = true;
ChangeTextImmediately = true;
}
private void SetTimer()

@ -2,26 +2,10 @@
@typeparam T
@inherits InputBase<T>
<InputControl Label="@Label"
Variant="@Variant"
HelperText="@HelperText"
HelperTextOnFocus="@HelperTextOnFocus"
CounterText="@GetCounterText()"
FullWidth="@FullWidth"
Class="@CompiledClassList.Build()"
Error="@HasErrors"
ErrorText="@ErrorText"
ErrorId="@ErrorId"
Disabled="@Disabled"
Margin="@Margin"
Required="@Required"
ForId="@FieldId">
<CascadingValue Name="SubscribeToParentForm" Value="@base.SubscribeToParentForm" IsFixed="true">
<div class="@CompiledWrapperClass.Build()">
@if (Adornment == Adornment.Start)
{
<InputAdornment Class="@AdornmentClassname"
<InputAdornment Class="@CompiledAdornmentClass.Build()"
Icon="@AdornmentIcon"
Color="@AdornmentColor"
Size="@IconSize"
@ -31,13 +15,14 @@
AriaLabel="@AdornmentAriaLabel"
/>
}
<InputContent>
@if (Lines > 1)
@if (NumberOfLines > 1)
{
<textarea class="@InputClassname"
<textarea class="@CompiledInputClass.Build()"
@ref="ElementReference"
rows="@Lines"
@attributes="CustomAttributes"
rows="@NumberOfLines"
style="@Style"
@attributes="@Attributes"
type="@InputTypeString"
placeholder="@Placeholder"
disabled=@Disabled
@ -58,18 +43,20 @@
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId">
aria-describedby="@ErrorId"
>
@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*@
}
else
{
<input class="@InputClassname"
<input class="@CompiledInputClass.Build()"
style="@Style"
@ref="ElementReference"
@attributes="CustomAttributes"
@attributes="@Attributes"
step="@Step"
type="@InputTypeString"
value="@_internalText"
@oninput="OnInput"
@ -98,7 +85,7 @@
@*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
*@
<div class="@InputClassname"
<div class="@CompiledInputClass.Build()"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
@onblur="@OnBlurred" @ref="@_elementReference1"
>
@ -108,7 +95,7 @@
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"
<div class="@CompiledInputClass.Build()"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
tabindex="@(InputType == InputType.Hidden && ChildContent != null ? 0 : -1)"
@onblur="@OnBlurred" @ref="@_elementReference1"
@ -120,13 +107,16 @@
@if (_showClearable && !Disabled)
{
<IconButton ClassList="@CompiledClearButtonClassList.Build()"
Icon="@ClearIcon"
Clicked="@ClearButtonClickHandlerAsync"
tabindex="-1"
/>
}
@if (Adornment == Adornment.End)
{
<InputAdornment Class="@AdornmentClassname"
<InputAdornment Class="@CompiledAdornmentClass.Build()"
Icon="@AdornmentIcon"
Color="@AdornmentColor"
Size="@IconSize"
@ -145,19 +135,14 @@
@if (!HideSpinButtons)
{
<div class="input-numeric-spin">
<Button Variant="Variant.Text" @onclick="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
<Button Variant="Variant.Text" Clicked="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
<Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
</Button>
<Button Variant="Variant.Text" @onclick="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
<Button Variant="Variant.Text" Clicked="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
<Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" />
</Button>
</div>
}
</InputContent>
</CascadingValue>
</InputControl>
</div>

@ -9,40 +9,19 @@ namespace Connected.Components;
public partial class Input<T> : InputBase<T>
{
/*
* Debounce
*
*/
#region Event Callbacks
/// <summary>
/// The current character counter, displayed below the text field.
/// Paste hook for descendants.
/// </summary>
[Parameter] public string CounterText { get; set; }
private System.Timers.Timer _timer;
private double _debounceInterval;
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
/// <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)
protected virtual async Task OnPaste(ClipboardEventArgs args)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
// not debounced, dispose timer if any
ClearTimer(suppressTick: false);
// do nothing
return;
}
SetTimer();
}
}
/// <summary>
/// callback to be called when the debounce interval has elapsed
@ -81,26 +60,6 @@ public partial class Input<T> : InputBase<T>
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();
@ -111,181 +70,9 @@ public partial class Input<T> : InputBase<T>
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(CompiledClearButtonClassList.Build())
.AddClass(CompiledHelperClassList.Build());
}
}
protected CssBuilder CompiledClearButtonClassList
{
get
{
return new CssBuilder()
.AddClass("me-n1", Adornment == Adornment.End && HideSpinButtons == false)
.AddClass("icon-button-edge-end", Adornment == Adornment.End && HideSpinButtons == true)
.AddClass("me-6", Adornment != Adornment.End && HideSpinButtons == false)
.AddClass("icon-button-edge-margin-end", Adornment != Adornment.End && HideSpinButtons == true);
}
}
/// <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));
protected CssBuilder CompiledClassList
{
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(CompiledClearButtonClassList.Build())
.AddClass(CompiledHelperClassList.Build());
}
}
protected string InputClassname => InputCssHelper.GetInputClassname(this);
protected string AdornmentClassname => InputCssHelper.GetAdornmentClassname(this);
/// <summary>
/// Type of the input element. It should be a valid HTML5 input type.
/// </summary>
[Parameter] public InputType InputType { get; set; } = InputType.Text;
internal override InputType GetInputType() => InputType;
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)
if (!ChangeTextImmediately)
return Task.CompletedTask;
_isFocused = true;
return SetTextAsync(args?.Value as string);
@ -303,7 +90,7 @@ public partial class Input<T> : InputBase<T>
{
_internalText = args?.Value as string;
await OnInternalInputChanged.InvokeAsync(args);
if (!Immediate)
if (!ChangeTextImmediately)
{
await SetTextAsync(args?.Value as string);
}
@ -312,24 +99,26 @@ public partial class Input<T> : InputBase<T>
}
/// <summary>
/// Paste hook for descendants.
/// Invokes the callback when the Up arrow button is clicked when the input is set to <see cref="InputType.Number"/>.
/// Note: use the optimized control <see cref="NumericField{T}"/> if you need to deal with numbers.
/// </summary>
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
[Parameter] public EventCallback OnIncrement { get; set; }
protected virtual async Task OnPaste(ClipboardEventArgs args)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
// do nothing
return;
}
/// <summary>
/// Invokes the callback when the Down arrow button is clicked when the input is set to <see cref="InputType.Number"/>.
/// Note: use the optimized control <see cref="NumericField{T}"/> if you need to deal with numbers.
/// </summary>
[Parameter] public EventCallback OnDecrement { get; set; }
/// <summary>
/// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null.
/// Button click event for clear button. Called after text and value has been cleared.
/// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
public ElementReference ElementReference { get; private set; }
private ElementReference _elementReference1;
/// <summary>
/// Mouse wheel event for input.
/// </summary>
[Parameter] public EventCallback<WheelEventArgs> OnMouseWheel { get; set; }
public override async ValueTask FocusAsync()
{
@ -361,20 +150,51 @@ public partial class Input<T> : InputBase<T>
return ElementReference.SelectRangeAsync(pos1, pos2);
}
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 virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
{
await SetTextAsync(string.Empty, updateValue: true);
await ElementReference.FocusAsync();
await OnClearButtonClick.InvokeAsync(e);
}
/// <summary>
/// Invokes the callback when the Up arrow button is clicked when the input is set to <see cref="InputType.Number"/>.
/// Note: use the optimized control <see cref="NumericField{T}"/> if you need to deal with numbers.
/// Custom input Attributes
/// </summary>
[Parameter] public EventCallback OnIncrement { get; set; }
[Parameter] public Dictionary<string, object>? Attributes { get; set; } = null;
#endregion
#region Style properties
/// <summary>
/// Invokes the callback when the Down arrow button is clicked when the input is set to <see cref="InputType.Number"/>.
/// Note: use the optimized control <see cref="MudNumericField{T}"/> if you need to deal with numbers.
/// Type of the input element. It should be a valid HTML5 input type.
/// </summary>
[Parameter] public EventCallback OnDecrement { get; set; }
[Parameter] public InputType InputType { get; set; } = InputType.Text;
private string ClearIcon = Icons.Material.Filled.Clear;
private string NumericUpIcon = Icons.Material.Filled.KeyboardArrowUp;
private string NumericDownIcon = Icons.Material.Filled.KeyboardArrowDown;
/// <summary>
/// Hides the spin buttons for <see cref="MudNumericField{T}"/>
/// Hides the spin buttons"/>
/// </summary>
[Parameter] public bool HideSpinButtons { get; set; } = true;
@ -383,65 +203,198 @@ public partial class Input<T> : InputBase<T>
/// </summary>
[Parameter] public bool Clearable { get; set; } = false;
/// <summary>
/// Button click event for clear button. Called after text and value has been cleared.
/// </summary>
[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
#region Wrapper class
[Parameter]
public string WrapperClass { get; set; } = string.Empty;
protected CssBuilder CompiledWrapperClass
{
get
{
return new CssBuilder("input")
.AddClass($"input-{Variant.ToDescription()}")
.AddClass($"input-adorned-{Adornment.ToDescription()}", Adornment != Adornment.None)
.AddClass($"input-margin-{Margin.ToDescription()}", when: () => Margin != Margin.None)
.AddClass("input-underline", when: () => DisableUnderLine == false && Variant != Variant.Outlined)
.AddClass("shrink", when: HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder))
.AddClass("disabled", Disabled)
.AddClass("input-error", HasErrors)
.AddClass("ltr", GetInputType() == InputType.Email || GetInputType() == InputType.Telephone)
.AddClass(WrapperClass);
}
}
/// <summary>
/// Mouse wheel event for input.
/// </summary>
[Parameter] public EventCallback<WheelEventArgs> OnMouseWheel { get; set; }
/// <summary>
/// Custom clear icon.
/// </summary>
[Parameter] public string ClearIcon { get; set; } = Icons.Material.Filled.Clear;
#endregion
#region Input field class
[Parameter]
public string InputClass { get; set; } = string.Empty;
protected CssBuilder CompiledInputClass
{
get
{
return new CssBuilder("input-slot")
.AddClass("input-root")
.AddClass($"input-root-{Variant.ToDescription()}")
.AddClass($"input-root-adorned-{Adornment.ToDescription()}", Adornment != Adornment.None)
.AddClass($"input-root-margin-{Margin.ToDescription()}", when: () => Margin != Margin.None)
.AddClass(InputClass);
}
}
#endregion
#region Adornment class
[Parameter]
public string AdornmentClass { get; set; } = string.Empty;
protected CssBuilder CompiledAdornmentClass
{
get
{
return new CssBuilder("input-adornment")
.AddClass($"input-adornment-{Adornment.ToDescription()}", Adornment != Adornment.None)
.AddClass($"text", !string.IsNullOrEmpty(AdornmentText))
.AddClass($"input-root-filled-shrink", Variant == Variant.Filled)
.AddClass(AdornmentClass);
}
}
#endregion
#region Clear icon class
[Parameter]
public string ClearButtonClass { get; set; } = string.Empty;
protected CssBuilder CompiledClearButtonClassList
{
get
{
return new CssBuilder()
.AddClass("me-n1", Adornment == Adornment.End && HideSpinButtons == false)
.AddClass("icon-button-edge-end", Adornment == Adornment.End && HideSpinButtons == true)
.AddClass("me-6", Adornment != Adornment.End && HideSpinButtons == false)
.AddClass("icon-button-edge-margin-end", Adornment != Adornment.End && HideSpinButtons == true)
.AddClass(ClearButtonClass);
}
}
#endregion
#region Helper container class
/// <summary>
/// Custom numeric up icon.
/// A space separated list of class names, added on top of the default helper container class list.
/// </summary>
[Parameter] public string NumericUpIcon { get; set; } = Icons.Material.Filled.KeyboardArrowUp;
[Parameter]
public string? HelperContainerClass { get; set; }
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(HelperContainerClass);
}
}
#endregion
#region Error container class -- still needs implementation
#endregion
#region Counter container class -- still needs implementation
#endregion
#endregion
#region Content placeholders
/// <summary>
/// Custom numeric down icon.
/// The current character counter, displayed below the text field.
/// </summary>
[Parameter] public string NumericDownIcon { get; set; } = Icons.Material.Filled.KeyboardArrowDown;
[Parameter] public string CounterText { get; set; }
private Size GetButtonSize() => Margin == Margin.Dense ? Size.Small : Size.Medium;
private System.Timers.Timer _timer;
private bool _showClearable;
private double _textChangeInterval;
private void UpdateClearable(object value)
/// <summary>
/// Interval to be awaited in MILLISECONDS before changing the Text value
/// </summary>
[Parameter]
public double TextChangeDelay
{
var showClearable = Clearable && ((value is string stringValue && !string.IsNullOrWhiteSpace(stringValue)) || (value is not string && value is not null));
if (_showClearable != showClearable)
_showClearable = showClearable;
get => _textChangeInterval;
set
{
if (NumericConverter<double>.AreEqual(_textChangeInterval, value))
return;
_textChangeInterval = value;
if (_textChangeInterval == 0)
{
// not debounced, dispose timer if any
ClearTimer(suppressTick: false);
return;
}
SetTimer();
}
}
protected override async Task UpdateTextPropertyAsync(bool updateValue)
private void SetTimer()
{
await base.UpdateTextPropertyAsync(updateValue);
if (Clearable)
UpdateClearable(Text);
if (_timer == null)
{
_timer = new System.Timers.Timer();
_timer.Elapsed += OnTimerTick;
_timer.AutoReset = false;
}
_timer.Interval = TextChangeDelay;
}
/*protected override async Task UpdateValuePropertyAsync(bool updateText)
private void ClearTimer(bool suppressTick = false)
{
await base.UpdateValuePropertyAsync(updateText);
if (Clearable)
UpdateClearable(Value);
}*/
if (_timer == null)
return;
var wasEnabled = _timer.Enabled;
_timer.Stop();
_timer.Elapsed -= OnTimerTick;
_timer.Dispose();
_timer = null;
if (wasEnabled && !suppressTick)
OnTimerTickGuiThread().AndForget();
}
protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
/// <summary>
/// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null.
/// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
private string TextCounter()
{
await SetTextAsync(string.Empty, updateValue: true);
await ElementReference.FocusAsync();
await OnClearButtonClick.InvokeAsync(e);
if (string.IsNullOrEmpty(Text)) return "0";
return Text.Length.ToString();
}
[Parameter]
public double Step { get; set; } = 1;
internal override InputType GetInputType() => InputType;
protected string InputTypeString => InputType.ToDescription();
public ElementReference ElementReference { get; private set; }
private ElementReference _elementReference1;
private Size GetButtonSize() => Margin == Margin.Dense ? Size.Small : Size.Medium;
private bool _showClearable;
private string _internalText;
#endregion
#region Lifecycle events
public override async Task SetParametersAsync(ParameterView parameters)
{
await base.SetParametersAsync(parameters);
@ -460,52 +413,29 @@ public partial class Input<T> : InputBase<T>
_internalText = Text;
}
string baseTypeName = typeof(T).Name;
if (IsNumericType(baseTypeName) && InputType !=InputType.Number)
if (Helper.IsNumericType(typeof(T).Name) && InputType != InputType.Number)
{
InputType = InputType.Number;
}
}
private bool IsNumericType(string type)
{
switch (type.ToLower())
protected override void OnParametersSet()
{
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;
}
base.OnParametersSet();
// if input is to be debounced, makes sense to bind the change of the text to oninput
// so we set ChangeTextImmediately to true
if (TextChangeDelay > 0)
ChangeTextImmediately = true;
}
#endregion
/// <summary>
/// Sets the input text from outside programmatically
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
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<string> { }
}

@ -11,7 +11,7 @@
{
@if (AdornmentClick.HasDelegate)
{
<IconButton Icon="@Icon" OnClick="@AdornmentClick" Edge="@Edge" Size="@Size" Color="@Color" aria-label="@(!string.IsNullOrEmpty(AriaLabel) ? AriaLabel : "Icon Button")" tabindex="-1"/>
<IconButton Icon="@Icon" Clicked="@AdornmentClick" Edge="@Edge" Size="@Size" Color="@Color" aria-label="@(!string.IsNullOrEmpty(AriaLabel) ? AriaLabel : "Icon Button")" tabindex="-1" />
}
else
{

@ -39,7 +39,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public bool Immediate { get; set; }
public bool ChangeTextImmediately { get; set; } = true;
/// <summary>
/// If true, the input will not have an underline.
@ -170,7 +170,7 @@ public abstract class InputBase<T> : FormComponent<T, string>
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public int Lines { get; set; } = 1;
public int NumberOfLines { get; set; } = 1;
/// <summary>
/// The text to be displayed.

@ -15,10 +15,10 @@
</div>
}
<input @ref="_elementReferenceStart" @attributes="CustomAttributes" type="@InputTypeString" class="@InputClassname" @bind-value="@TextStart" @bind-value:event="@((Immediate ? "oninput" : "onchange"))"
<input @ref="_elementReferenceStart" @attributes="CustomAttributes" type="@InputTypeString" class="@InputClassname" @bind-value="@TextStart" @bind-value:event="@((ChangeTextImmediately ? "oninput" : "onchange"))"
placeholder="@PlaceholderStart" disabled=@Disabled readonly="@ReadOnly" @onblur="@OnBlurred" @onkeydown="@InvokeKeyDown" @onkeypress="@InvokeKeyPress" @onkeyup="@InvokeKeyUp" inputmode="@InputMode.ToString()" pattern="@Pattern" />
<Icon Class="range-input-separator mud-flip-x-rtl" Icon="@SeparatorIcon" Color="@ThemeColor.Default" />
<input @ref="_elementReferenceEnd" @attributes="CustomAttributes" type="@InputTypeString" class="@InputClassname" @bind-value="@TextEnd" @bind-value:event="@((Immediate ? "oninput" : "onchange"))" inputmode="@InputMode.ToString()" pattern="@Pattern"
<input @ref="_elementReferenceEnd" @attributes="CustomAttributes" type="@InputTypeString" class="@InputClassname" @bind-value="@TextEnd" @bind-value:event="@((ChangeTextImmediately ? "oninput" : "onchange"))" inputmode="@InputMode.ToString()" pattern="@Pattern"
placeholder="@PlaceholderEnd" disabled=@Disabled readonly="@ReadOnly" @onblur="@OnBlurred" @onkeydown="@InvokeKeyDown" @onkeypress="@InvokeKeyPress" @onkeyup="@InvokeKeyUp" />
@if (Adornment == Adornment.End)

@ -58,7 +58,7 @@
Color="@ThemeColor.Default"
Icon="@ClearIcon"
Size="@Size.Small"
OnClick="@HandleClearButton"/>
Clicked="@HandleClearButton" />
}
@if (Adornment == Adornment.End)

@ -33,7 +33,7 @@
}
else
{
<IconButton Variant="@Variant" Icon="@Icon" Color="@Color" Size="@Size" Disabled="@Disabled" DisableRipple="@DisableRipple" DisableElevation="@DisableElevation" @onclick="@ToggleMenu" @ontouchend="@(ActivationEvent == MouseEvent.RightClick ? ToggleMenuTouch : null)" @oncontextmenu="@(ActivationEvent==MouseEvent.RightClick ? ToggleMenu : null)" />
<IconButton Variant="@Variant" Icon="@Icon" Color="@Color" Size="@Size" Disabled="@Disabled" DisableRipple="@DisableRipple" DisableElevation="@DisableElevation" Clicked="@ToggleMenu" @ontouchend="@(ActivationEvent == MouseEvent.RightClick ? ToggleMenuTouch : null)" @oncontextmenu="@(ActivationEvent==MouseEvent.RightClick ? ToggleMenu : null)" />
}
@* The portal has to include the cascading values inside, because it's not able to teletransport the cascade *@
<Popover Open="@_isOpen" Class="@PopoverClass" MaxHeight="@MaxHeight" AnchorOrigin="@AnchorOrigin" TransformOrigin="@TransformOrigin" RelativeWidth="@FullWidth" Style="@PopoverStyle">

@ -39,7 +39,7 @@
AdornmentColor="@AdornmentColor"
IconSize="@IconSize"
Error="@HasError"
Immediate="@(Immediate)"
ChangeTextImmediately="@(ChangeTextImmediately)"
Margin="@Margin"
MaxLength="@MaxLength"
HideSpinButtons="@HideSpinButtons"

@ -6,13 +6,13 @@
@if (ShowFirstButton)
{
<li class="@ItemClassname">
<IconButton Icon="@FirstIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" OnClick="@(() => OnClickControlButton(Page.First))" aria-label="First page"></IconButton>
<IconButton Icon="@FirstIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" Clicked="@(() => OnClickControlButton(Page.First))" aria-label="First page"></IconButton>
</li>
}
@if (ShowPreviousButton)
{
<li class="@ItemClassname">
<IconButton Icon="@BeforeIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" OnClick="@(() => OnClickControlButton(Page.Previous))" aria-label="Previous page"></IconButton>
<IconButton Icon="@BeforeIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" Clicked="@(() => OnClickControlButton(Page.Previous))" aria-label="Previous page"></IconButton>
</li>
}
@foreach (var state in GeneratePagination())
@ -32,20 +32,20 @@
}
else {
<li class="@ItemClassname">
<Button OnClick="@(() => Selected = currentPage)" Variant="@Variant" Size="@Size" DisableRipple="true" Disabled="@Disabled" aria-label="@($"Page {currentPage}")">@currentPage</Button>
<Button Clicked="@(() => Selected = currentPage)" Variant="@Variant" Size="@Size" DisableRipple="true" Disabled="@Disabled" aria-label="@($"Page {currentPage}")">@currentPage</Button>
</li>
}
}
@if (ShowNextButton)
{
<li class="@ItemClassname">
<IconButton Icon="@NextIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" OnClick="@(() => OnClickControlButton(Page.Next))" aria-label="Next page"></IconButton>
<IconButton Icon="@NextIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" Clicked="@(() => OnClickControlButton(Page.Next))" aria-label="Next page"></IconButton>
</li>
}
@if (ShowLastButton)
{
<li class="@ItemClassname">
<IconButton Icon="@LastIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" OnClick="@(() => OnClickControlButton(Page.Last))" aria-label="Last page"></IconButton>
<IconButton Icon="@LastIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" Clicked="@(() => OnClickControlButton(Page.Last))" aria-label="Last page"></IconButton>
</li>
}
</Element>

@ -39,7 +39,7 @@
</div>
}
<input class="slider-input" aria-valuenow="@Value" aria-valuemin="@_min" aria-valuemax="@_max" role="slider" @attributes="CustomAttributes" type="range" min="@_min" max="@_max" step="@_step" disabled="@Disabled"
@bind-value="@Text" @bind-value:event="@((Immediate == true ? "oninput" : "onchange"))" />
@bind-value="@Text" @bind-value:event="@((ChangeImmediately == true ? "oninput" : "onchange"))" />
@if (ValueLabel)
{
<div class="slider-value-label" style="@($"left:{width}%;")">

@ -117,7 +117,7 @@ public partial class Slider<T> : UIComponent
/// </summary>
[Parameter]
[Category(CategoryTypes.Slider.Behavior)]
public bool Immediate { get; set; } = true;
public bool ChangeImmediately { get; set; } = true;
/// <summary>
/// If true, displays the slider vertical.

@ -23,12 +23,12 @@
@if (ShowActionButton)
{
<Button Variant="@ActionVariant" Color="@ActionColor" OnClick="ActionClicked" DisableElevation>@Action</Button>
<Button Variant="@ActionVariant" Color="@ActionColor" Clicked="ActionClicked" DisableElevation>@Action</Button>
}
@if (ShowCloseIcon)
{
<IconButton Icon="@CloseIcon" Size="Size.Small" Class="ms-2" OnClick="CloseIconClicked" />
<IconButton Icon="@CloseIcon" Size="Size.Small" Class="ms-2" Clicked="CloseIconClicked" />
}
</div>
}

@ -13,7 +13,7 @@
<div class="d-flex">
@if (GroupDefinition.Expandable)
{
<IconButton Class="table-row-expander" Icon="@(IsExpanded ? ExpandIcon : CollapseIcon)" OnClick="@(() => IsExpanded = !IsExpanded)"/>
<IconButton Class="table-row-expander" Icon="@(IsExpanded ? ExpandIcon : CollapseIcon)" Clicked="@(() => IsExpanded = !IsExpanded)" />
}
else
{

@ -34,10 +34,10 @@
@if (!HidePagination)
{
<div class="table-pagination-actions">
<IconButton Class="flip-x-rtl" Icon="@FirstIcon" Disabled="@BackButtonsDisabled" @onclick="@(() => Table.NavigateTo(Page.First))" aria-label="First page" />
<IconButton Class="flip-x-rtl" Icon="@BeforeIcon" Disabled="@BackButtonsDisabled" @onclick="@(() => Table.NavigateTo(Page.Previous))" aria-label="Previous page" />
<IconButton Class="flip-x-rtl" Icon="@NextIcon" Disabled="@ForwardButtonsDisabled" @onclick="@(() => Table.NavigateTo(Page.Next))" aria-label="Next page" />
<IconButton Class="flip-x-rtl" Icon="@LastIcon" Disabled="@ForwardButtonsDisabled" @onclick="@(() => Table.NavigateTo(Page.Last))" aria-label="Last page" />
<IconButton Class="flip-x-rtl" Icon="@FirstIcon" Disabled="@BackButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.First))" aria-label="First page" />
<IconButton Class="flip-x-rtl" Icon="@BeforeIcon" Disabled="@BackButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Previous))" aria-label="Previous page" />
<IconButton Class="flip-x-rtl" Icon="@NextIcon" Disabled="@ForwardButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Next))" aria-label="Next page" />
<IconButton Class="flip-x-rtl" Icon="@LastIcon" Disabled="@ForwardButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Last))" aria-label="Last page" />
</div>
}
@if (HorizontalAlignment == HorizontalAlignment.Start ||

@ -15,19 +15,19 @@
}
else
{
<IconButton Size="@Size.Small" Icon="@Icons.Outlined.Edit" Class="pa-0" OnClick="StartEditingItem" Disabled="Context.EditButtonDisabled(Item)" />
<IconButton Size="@Size.Small" Icon="@Icons.Outlined.Edit" Class="pa-0" Clicked="StartEditingItem" Disabled="Context.EditButtonDisabled(Item)" />
}
}
else if (object.ReferenceEquals(Context?.Table._editingItem, Item) && (!Context?.Table.ReadOnly ?? false) && Context?.Table.ApplyButtonPosition.DisplayApplyButtonAtStart() == true)
{
<div style="display: flex;">
<Tooltip Text="@Context.Table.CommitEditTooltip">
<IconButton Class="pa-0" Icon="@Context.Table.CommitEditIcon" OnClick="FinishEdit" Size="@Size.Small" Disabled="@(!(Context?.Table.Validator?.IsValid ?? false))" />
<IconButton Class="pa-0" Icon="@Context.Table.CommitEditIcon" Clicked="FinishEdit" Size="@Size.Small" Disabled="@(!(Context?.Table.Validator?.IsValid ?? false))" />
</Tooltip>
@if (Context.Table.CanCancelEdit)
{
<Tooltip Text="@Context.Table.CancelEditTooltip">
<IconButton Class="pa-0 ml-4" Icon="@Context.Table.CancelEditIcon" OnClick="CancelEdit" Size="@Size.Small" />
<IconButton Class="pa-0 ml-4" Icon="@Context.Table.CancelEditIcon" Clicked="CancelEdit" Size="@Size.Small" />
</Tooltip>
}
</div>
@ -58,19 +58,19 @@
}
else
{
<IconButton Size="@Size.Small" Icon="@Icons.Outlined.Edit" Class="pa-0" OnClick="StartEditingItem" Disabled="Context.EditButtonDisabled(Item)" />
<IconButton Size="@Size.Small" Icon="@Icons.Outlined.Edit" Class="pa-0" Clicked="StartEditingItem" Disabled="Context.EditButtonDisabled(Item)" />
}
}
else if (object.ReferenceEquals(Context?.Table._editingItem, Item) && (!Context?.Table.ReadOnly ?? false) && Context?.Table.ApplyButtonPosition.DisplayApplyButtonAtEnd() == true)
{
<div style="display: flex;">
<Tooltip Text="@Context.Table.CommitEditTooltip">
<IconButton Class="pa-0" Icon="@Context.Table.CommitEditIcon" OnClick="FinishEdit" Size="@Size.Small" Disabled="@(!(Context?.Table.Validator?.IsValid ?? false))" />
<IconButton Class="pa-0" Icon="@Context.Table.CommitEditIcon" Clicked="FinishEdit" Size="@Size.Small" Disabled="@(!(Context?.Table.Validator?.IsValid ?? false))" />
</Tooltip>
@if (Context.Table.CanCancelEdit)
{
<Tooltip Text="@Context.Table.CancelEditTooltip">
<MudIconButton Class="pa-0 ml-4" Icon="@Context.Table.CancelEditIcon" OnClick="CancelEdit" Size="@Size.Small" />
<IconButton Class="pa-0 ml-4" Icon="@Context.Table.CancelEditIcon" Clicked="CancelEdit" Size="@Size.Small" />
</Tooltip>
}
</div>

@ -15,12 +15,12 @@
if (string.IsNullOrEmpty(AddIconToolTip) == false)
{
<Tooltip Text="@AddIconToolTip">
<IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" OnClick="@AddTab" />
<IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" Clicked="@AddTab" />
</Tooltip>
}
else
{
<IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" OnClick="@AddTab" />
<IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" Clicked="@AddTab" />
}
}
;
@ -30,12 +30,12 @@
if (string.IsNullOrEmpty(CloseIconToolTip) == false)
{
<Tooltip Text="@CloseIconToolTip">
<IconButton Icon="@CloseTabIcon" Class="@CloseIconClass" Style="@CloseIconStyle" OnClick="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
<IconButton Icon="@CloseTabIcon" Class="@CloseIconClass" Style="@CloseIconStyle" Clicked="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
</Tooltip>
}
else
{
<IconButton Icon="@CloseTabIcon" Class="@CloseIconClass" Style="@CloseIconStyle" OnClick="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
<IconButton Icon="@CloseTabIcon" Class="@CloseIconClass" Style="@CloseIconStyle" Clicked="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
}
}
;

@ -14,7 +14,7 @@
@if (_showScrollButtons)
{
<div class="tabs-scroll-button">
<GlyphButton Icon="@_prevIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollPrev())" Disabled="@_prevButtonDisabled" />
<IconButton Icon="@_prevIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollPrev())" Disabled="@_prevButtonDisabled" />
</div>
}
<div @ref="@_tabsContentSize" class="tabs-toolbar-content">
@ -52,7 +52,7 @@
@if (_showScrollButtons)
{
<div class="tabs-scroll-button">
<GlyphButton Icon="@_nextIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollNext())" Disabled="@_nextButtonDisabled" />
<IconButton Icon="@_nextIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollNext())" Disabled="@_nextButtonDisabled" />
</div>
}
@if (HeaderPosition == TabHeaderPosition.After && Header != null)

@ -25,7 +25,7 @@
@ref="InputReference"
@attributes="CustomAttributes"
InputType="@InputType"
Lines="@Lines"
NumberOfLines="@NumberOfLines"
Variant="@Variant"
TextUpdateSuppression="@TextUpdateSuppression"
Value="@Text"
@ -44,7 +44,7 @@
OnAdornmentClick="@OnAdornmentClick"
Error="@HasError"
ErrorId="@ErrorId"
Immediate="@Immediate"
ChangeTextImmediately="@ChangeTextImmediately"
Margin="@Margin"
OnBlur="@OnBlurred"
OnKeyDown="@InvokeKeyDown"
@ -65,7 +65,7 @@
@attributes="CustomAttributes"
Mask="@_mask"
InputType="@InputType"
Lines="@Lines"
NumberOfLines="@NumberOfLines"
Variant="@Variant"
TextUpdateSuppression="@TextUpdateSuppression"
Value="@Text"
@ -82,7 +82,7 @@
IconSize="@IconSize"
OnAdornmentClick="@OnAdornmentClick"
Error="@HasError"
Immediate="@Immediate"
ChangeTextImmediately="@ChangeTextImmediately"
Margin="@Margin"
OnBlur="@OnBlurred"
Clearable="@Clearable"

@ -5,7 +5,7 @@
<div class="treeview-item-arrow">
@if (Visible)
{
<IconButton OnClick="@ToggleAsync" Icon="@(Loading ? LoadingIcon : ExpandedIcon)" Color="@(Loading ? LoadingIconColor : ExpandedIconColor)" Class="@Classname"></IconButton>
<IconButton Clicked="@ToggleAsync" Icon="@(Loading ? LoadingIcon : ExpandedIcon)" Color="@(Loading ? LoadingIconColor : ExpandedIconColor)" Class="@Classname"></IconButton>
}
</div>

@ -0,0 +1,23 @@
namespace Connected.Utilities;
public static class Helper
{
public static 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;
}
}
}
Loading…
Cancel
Save