Prograss - Input field

This commit is contained in:
stm 2023-01-18 10:27:39 +01:00
parent c5e97f9600
commit 3ea88592ce
37 changed files with 589 additions and 651 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,7 +31,7 @@
{ {
@if (PreviousButtonTemplate == null) @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 else
{ {
@ -51,7 +51,7 @@
int current = i; int current = i;
if (BulletTemplate == null) 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 else
{ {
@ -69,7 +69,7 @@
{ {
@if (NextButtonTemplate == null) @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 else
{ {

View File

@ -27,7 +27,7 @@
} }
@if (OnClose.HasDelegate || ChipSet?.AllClosable==true) @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> </span>
</div> </div>

View File

@ -12,12 +12,12 @@
<PickerToolbar DisableToolbar="@DisableToolbar" Class="picker-color-toolbar"> <PickerToolbar DisableToolbar="@DisableToolbar" Class="picker-color-toolbar">
@if (PickerVariant != PickerVariant.Static) @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 /> <Spacer />
<IconButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Spectrum)" Icon="@SpectrumIcon" OnClick="(() => ChangeView(ColorPickerView.Spectrum))" /> <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" OnClick="(() => ChangeView(ColorPickerView.Grid))" /> <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" OnClick="(() => ChangeView(ColorPickerView.Palette))" /> <IconButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Palette)" Icon="@PaletteIcon" Clicked="(() => ChangeView(ColorPickerView.Palette))" />
</PickerToolbar> </PickerToolbar>
<PickerContent Class="picker-color-content"> <PickerContent Class="picker-color-content">
@if (!DisableColorField) @if (!DisableColorField)
@ -126,7 +126,7 @@
@if (!DisableModeSwitch) @if (!DisableModeSwitch)
{ {
<div class="picker-control-switch"> <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>
} }
</div> </div>

View File

@ -128,8 +128,8 @@
<td class="table-cell @groupClass" colspan="1000" style="background-color:var(--mud-palette-background-grey);@groupStyle"> <td class="table-cell @groupClass" colspan="1000" style="background-color:var(--mud-palette-background-grey);@groupStyle">
<IconButton <IconButton
Class="table-row-expander" Class="table-row-expander"
Icon="@(g.IsExpanded ? Icons.Material.Filled.ExpandMore : Icons.Material.Filled.ChevronRight)" Icon="@(g.IsExpanded ? Icons.Material.Filled.ExpandMore : Icons.Material.Filled.ChevronRight)"
OnClick="@(() => ToggleGroupExpansion(g))" /> Clicked="@(() => ToggleGroupExpansion(g))" />
@if (GroupedColumn.GroupTemplate == null) @if (GroupedColumn.GroupTemplate == null)
{ {
@ -377,7 +377,7 @@
@if (column == null) @if (column == null)
{ {
<Item xs="1" Class="d-flex"> <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>
<Item xs="4"> <Item xs="4">
<Select T="string" Value="@f.Field" ValueChanged="@filter.FieldChanged" FullWidth="true" Label="Column" Dense="true" Margin="@Margin.Dense" <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")) @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" <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")) 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" <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) else if (filter.isEnum)
{ {
@ -442,7 +442,7 @@
else if (filter.dataType == typeof(Guid)) 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" <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> </Item>
} }
@ -461,12 +461,12 @@
@if (filter.dataType == typeof(string) && !(f.Operator ?? "").EndsWith("empty")) @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" <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")) 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" <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) else if (filter.isEnum)
{ {
@ -501,8 +501,8 @@
} }
else if (filter.dataType == typeof(Guid)) 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" <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> </Item>
} }

View File

@ -20,10 +20,10 @@
@Info @Info
</TextContent> </TextContent>
<div class="table-pagination-actions"> <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.FirstPage" Disabled="@BackButtonsDisabled" Clicked="@(() => 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.NavigateBefore" Disabled="@BackButtonsDisabled" Clicked="@(() => 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.NavigateNext" Disabled="@ForwardButtonsDisabled" Clicked="@(() => 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.LastPage" Disabled="@ForwardButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Last))" />
</div> </div>
</ToolBar> </ToolBar>

View File

@ -14,11 +14,11 @@
<Stack Row="true"> <Stack Row="true">
@if (dataType == typeof(string) && !(_operator ?? "").EndsWith("empty")) @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")) 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) else if (isEnum)
{ {
@ -58,7 +58,7 @@
} }
} }
</Menu> </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> </Stack>
} }
} }

View File

@ -41,11 +41,11 @@ else if (Column != null && !Column.Hidden)
{ {
if (_initialDirection == SortDirection.None) 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 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) if(DataGrid.SortMode == SortMode.Multiple)
{ {
<span class="sort-index mud-text-disabled">@(Column.SortIndex + 1)</span> <span class="sort-index mud-text-disabled">@(Column.SortIndex + 1)</span>
@ -57,11 +57,11 @@ else if (Column != null && !Column.Hidden)
{ {
if (hasFilter) 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) 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>
} }
} }

View File

@ -47,11 +47,11 @@
<div class="picker-calendar-header-switch"> <div class="picker-calendar-header-switch">
@if (!FixYear.HasValue) @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"> <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> <TextContent Typo="Typo.body1" Align="Align.Center">@calendarYear</TextContent>
</button> </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 else
{ {
@ -77,11 +77,11 @@
<div class="picker-calendar-header-switch"> <div class="picker-calendar-header-switch">
@if (!FixMonth.HasValue) @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"> <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> <TextContent Typo="Typo.body1" Align="Align.Center">@GetMonthName(tempMonth)</TextContent>
</button> </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 else
{ {

View File

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

View File

@ -60,7 +60,7 @@ public partial class Form : UIComponent, IDisposable, IForm
/// <summary> /// <summary>
/// Validation debounce delay in milliseconds. This can help improve rendering performance of forms with real-time validation of inputs /// 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> /// </summary>
[Parameter] [Parameter]
[Category(CategoryTypes.Form.Behavior)] [Category(CategoryTypes.Form.Behavior)]

View File

@ -72,10 +72,10 @@ public abstract class DebouncedInput<T> : InputBase<T>
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
base.OnParametersSet(); base.OnParametersSet();
// if input is to be debounced, makes sense to bind the change of the text to oninput // 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) if (DebounceInterval > 0)
Immediate = true; ChangeTextImmediately = true;
} }
private void SetTimer() private void SetTimer()

View File

@ -2,162 +2,147 @@
@typeparam T @typeparam T
@inherits InputBase<T> @inherits InputBase<T>
<InputControl Label="@Label" <div class="@CompiledWrapperClass.Build()">
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">
@if (Adornment == Adornment.Start) @if (Adornment == Adornment.Start)
{ {
<InputAdornment Class="@AdornmentClassname" <InputAdornment Class="@CompiledAdornmentClass.Build()"
Icon="@AdornmentIcon" Icon="@AdornmentIcon"
Color="@AdornmentColor"
Size="@IconSize"
Text="@AdornmentText"
Edge="@Edge.Start"
AdornmentClick="@OnAdornmentClick"
AriaLabel="@AdornmentAriaLabel"
/>
}
@if (NumberOfLines > 1)
{
<textarea class="@CompiledInputClass.Build()"
@ref="ElementReference"
rows="@NumberOfLines"
style="@Style"
@attributes="@Attributes"
type="@InputTypeString"
placeholder="@Placeholder"
disabled=@Disabled
readonly="@ReadOnly"
inputmode="@InputMode.ToString()"
@oninput="OnInput"
@onchange="OnChange"
@onblur="@OnBlurred"
@onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp"
@onpaste="@OnPaste"
value="@_internalText"
maxlength="@MaxLength"
@onkeydown:preventDefault="@KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
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="@CompiledInputClass.Build()"
style="@Style"
@ref="ElementReference"
@attributes="@Attributes"
step="@Step"
type="@InputTypeString"
value="@_internalText"
@oninput="OnInput"
@onchange="OnChange"
placeholder="@Placeholder"
disabled=@Disabled
readonly="@ReadOnly"
@onblur="@OnBlurred"
inputmode="@InputMode.ToString()"
pattern="@Pattern"
@onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp"
maxlength="@MaxLength"
@onkeydown:preventDefault="KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId"
/>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
@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.
In Disabled state the tabindex attribute must NOT be set at all or else it will get focus on click
*@
<div class="@CompiledInputClass.Build()"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
@onblur="@OnBlurred" @ref="@_elementReference1"
>
@ChildContent
</div>
}
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="@CompiledInputClass.Build()"
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)
{
<IconButton ClassList="@CompiledClearButtonClassList.Build()"
Icon="@ClearIcon"
Clicked="@ClearButtonClickHandlerAsync"
tabindex="-1"
/>
}
@if (Adornment == Adornment.End)
{
<InputAdornment Class="@CompiledAdornmentClass.Build()"
Icon="@AdornmentIcon"
Color="@AdornmentColor" Color="@AdornmentColor"
Size="@IconSize" Size="@IconSize"
Text="@AdornmentText" Text="@AdornmentText"
Edge="@Edge.Start" Edge="@Edge.End"
AdornmentClick="@OnAdornmentClick" AdornmentClick="@OnAdornmentClick"
AriaLabel="@AdornmentAriaLabel" AriaLabel="@AdornmentAriaLabel"
/> />
} }
<InputContent>
@if (Lines > 1)
{
<textarea class="@InputClassname"
@ref="ElementReference"
rows="@Lines"
@attributes="CustomAttributes"
type="@InputTypeString"
placeholder="@Placeholder"
disabled=@Disabled
readonly="@ReadOnly"
inputmode="@InputMode.ToString()"
@oninput="OnInput"
@onchange="OnChange"
@onblur="@OnBlurred"
@onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp"
@onpaste="@OnPaste"
value="@_internalText"
maxlength="@MaxLength"
@onkeydown:preventDefault="@KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
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"
@ref="ElementReference"
@attributes="CustomAttributes"
type="@InputTypeString"
value="@_internalText"
@oninput="OnInput"
@onchange="OnChange"
placeholder="@Placeholder"
disabled=@Disabled
readonly="@ReadOnly"
@onblur="@OnBlurred"
inputmode="@InputMode.ToString()"
pattern="@Pattern"
@onkeydown="@InvokeKeyDown"
@onkeypress="@InvokeKeyPress"
@onkeyup="@InvokeKeyUp"
maxlength="@MaxLength"
@onkeydown:preventDefault="KeyDownPreventDefault"
@onkeypress:preventDefault="@KeyPressPreventDefault"
@onkeyup:preventDefault="@KeyUpPreventDefault"
@onmousewheel="@OnMouseWheel"
@onwheel="@OnMouseWheel"
aria-invalid="@HasError.ToString().ToLower()"
aria-describedby="@ErrorId"
/>
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
@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.
In Disabled state the tabindex attribute must NOT be set at all or else it will get focus on click
*@
<div class="@InputClassname"
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
@onblur="@OnBlurred" @ref="@_elementReference1"
>
@ChildContent
</div>
}
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) @if (Variant == Variant.Outlined)
{ {
<div class="input-outlined-border"></div>
}
} @if (!HideSpinButtons)
{
<div class="input-numeric-spin">
@if (Adornment == Adornment.End) <Button Variant="Variant.Text" Clicked="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
{ <Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
<InputAdornment Class="@AdornmentClassname" </Button>
Icon="@AdornmentIcon" <Button Variant="Variant.Text" Clicked="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
Color="@AdornmentColor" <Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" />
Size="@IconSize" </Button>
Text="@AdornmentText" </div>
Edge="@Edge.End" }
AdornmentClick="@OnAdornmentClick" </div>
AriaLabel="@AdornmentAriaLabel"
/>
}
@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>
}
</InputContent>
</CascadingValue>
</InputControl>

View File

@ -9,39 +9,18 @@ namespace Connected.Components;
public partial class Input<T> : InputBase<T> public partial class Input<T> : InputBase<T>
{ {
/* #region Event Callbacks
* Debounce
*
*/
/// <summary> /// <summary>
/// The current character counter, displayed below the text field. /// Paste hook for descendants.
/// </summary> /// </summary>
[Parameter] public string CounterText { get; set; } #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
private System.Timers.Timer _timer; protected virtual async Task OnPaste(ClipboardEventArgs args)
private double _debounceInterval; #pragma warning restore 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; // do nothing
set return;
{
if (NumericConverter<double>.AreEqual(_debounceInterval, value))
return;
_debounceInterval = value;
if (_debounceInterval == 0)
{
// not debounced, dispose timer if any
ClearTimer(suppressTick: false);
return;
}
SetTimer();
}
} }
/// <summary> /// <summary>
@ -81,13 +60,289 @@ public partial class Input<T> : InputBase<T>
return Task.CompletedTask; return Task.CompletedTask;
} }
protected override void OnParametersSet() private void OnTimerTick(object sender, ElapsedEventArgs e)
{ {
base.OnParametersSet(); InvokeAsync(OnTimerTickGuiThread).AndForget();
// 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) private async Task OnTimerTickGuiThread()
Immediate = true; {
await base.UpdateValuePropertyAsync(false);
await OnDebounceIntervalElapsed.InvokeAsync(Text);
}
protected Task OnInput(ChangeEventArgs args)
{
if (!ChangeTextImmediately)
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);
if (!ChangeTextImmediately)
{
await SetTextAsync(args?.Value as string);
}
}
}
/// <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.
/// </summary>
[Parameter] public EventCallback OnIncrement { get; set; }
/// <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>
/// Button click event for clear button. Called after text and value has been cleared.
/// </summary>
[Parameter] public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
/// <summary>
/// Mouse wheel event for input.
/// </summary>
[Parameter] public EventCallback<WheelEventArgs> OnMouseWheel { get; set; }
public override async ValueTask FocusAsync()
{
try
{
if (InputType == InputType.Hidden && ChildContent != null)
await _elementReference1.FocusAsync();
else
await ElementReference.FocusAsync();
}
catch (Exception e)
{
Console.WriteLine("Input.FocusAsync: " + e.Message);
}
}
public override ValueTask BlurAsync()
{
return ElementReference.BlurAsync();
}
public override ValueTask SelectAsync()
{
return ElementReference.SelectAsync();
}
public override ValueTask SelectRangeAsync(int pos1, int pos2)
{
return ElementReference.SelectRangeAsync(pos1, pos2);
}
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>
/// Custom input Attributes
/// </summary>
[Parameter] public Dictionary<string, object>? Attributes { get; set; } = null;
#endregion
#region Style properties
/// <summary>
/// Type of the input element. It should be a valid HTML5 input type.
/// </summary>
[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"/>
/// </summary>
[Parameter] public bool HideSpinButtons { get; set; } = true;
/// <summary>
/// Show clear button.
/// </summary>
[Parameter] public bool Clearable { get; set; } = false;
#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);
}
}
#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>
/// A space separated list of class names, added on top of the default helper container class list.
/// </summary>
[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>
/// The current character counter, displayed below the text field.
/// </summary>
[Parameter] public string CounterText { get; set; }
private System.Timers.Timer _timer;
private double _textChangeInterval;
/// <summary>
/// Interval to be awaited in MILLISECONDS before changing the Text value
/// </summary>
[Parameter]
public double TextChangeDelay
{
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();
}
} }
private void SetTimer() private void SetTimer()
@ -101,17 +356,6 @@ public partial class Input<T> : InputBase<T>
_timer.Interval = TextChangeDelay; _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) private void ClearTimer(bool suppressTick = false)
{ {
if (_timer == null) if (_timer == null)
@ -125,387 +369,73 @@ public partial class Input<T> : InputBase<T>
OnTimerTickGuiThread().AndForget(); 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> /// <summary>
/// A space separated list of class names, added on top of the default helper container class list. /// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null.
/// </summary> /// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
private string TextCounter()
{
if (string.IsNullOrEmpty(Text)) return "0";
return Text.Length.ToString();
}
[Parameter] [Parameter]
public string? HelperContainerClassList { get; set; } 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;
protected CssBuilder CompiledHelperClassList #endregion
#region Lifecycle events
public override async Task SetParametersAsync(ParameterView parameters)
{ {
get await base.SetParametersAsync(parameters);
//if (!_isFocused || _forceTextUpdate)
// _internalText = Text;
if (RuntimeLocation.IsServerSide && TextUpdateSuppression)
{ {
return new CssBuilder("input-helper-text") // Text update suppression, only in BSS (not in WASM).
.AddClass("input-helper-onfocus", HelperTextOnFocus) // This is a fix for #1012
.AddClass(HelperClassList); if (!_isFocused || _forceTextUpdate)
} _internalText = Text;
}
/// <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)
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 else
{ {
_internalText = args?.Value as string; // in WASM (or in BSS with TextUpdateSuppression==false) we always update
await OnInternalInputChanged.InvokeAsync(args); _internalText = Text;
if (!Immediate)
{
await SetTextAsync(args?.Value as string);
}
} }
}
/// <summary> if (Helper.IsNumericType(typeof(T).Name) && InputType != InputType.Number)
/// Paste hook for descendants.
/// </summary>
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
protected virtual async Task OnPaste(ClipboardEventArgs args)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
// do nothing
return;
}
/// <summary>
/// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null.
/// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
public ElementReference ElementReference { get; private set; }
private ElementReference _elementReference1;
public override async ValueTask FocusAsync()
{
try
{
if (InputType == InputType.Hidden && ChildContent != null)
await _elementReference1.FocusAsync();
else
await ElementReference.FocusAsync();
}
catch (Exception e)
{
Console.WriteLine("Input.FocusAsync: " + e.Message);
}
}
public override ValueTask BlurAsync()
{
return ElementReference.BlurAsync();
}
public override ValueTask SelectAsync()
{
return ElementReference.SelectAsync();
}
public override ValueTask SelectRangeAsync(int pos1, int pos2)
{
return ElementReference.SelectRangeAsync(pos1, pos2);
}
/// <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.
/// </summary>
[Parameter] public EventCallback OnIncrement { get; set; }
/// <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.
/// </summary>
[Parameter] public EventCallback OnDecrement { get; set; }
/// <summary>
/// Hides the spin buttons for <see cref="MudNumericField{T}"/>
/// </summary>
[Parameter] public bool HideSpinButtons { get; set; } = true;
/// <summary>
/// Show clear button.
/// </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; }
/// <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;
/// <summary>
/// Custom numeric up icon.
/// </summary>
[Parameter] public string NumericUpIcon { get; set; } = Icons.Material.Filled.KeyboardArrowUp;
/// <summary>
/// Custom numeric down icon.
/// </summary>
[Parameter] public string NumericDownIcon { get; set; } = Icons.Material.Filled.KeyboardArrowDown;
private Size GetButtonSize() => Margin == Margin.Dense ? Size.Small : Size.Medium;
private bool _showClearable;
private void UpdateClearable(object value)
{
var showClearable = Clearable && ((value is string stringValue && !string.IsNullOrWhiteSpace(stringValue)) || (value is not string && value is not null));
if (_showClearable != showClearable)
_showClearable = showClearable;
}
protected override async Task UpdateTextPropertyAsync(bool updateValue)
{
await base.UpdateTextPropertyAsync(updateValue);
if (Clearable)
UpdateClearable(Text);
}
/*protected override async Task UpdateValuePropertyAsync(bool updateText)
{
await base.UpdateValuePropertyAsync(updateText);
if (Clearable)
UpdateClearable(Value);
}*/
protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e)
{
await SetTextAsync(string.Empty, updateValue: true);
await ElementReference.FocusAsync();
await OnClearButtonClick.InvokeAsync(e);
}
private string _internalText;
public override async Task SetParametersAsync(ParameterView parameters)
{
await base.SetParametersAsync(parameters);
//if (!_isFocused || _forceTextUpdate)
// _internalText = Text;
if (RuntimeLocation.IsServerSide && TextUpdateSuppression)
{
// Text update suppression, only in BSS (not in WASM).
// This is a fix for #1012
if (!_isFocused || _forceTextUpdate)
_internalText = Text;
}
else
{
// in WASM (or in BSS with TextUpdateSuppression==false) we always update
_internalText = Text;
}
string baseTypeName = typeof(T).Name;
if (IsNumericType(baseTypeName) && InputType !=InputType.Number)
{ {
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;
}
} }
/// <summary> protected override void OnParametersSet()
/// Sets the input text from outside programmatically {
/// </summary> base.OnParametersSet();
/// <param name="text"></param> // if input is to be debounced, makes sense to bind the change of the text to oninput
/// <returns></returns> // so we set ChangeTextImmediately to true
public Task SetText(string text) if (TextChangeDelay > 0)
{ ChangeTextImmediately = true;
_internalText = text; }
return SetTextAsync(text); #endregion
}
// 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> { }

View File

@ -11,7 +11,7 @@
{ {
@if (AdornmentClick.HasDelegate) @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 else
{ {

View File

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

View File

@ -15,10 +15,10 @@
</div> </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" /> 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" /> <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" /> placeholder="@PlaceholderEnd" disabled=@Disabled readonly="@ReadOnly" @onblur="@OnBlurred" @onkeydown="@InvokeKeyDown" @onkeypress="@InvokeKeyPress" @onkeyup="@InvokeKeyUp" />
@if (Adornment == Adornment.End) @if (Adornment == Adornment.End)

View File

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

View File

@ -33,7 +33,7 @@
} }
else 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 *@ @* 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"> <Popover Open="@_isOpen" Class="@PopoverClass" MaxHeight="@MaxHeight" AnchorOrigin="@AnchorOrigin" TransformOrigin="@TransformOrigin" RelativeWidth="@FullWidth" Style="@PopoverStyle">

View File

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

View File

@ -6,13 +6,13 @@
@if (ShowFirstButton) @if (ShowFirstButton)
{ {
<li class="@ItemClassname"> <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> </li>
} }
@if (ShowPreviousButton) @if (ShowPreviousButton)
{ {
<li class="@ItemClassname"> <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> </li>
} }
@foreach (var state in GeneratePagination()) @foreach (var state in GeneratePagination())
@ -32,20 +32,20 @@
} }
else { else {
<li class="@ItemClassname"> <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> </li>
} }
} }
@if (ShowNextButton) @if (ShowNextButton)
{ {
<li class="@ItemClassname"> <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> </li>
} }
@if (ShowLastButton) @if (ShowLastButton)
{ {
<li class="@ItemClassname"> <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> </li>
} }
</Element> </Element>

View File

@ -39,7 +39,7 @@
</div> </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" <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) @if (ValueLabel)
{ {
<div class="slider-value-label" style="@($"left:{width}%;")"> <div class="slider-value-label" style="@($"left:{width}%;")">

View File

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

View File

@ -23,12 +23,12 @@
@if (ShowActionButton) @if (ShowActionButton)
{ {
<Button Variant="@ActionVariant" Color="@ActionColor" OnClick="ActionClicked" DisableElevation>@Action</Button> <Button Variant="@ActionVariant" Color="@ActionColor" Clicked="ActionClicked" DisableElevation>@Action</Button>
} }
@if (ShowCloseIcon) @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> </div>
} }

View File

@ -13,7 +13,7 @@
<div class="d-flex"> <div class="d-flex">
@if (GroupDefinition.Expandable) @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 else
{ {

View File

@ -34,10 +34,10 @@
@if (!HidePagination) @if (!HidePagination)
{ {
<div class="table-pagination-actions"> <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="@FirstIcon" Disabled="@BackButtonsDisabled" Clicked="@(() => 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="@BeforeIcon" Disabled="@BackButtonsDisabled" Clicked="@(() => 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="@NextIcon" Disabled="@ForwardButtonsDisabled" Clicked="@(() => 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="@LastIcon" Disabled="@ForwardButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Last))" aria-label="Last page" />
</div> </div>
} }
@if (HorizontalAlignment == HorizontalAlignment.Start || @if (HorizontalAlignment == HorizontalAlignment.Start ||

View File

@ -15,19 +15,19 @@
} }
else 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) else if (object.ReferenceEquals(Context?.Table._editingItem, Item) && (!Context?.Table.ReadOnly ?? false) && Context?.Table.ApplyButtonPosition.DisplayApplyButtonAtStart() == true)
{ {
<div style="display: flex;"> <div style="display: flex;">
<Tooltip Text="@Context.Table.CommitEditTooltip"> <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> </Tooltip>
@if (Context.Table.CanCancelEdit) @if (Context.Table.CanCancelEdit)
{ {
<Tooltip Text="@Context.Table.CancelEditTooltip"> <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> </Tooltip>
} }
</div> </div>
@ -58,19 +58,19 @@
} }
else 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) else if (object.ReferenceEquals(Context?.Table._editingItem, Item) && (!Context?.Table.ReadOnly ?? false) && Context?.Table.ApplyButtonPosition.DisplayApplyButtonAtEnd() == true)
{ {
<div style="display: flex;"> <div style="display: flex;">
<Tooltip Text="@Context.Table.CommitEditTooltip"> <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> </Tooltip>
@if (Context.Table.CanCancelEdit) @if (Context.Table.CanCancelEdit)
{ {
<Tooltip Text="@Context.Table.CancelEditTooltip"> <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> </Tooltip>
} }
</div> </div>

View File

@ -15,12 +15,12 @@
if (string.IsNullOrEmpty(AddIconToolTip) == false) if (string.IsNullOrEmpty(AddIconToolTip) == false)
{ {
<Tooltip Text="@AddIconToolTip"> <Tooltip Text="@AddIconToolTip">
<IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" OnClick="@AddTab" /> <IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" Clicked="@AddTab" />
</Tooltip> </Tooltip>
} }
else 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) if (string.IsNullOrEmpty(CloseIconToolTip) == false)
{ {
<Tooltip Text="@CloseIconToolTip"> <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> </Tooltip>
} }
else 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))" />
} }
} }
; ;

View File

@ -14,7 +14,7 @@
@if (_showScrollButtons) @if (_showScrollButtons)
{ {
<div class="tabs-scroll-button"> <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>
} }
<div @ref="@_tabsContentSize" class="tabs-toolbar-content"> <div @ref="@_tabsContentSize" class="tabs-toolbar-content">
@ -52,7 +52,7 @@
@if (_showScrollButtons) @if (_showScrollButtons)
{ {
<div class="tabs-scroll-button"> <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> </div>
} }
@if (HeaderPosition == TabHeaderPosition.After && Header != null) @if (HeaderPosition == TabHeaderPosition.After && Header != null)

View File

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

View File

@ -5,7 +5,7 @@
<div class="treeview-item-arrow"> <div class="treeview-item-arrow">
@if (Visible) @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> </div>

View File

@ -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;
}
}
}