Progress
This commit is contained in:
parent
b178bbb9b0
commit
1a424571ad
@ -20,7 +20,7 @@
|
||||
@if (CloseGlyphVisible)
|
||||
{
|
||||
<div class="alert-close">
|
||||
<IconButton ClassList="size-small" Icon="@CloseGlyph" Clicked="OnCloseGlyphClick" />
|
||||
<GlyphButton ClassList="size-small" Glyph="@CloseGlyph" Clicked="OnCloseGlyphClick" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
@ -11,7 +11,7 @@
|
||||
{
|
||||
@if (!String.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<Icon Icon="@Icon" Class="icon-badge" />
|
||||
<Icon Glyph="@Icon" Class="icon-badge" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
<a href="@(Item?.Href ?? "#")">
|
||||
@if (Item?.Icon != null)
|
||||
{
|
||||
<Icon Icon="@Item?.Icon" Size="Size.Small" />
|
||||
<Icon Glyph="@Item?.Icon" Size="Size.Small" />
|
||||
}
|
||||
@Item?.Text
|
||||
</a>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<BreadcrumbLink Item="Items[0]"></BreadcrumbLink>
|
||||
<BreadcrumbSeparator></BreadcrumbSeparator>
|
||||
<li class="breadcrumbs-expander" @onclick="Expand">
|
||||
<Icon Icon="@ExpanderIcon" Size="Size.Small"></Icon>
|
||||
<Icon Glyph="@ExpanderIcon" Size="Size.Small"></Icon>
|
||||
</li>
|
||||
<BreadcrumbSeparator></BreadcrumbSeparator>
|
||||
<BreadcrumbLink Item="Items[Items.Count - 1]"></BreadcrumbLink>
|
||||
|
@ -14,12 +14,12 @@
|
||||
<span class="fab-label">
|
||||
@if (!string.IsNullOrWhiteSpace(StartIcon))
|
||||
{
|
||||
<Icon Icon="@StartIcon" Color="@IconColor" Size="@IconSize" />
|
||||
<Icon Glyph="@StartIcon" Color="@IconColor" Size="@IconSize" />
|
||||
}
|
||||
@Label
|
||||
@if (!string.IsNullOrWhiteSpace(EndIcon))
|
||||
{
|
||||
<Icon Icon="@EndIcon" Color="@IconColor" Size="@IconSize" />
|
||||
<Icon Glyph="@EndIcon" Color="@IconColor" Size="@IconSize" />
|
||||
}
|
||||
</span>
|
||||
</Element>
|
||||
|
@ -5,17 +5,17 @@
|
||||
@using Connected.Components;
|
||||
|
||||
<Element disabled="@Disabled"
|
||||
title="@IconTitle"
|
||||
title="@GlyphTitle"
|
||||
type="@ButtonType.ToString()"
|
||||
ClassList="@CompiledClassList.ToString()"
|
||||
HtmlTag="@HtmlTag"
|
||||
PreventOnClickPropagation="PreventOnClickPropagation"
|
||||
@attributes="CustomAttributes"
|
||||
@onclick="OnClick">
|
||||
@if (!String.IsNullOrEmpty(Icon))
|
||||
@if (!String.IsNullOrEmpty(Glyph))
|
||||
{
|
||||
<span name="glyph-container" class="glyph-button-label">
|
||||
<Icon Glyph="@Icon" />
|
||||
<Icon Glyph="@Glyph" />
|
||||
</span>
|
||||
}
|
||||
else
|
@ -3,20 +3,20 @@ using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Connected.Components;
|
||||
|
||||
public partial class IconButton : ButtonBase
|
||||
public partial class GlyphButton : ButtonBase
|
||||
{
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// The Icon that will be used in the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? Icon { get; set; }
|
||||
public string? Glyph { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GlyphTitle of the icon used for accessibility.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? IconTitle { get; set; }
|
||||
public string? GlyphTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component, only shows if Glyph is null or Empty.
|
@ -2,12 +2,12 @@
|
||||
|
||||
@inherits UIComponent
|
||||
|
||||
<IconButton aria-pressed="@Toggled.ToString()"
|
||||
<GlyphButton aria-pressed="@Toggled.ToString()"
|
||||
ClassList="@ClassList"
|
||||
Clicked="Toggle"
|
||||
Disabled="Disabled"
|
||||
Icon="@(Toggled ? ToggledIcon : Icon)"
|
||||
IconTitle="@(Toggled && ToggledIconTitle != null ? ToggledIconTitle : IconTitle)"
|
||||
Glyph="@(Toggled ? ToggledGlyph : Glyph)"
|
||||
GlyphTitle="@(Toggled && ToggledGlyphTitle != null ? ToggledGlyphTitle : GlyphTitle)"
|
||||
Variant="Variant"
|
||||
@attributes="CustomAttributes"
|
||||
/>
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Connected.Components;
|
||||
|
||||
public partial class ToggleIconButton : UIComponent
|
||||
public partial class ToggleGlyphButton : UIComponent
|
||||
{
|
||||
#region Events
|
||||
/// <summary>
|
||||
@ -39,25 +39,25 @@ public partial class ToggleIconButton : UIComponent
|
||||
/// The glyph that will be used in the untoggled state.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? Icon { get; set; }
|
||||
public string? Glyph { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GlyphTitle of the icon used for accessibility.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? IconTitle { get; set; }
|
||||
public string? GlyphTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The glyph that will be used in the toggled state.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? ToggledIcon { get; set; }
|
||||
public string? ToggledGlyph { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GlyphTitle used in toggled state, if different.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? ToggledIconTitle { get; set; }
|
||||
public string? ToggledGlyphTitle { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
@ -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" Clicked="Previous" Color="ThemeColor.Inherit" />
|
||||
<GlyphButton tabindex="1" aria-label="Go to previous" Class="@NavigationButtonsClassName" Style="z-index:3;opacity:0.75" Glyph="@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)" Clicked="(() => MoveTo(current))" Color="ThemeColor.Inherit" />
|
||||
<GlyphButton tabindex="@(i+3)" aria-label="@(i+1)" Class="@BulletsButtonsClassName" Style="z-index:3;opacity:0.75" Glyph="@(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" Clicked="Next" Color="ThemeColor.Inherit" />
|
||||
<GlyphButton tabindex="2" aria-label="Go to next" Class="@NavigationButtonsClassName" Style="z-index:3;opacity:0.75" Glyph="@NextIcon" Clicked="Next" Color="ThemeColor.Inherit" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
<span tabindex="0" class="@CheckBoxClassname">
|
||||
@*note: stopping the click propagation is important here. otherwise checking the checkbox results in click events on its parent (i.e. table row), which is generally not what you would want*@
|
||||
<input tabindex="-1" @attributes="CustomAttributes" type="checkbox" class="checkbox-input" checked="@BoolValue" @onchange="@OnChange" disabled="@Disabled" @onclick:preventDefault="@ReadOnly" />
|
||||
<Icon Icon="@GetIcon()" Color="HasErrors ? ThemeColor.Error : ThemeColor.Inherit" Size="@Size" />
|
||||
<Icon Glyph="@GetIcon()" Color="HasErrors ? ThemeColor.Error : ThemeColor.Inherit" Size="@Size" />
|
||||
</span>
|
||||
@if (!String.IsNullOrEmpty(Label))
|
||||
{
|
||||
|
@ -10,11 +10,11 @@
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(Icon) && !IsChecked)
|
||||
{
|
||||
<Icon Icon="@Icon" Class="chip-icon" Size="Size.Small" Color="@IconColor" />
|
||||
<Icon Glyph="@Icon" Class="chip-icon" Size="Size.Small" Color="@IconColor" />
|
||||
}
|
||||
else if (IsChecked)
|
||||
{
|
||||
<Icon Icon="@CheckedIcon" Class="chip-icon" Size="Size.Small" />
|
||||
<Icon Glyph="@CheckedIcon" Class="chip-icon" Size="Size.Small" />
|
||||
}
|
||||
<span class="chip-content">
|
||||
@if (ChildContent == null)
|
||||
@ -27,7 +27,7 @@
|
||||
}
|
||||
@if (OnClose.HasDelegate || ChipSet?.AllClosable==true)
|
||||
{
|
||||
<IconButton Class="chip-close-button" Icon="@(String.IsNullOrEmpty(CloseIcon) ? $"{Icons.Material.Filled.Cancel}" : $"{CloseIcon}")" Clicked="OnCloseHandler" Size="Size.Small"/>
|
||||
<GlyphButton Class="chip-close-button" Glyph="@(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" Clicked="@GetEventCallback()" />
|
||||
<GlyphButton Class="pa-1 mud-close-picker-button" Size="Size.Small" Color="ThemeColor.Inherit" Glyph="@CloseIcon" Clicked="@GetEventCallback()" />
|
||||
}
|
||||
<Spacer />
|
||||
<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))" />
|
||||
<GlyphButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Spectrum)" Glyph="@SpectrumIcon" Clicked="(() => ChangeView(ColorPickerView.Spectrum))" />
|
||||
<GlyphButton Class="pa-1 mx-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Grid)" Glyph="@GridIcon" Clicked="(() => ChangeView(ColorPickerView.Grid))" />
|
||||
<GlyphButton Class="pa-1" Size="Size.Small" Color="GetButtonColor(ColorPickerView.Palette)" Glyph="@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 Clicked="ChangeMode" Icon="@ImportExportIcon" Class="pa-1 me-n1"></IconButton>
|
||||
<GlyphButton Clicked="ChangeMode" Glyph="@ImportExportIcon" Class="pa-1 me-n1"></GlyphButton>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
@ -126,9 +126,9 @@
|
||||
@{ var groupStyle = new StyleBuilder().AddStyle(GroupStyle).AddStyle(GroupStyleFunc?.Invoke(g)).Build(); }
|
||||
|
||||
<td class="table-cell @groupClass" colspan="1000" style="background-color:var(--mud-palette-background-grey);@groupStyle">
|
||||
<IconButton
|
||||
<GlyphButton
|
||||
Class="table-row-expander"
|
||||
Icon="@(g.IsExpanded ? Icons.Material.Filled.ExpandMore : Icons.Material.Filled.ChevronRight)"
|
||||
Glyph="@(g.IsExpanded ? Icons.Material.Filled.ExpandMore : Icons.Material.Filled.ChevronRight)"
|
||||
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" Clicked="@filter.RemoveFilter" Size="@Size.Small" Style="align-self:flex-end"></IconButton>
|
||||
<GlyphButton Class="remove-filter-button" Glyph="@Icons.Material.Filled.Close" Clicked="@filter.RemoveFilter" Size="@Size.Small" Style="align-self:flex-end"></GlyphButton>
|
||||
</Item>
|
||||
<Item xs="4">
|
||||
<Select T="string" Value="@f.Field" ValueChanged="@filter.FieldChanged" FullWidth="true" Label="Column" Dense="true" Margin="@Margin.Dense"
|
||||
|
@ -20,10 +20,10 @@
|
||||
@Info
|
||||
</TextContent>
|
||||
<div class="table-pagination-actions">
|
||||
<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))" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@Icons.Material.Filled.FirstPage" Disabled="@BackButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.First))" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@Icons.Material.Filled.NavigateBefore" Disabled="@BackButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Previous))" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@Icons.Material.Filled.NavigateNext" Disabled="@ForwardButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Next))" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@Icons.Material.Filled.LastPage" Disabled="@ForwardButtonsDisabled" Clicked="@(() => DataGrid.NavigateTo(Page.Last))" />
|
||||
</div>
|
||||
</ToolBar>
|
||||
|
||||
|
@ -58,7 +58,7 @@
|
||||
}
|
||||
}
|
||||
</Menu>
|
||||
<IconButton Class="align-self-center" Icon="@Icons.Material.Filled.FilterAltOff" Size="@Size.Small" Clicked="@ClearFilter"></IconButton>
|
||||
<GlyphButton Class="align-self-center" Glyph="@Icons.Material.Filled.FilterAltOff" Size="@Size.Small" Clicked="@ClearFilter"></GlyphButton>
|
||||
</Stack>
|
||||
}
|
||||
}
|
||||
|
@ -41,11 +41,11 @@ else if (Column != null && !Column.Hidden)
|
||||
{
|
||||
if (_initialDirection == SortDirection.None)
|
||||
{
|
||||
<IconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Clicked="@SortChangedAsync"></IconButton>
|
||||
<GlyphButton Glyph="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Clicked="@SortChangedAsync"></GlyphButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<IconButton Icon="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Clicked="@SortChangedAsync"></IconButton>
|
||||
<GlyphButton Glyph="@Column.SortIcon" Class="@sortIconClass" Size="@Size.Small" Clicked="@SortChangedAsync"></GlyphButton>
|
||||
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" Clicked="@OpenFilters"></IconButton>
|
||||
<GlyphButton Class="filter-button filtered" Glyph="@Icons.Material.Filled.FilterAlt" Size="@Size.Small" Clicked="@OpenFilters"></GlyphButton>
|
||||
}
|
||||
else if (showFilterIcon)
|
||||
{
|
||||
<IconButton Class="filter-button" Icon="@Icons.Material.Outlined.FilterAlt" Size="@Size.Small" Clicked="@AddFilter"></IconButton>
|
||||
<GlyphButton Class="filter-button" Glyph="@Icons.Material.Outlined.FilterAlt" Size="@Size.Small" Clicked="@AddFilter"></GlyphButton>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,7 @@
|
||||
Filterable="false">
|
||||
<CellTemplate>
|
||||
<label class="ma-n3">
|
||||
<IconButton
|
||||
Icon="@(context.openHierarchies.Contains(context.Item) ? OpenIcon : ClosedIcon)"
|
||||
<GlyphButton Glyph="@(context.openHierarchies.Contains(context.Item) ? OpenIcon : ClosedIcon)"
|
||||
OnClick="context.Actions.ToggleHierarchyVisibilityForItem"
|
||||
Size="@IconSize"
|
||||
Disabled="ButtonDisabledFunc.Invoke(context.Item)"/>
|
||||
|
@ -47,11 +47,11 @@
|
||||
<div class="picker-calendar-header-switch">
|
||||
@if (!FixYear.HasValue)
|
||||
{
|
||||
<IconButton aria-label="@prevLabel" Icon="@PreviousIcon" Clicked="OnPreviousYearClick" Class="flip-x-rtl" />
|
||||
<GlyphButton aria-label="@prevLabel" Glyph="@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" Clicked="OnNextYearClick" Class="flip-x-rtl" />
|
||||
<GlyphButton aria-label="@nextLabel" Glyph="@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" Clicked="OnPreviousMonthClick" />
|
||||
<GlyphButton aria-label="@prevLabel" Class="picker-nav-button-prev mud-flip-x-rtl" Glyph="@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" Clicked="OnNextMonthClick" />
|
||||
<GlyphButton aria-label="@nextLabel" Class="picker-nav-button-next mud-flip-x-rtl" Glyph="@NextIcon" Clicked="OnNextMonthClick" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -17,7 +17,7 @@
|
||||
}
|
||||
@if (CloseButton)
|
||||
{
|
||||
<IconButton aria-label="close" Icon="@CloseIcon" Clicked="Cancel" />
|
||||
<GlyphButton aria-label="close" Glyph="@CloseIcon" Clicked="Cancel" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
@ -27,6 +27,12 @@ public class DragAndDropIndexChangedEventArgs : EventArgs
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to encapsulate data for a drag and drop transaction
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
|
||||
public class DragAndDropItemTransaction<T>
|
||||
{
|
||||
#region Variables
|
||||
@ -113,23 +119,8 @@ public class DragAndDropItemTransaction<T>
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to encapsulate data for a drag and drop transaction
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Record encaplusalting data regaring a completed transaction
|
||||
@ -142,6 +133,16 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
|
||||
public class DragAndDropTransactionFinishedEventArgs<T> : EventArgs
|
||||
{
|
||||
#region Variables
|
||||
public T Item { get; }
|
||||
public bool Success { get; }
|
||||
public string OriginatedDropzoneIdentifier { get; }
|
||||
public string DestinationDropzoneIdentifier { get; }
|
||||
public int OriginIndex { get; }
|
||||
public int DestinationIndex { get; }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
public DragAndDropTransactionFinishedEventArgs(DragAndDropItemTransaction<T> transaction) :
|
||||
this(string.Empty, false, transaction)
|
||||
{
|
||||
@ -158,14 +159,9 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
DestinationIndex = transaction.Index;
|
||||
}
|
||||
|
||||
public T Item { get; }
|
||||
public bool Success { get; }
|
||||
public string OriginatedDropzoneIdentifier { get; }
|
||||
public string DestinationDropzoneIdentifier { get; }
|
||||
public int OriginIndex { get; }
|
||||
public int DestinationIndex { get; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The container of a drag and drop zones
|
||||
@ -173,13 +169,20 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
/// <typeparam name="T">Datetype of items</typeparam>
|
||||
public partial class DropContainer<T> : UIComponent
|
||||
{
|
||||
|
||||
#region Variables
|
||||
private DragAndDropItemTransaction<T> _transaction;
|
||||
#endregion
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("drop-container")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
#region Events
|
||||
public event EventHandler<DragAndDropItemTransaction<T>> TransactionStarted;
|
||||
public event EventHandler<DragAndDropIndexChangedEventArgs> TransactionIndexChanged;
|
||||
|
||||
public event EventHandler<DragAndDropTransactionFinishedEventArgs<T>> TransactionEnded;
|
||||
public event EventHandler RefreshRequested;
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component. This should include the drop zones
|
||||
/// </summary>
|
||||
@ -193,34 +196,14 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public IEnumerable<T> Items { get; set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The render fragment (template) that should be used to render the items within a drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public RenderFragment<T> ItemRenderer { get; set; }
|
||||
#region Styling
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public Func<T, string, bool> ItemsSelector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Callback that indicates that an item has been dropped on a drop zone. Should be used to update the "status" of the data item
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public EventCallback<ItemDropInfo<T>> ItemDropped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public Func<T, string, bool> CanDrop { get; set; }
|
||||
protected string Classname =>
|
||||
new CssBuilder("drop-container")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// The CSS class(es), that is applied to drop zones that are a valid target for drag and drop transaction
|
||||
@ -236,13 +219,6 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public string NoDropClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, drop classes CanDropClass <see cref="CanDropClass"/> or NoDropClass <see cref="NoDropClass"/> or applied as soon, as a transaction has started
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public bool ApplyDropClassesOnDragStarted { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item should be disabled for dragging. Defaults to allow all items
|
||||
/// </summary>
|
||||
@ -271,11 +247,43 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string ItemDraggingClass { get; set; }
|
||||
|
||||
public event EventHandler<DragAndDropItemTransaction<T>> TransactionStarted;
|
||||
public event EventHandler<DragAndDropIndexChangedEventArgs> TransactionIndexChanged;
|
||||
#endregion
|
||||
|
||||
public event EventHandler<DragAndDropTransactionFinishedEventArgs<T>> TransactionEnded;
|
||||
public event EventHandler RefreshRequested;
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// Callback that indicates that an item has been dropped on a drop zone. Should be used to update the "status" of the data item
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public EventCallback<ItemDropInfo<T>> ItemDropped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public Func<T, string, bool> CanDrop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The render fragment (template) that should be used to render the items within a drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public RenderFragment<T> ItemRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public Func<T, string, bool> ItemsSelector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, drop classes CanDropClass <see cref="CanDropClass"/> or NoDropClass <see cref="NoDropClass"/> or applied as soon, as a transaction has started
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public bool ApplyDropClassesOnDragStarted { get; set; } = false;
|
||||
|
||||
public void StartTransaction(T item, string identifier, int index, Func<Task> commitCallback, Func<Task> cancelCallback)
|
||||
{
|
||||
@ -372,5 +380,6 @@ public record ItemDropInfo<T>(T Item, string DropzoneIdentifier, int IndexInZone
|
||||
/// </summary>
|
||||
public void Refresh() => RefreshRequested?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -11,12 +11,15 @@ namespace Connected.Components;
|
||||
|
||||
public partial class DropZone<T> : UIComponent, IDisposable
|
||||
{
|
||||
#region Variables
|
||||
private bool _containerIsInitialized = false;
|
||||
private bool _canDrop = false;
|
||||
private bool _dragInProgress = false;
|
||||
private bool _disposedValue = false;
|
||||
private Guid _id = Guid.NewGuid();
|
||||
|
||||
private int _dragCounter = 0;
|
||||
|
||||
private Dictionary<T, int> _indicies = new();
|
||||
|
||||
[Inject] private IJSRuntime JsRuntime { get; set; }
|
||||
@ -24,103 +27,9 @@ public partial class DropZone<T> : UIComponent, IDisposable
|
||||
[CascadingParameter]
|
||||
protected DropContainer<T> Container { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Appearance)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The unique identifier of this drop zone. It is used within transaction to
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Appearance)]
|
||||
public string Identifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The render fragment (template) that should be used to render the items within a drop zone. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public RenderFragment<T> ItemRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public Func<T, bool> ItemsSelector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public Func<T, bool> CanDrop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The CSS class(es), that is applied to drop zones that are a valid target for drag and drop transaction. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public string CanDropClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The CSS class(es), that is applied to drop zones that are NOT valid target for drag and drop transaction. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public string NoDropClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, drop classes CanDropClass <see cref="CanDropClass"/> or NoDropClass <see cref="NoDropClass"/> or applied as soon, as a transaction has started. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public bool? ApplyDropClassesOnDragStarted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item should be disabled for dragging. Defaults to allow all items. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public Func<T, bool> ItemIsDisabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a drop item is disabled (determinate by <see cref="ItemIsDisabled"/>). This class is applied to the element. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public string DisabledClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An additional class that is applied to the drop zone where a drag operation started
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string DraggingClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An additional class that is applied to an drop item, when it is dragged
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string ItemDraggingClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public bool AllowReorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, will only act as a dropable zone and not render any items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public bool OnlyZone { get; set; }
|
||||
|
||||
#region view helper
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
private int GetItemIndex(T item)
|
||||
{
|
||||
if (_indicies.ContainsKey(item) == false)
|
||||
@ -178,52 +87,6 @@ public partial class DropZone<T> : UIComponent, IDisposable
|
||||
return result;
|
||||
}
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("drop-zone")
|
||||
//.AddClass("drop-zone-drag-block", Container?.TransactionInProgress() == true && Container.GetTransactionOrignZoneIdentiifer() != Identifier)
|
||||
.AddClass(CanDropClass ?? Container?.CanDropClass, Container?.TransactionInProgress() == true && Container.GetTransactionOrignZoneIdentiifer() != Identifier && _canDrop == true && (_dragCounter > 0 || GetApplyDropClassesOnDragStarted() == true))
|
||||
.AddClass(NoDropClass ?? Container?.NoDropClass, Container?.TransactionInProgress() == true && Container.GetTransactionOrignZoneIdentiifer() != Identifier && _canDrop == false && (_dragCounter > 0 || GetApplyDropClassesOnDragStarted() == true))
|
||||
.AddClass(GetDragginClass(), _dragInProgress == true)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string PlaceholderClassname =>
|
||||
new CssBuilder("border-2 mud-border-primary border-dashed mud-chip-text mud-chip-color-primary pa-4 mud-dropitem-placeholder")
|
||||
.AddClass("d-none", AllowReorder == false || (Container?.TransactionInProgress() == false || Container.GetTransactionCurrentZoneIdentiifer() != Identifier))
|
||||
.Build();
|
||||
|
||||
#endregion
|
||||
|
||||
#region helper
|
||||
|
||||
private (T, bool) ItemCanBeDropped()
|
||||
{
|
||||
if (Container == null || Container.TransactionInProgress() == false)
|
||||
{
|
||||
return (default(T), false);
|
||||
}
|
||||
|
||||
var item = Container.GetTransactionItem();
|
||||
|
||||
var result = true;
|
||||
if (CanDrop != null)
|
||||
{
|
||||
result = CanDrop(item);
|
||||
}
|
||||
else if (Container.CanDrop != null)
|
||||
{
|
||||
result = Container.CanDrop(item, Identifier);
|
||||
}
|
||||
|
||||
return (item, result);
|
||||
}
|
||||
|
||||
private bool IsOrign(int index) => Container.IsOrign(index, Identifier);
|
||||
|
||||
#endregion
|
||||
|
||||
#region container event handling
|
||||
|
||||
private void Container_TransactionEnded(object sender, DragAndDropTransactionFinishedEventArgs<T> e)
|
||||
{
|
||||
_dragCounter = 0;
|
||||
@ -271,12 +134,6 @@ public partial class DropZone<T> : UIComponent, IDisposable
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region handling event callbacks
|
||||
|
||||
private int _dragCounter = 0;
|
||||
|
||||
private void HandleDragEnter()
|
||||
{
|
||||
_dragCounter++;
|
||||
@ -370,9 +227,160 @@ public partial class DropZone<T> : UIComponent, IDisposable
|
||||
private void FinishedDragOperation() => _dragInProgress = false;
|
||||
private void DragOperationStarted() => _dragInProgress = true;
|
||||
|
||||
private void Container_TransactionIndexChanged(object sender, DragAndDropIndexChangedEventArgs e)
|
||||
{
|
||||
if (e.ZoneIdentifier != Identifier && e.OldZoneIdentifier != Identifier) { return; }
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region life cycle
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Appearance)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The unique identifier of this drop zone. It is used within transaction to
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Appearance)]
|
||||
public string Identifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The render fragment (template) that should be used to render the items within a drop zone. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public RenderFragment<T> ItemRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Items)]
|
||||
public Func<T, bool> ItemsSelector { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
|
||||
/// <summary>
|
||||
/// The CSS class(es), that is applied to drop zones that are a valid target for drag and drop transaction. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public string CanDropClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The CSS class(es), that is applied to drop zones that are NOT valid target for drag and drop transaction. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public string NoDropClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item should be disabled for dragging. Defaults to allow all items. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public Func<T, bool> ItemIsDisabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a drop item is disabled (determinate by <see cref="ItemIsDisabled"/>). This class is applied to the element. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public string DisabledClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An additional class that is applied to the drop zone where a drag operation started
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string DraggingClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An additional class that is applied to an drop item, when it is dragged
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string ItemDraggingClass { get; set; }
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("drop-zone")
|
||||
//.AddClass("drop-zone-drag-block", Container?.TransactionInProgress() == true && Container.GetTransactionOrignZoneIdentiifer() != Identifier)
|
||||
.AddClass(CanDropClass ?? Container?.CanDropClass, Container?.TransactionInProgress() == true && Container.GetTransactionOrignZoneIdentiifer() != Identifier && _canDrop == true && (_dragCounter > 0 || GetApplyDropClassesOnDragStarted() == true))
|
||||
.AddClass(NoDropClass ?? Container?.NoDropClass, Container?.TransactionInProgress() == true && Container.GetTransactionOrignZoneIdentiifer() != Identifier && _canDrop == false && (_dragCounter > 0 || GetApplyDropClassesOnDragStarted() == true))
|
||||
.AddClass(GetDragginClass(), _dragInProgress == true)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string PlaceholderClassname =>
|
||||
new CssBuilder("border-2 mud-border-primary border-dashed mud-chip-text mud-chip-color-primary pa-4 mud-dropitem-placeholder")
|
||||
.AddClass("d-none", AllowReorder == false || (Container?.TransactionInProgress() == false || Container.GetTransactionCurrentZoneIdentiifer() != Identifier))
|
||||
.Build();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
|
||||
/// <summary>
|
||||
/// The method is used to determinate if an item can be dropped within a drop zone. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public Func<T, bool> CanDrop { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, drop classes CanDropClass <see cref="CanDropClass"/> or NoDropClass <see cref="NoDropClass"/> or applied as soon, as a transaction has started. Overrides value provided by drop container
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DropRules)]
|
||||
public bool? ApplyDropClassesOnDragStarted { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public bool AllowReorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, will only act as a dropable zone and not render any items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public bool OnlyZone { get; set; }
|
||||
|
||||
private (T, bool) ItemCanBeDropped()
|
||||
{
|
||||
if (Container == null || Container.TransactionInProgress() == false)
|
||||
{
|
||||
return (default(T), false);
|
||||
}
|
||||
|
||||
var item = Container.GetTransactionItem();
|
||||
|
||||
var result = true;
|
||||
if (CanDrop != null)
|
||||
{
|
||||
result = CanDrop(item);
|
||||
}
|
||||
else if (Container.CanDrop != null)
|
||||
{
|
||||
result = Container.CanDrop(item, Identifier);
|
||||
}
|
||||
|
||||
return (item, result);
|
||||
}
|
||||
|
||||
private bool IsOrign(int index) => Container.IsOrign(index, Identifier);
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
@ -388,12 +396,6 @@ public partial class DropZone<T> : UIComponent, IDisposable
|
||||
base.OnParametersSet();
|
||||
}
|
||||
|
||||
private void Container_TransactionIndexChanged(object sender, DragAndDropIndexChangedEventArgs e)
|
||||
{
|
||||
if (e.ZoneIdentifier != Identifier && e.OldZoneIdentifier != Identifier) { return; }
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
|
@ -11,39 +11,12 @@ namespace Connected.Components;
|
||||
|
||||
public partial class DynamicDropItem<T> : UIComponent
|
||||
{
|
||||
|
||||
#region Variables
|
||||
private bool _dragOperationIsInProgress = false;
|
||||
#endregion
|
||||
|
||||
[CascadingParameter]
|
||||
protected DropContainer<T> Container { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The zone identifier of the corresponding drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public string ZoneIdentifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the data item that is represneted by this item
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public T Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Appearance)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An additional class that is applied to this element when a drag operation is in progress
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string DraggingClass { get; set; }
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// An event callback set fires, when a drag operation has been started
|
||||
/// </summary>
|
||||
@ -58,30 +31,6 @@ public partial class DynamicDropItem<T> : UIComponent
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public EventCallback<T> OnDragEnded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When true, the item can't be dragged. defaults to false
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public bool Disabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The class that is applied when disabled <see cref="Disabled"/> is set to true
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public string DisabledClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Sorting)]
|
||||
public int Index { get; set; } = -1;
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Sorting)]
|
||||
public bool HideContent { get; set; }
|
||||
|
||||
#region Event handling and callbacks
|
||||
|
||||
private async Task DragStarted()
|
||||
{
|
||||
if (Container == null) { return; }
|
||||
@ -133,6 +82,58 @@ public partial class DynamicDropItem<T> : UIComponent
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
[CascadingParameter]
|
||||
protected DropContainer<T> Container { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The zone identifier of the corresponding drop zone
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public string ZoneIdentifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the data item that is represneted by this item
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Behavior)]
|
||||
public T Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Appearance)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
/// <summary>
|
||||
/// An additional class that is applied to this element when a drag operation is in progress
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.DraggingClass)]
|
||||
public string DraggingClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When true, the item can't be dragged. defaults to false
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public bool Disabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The class that is applied when disabled <see cref="Disabled"/> is set to true
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Disabled)]
|
||||
public string DisabledClass { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Sorting)]
|
||||
public int Index { get; set; } = -1;
|
||||
protected string Classname =>
|
||||
new CssBuilder("drop-item")
|
||||
.AddClass(DraggingClass, _dragOperationIsInProgress == true)
|
||||
@ -140,4 +141,13 @@ public partial class DynamicDropItem<T> : UIComponent
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.DropZone.Sorting)]
|
||||
public bool HideContent { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
</div>
|
||||
@if (!HideIcon)
|
||||
{
|
||||
<Icon Icon="@Icon" class="@(IsExpanded? "expand-panel-icon mud-transform" : "expand-panel-icon")" />
|
||||
<Icon Glyph="@Icon" class="@(IsExpanded? "expand-panel-icon mud-transform" : "expand-panel-icon")" />
|
||||
}
|
||||
</div>
|
||||
<Collapse Expanded="@_collapseIsExpanded" MaxHeight="@MaxHeight">
|
||||
|
@ -6,142 +6,14 @@ namespace Connected.Components;
|
||||
|
||||
public partial class ExpansionPanel : UIComponent, IDisposable
|
||||
{
|
||||
|
||||
#region Variables
|
||||
private bool _nextPanelExpanded;
|
||||
private bool _isExpanded;
|
||||
private bool _collapseIsExpanded;
|
||||
#endregion
|
||||
|
||||
[CascadingParameter] private ExpansionPanels Parent { get; set; }
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("expand-panel")
|
||||
.AddClass("panel-expanded", IsExpanded)
|
||||
.AddClass("panel-next-expanded", NextPanelExpanded)
|
||||
.AddClass("disabled", Disabled)
|
||||
.AddClass($"elevation-{Parent?.Elevation.ToString()}")
|
||||
.AddClass($"expand-panel-border", Parent?.DisableBorders != true)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string PanelContentClassname =>
|
||||
new CssBuilder("expand-panel-content")
|
||||
.AddClass("expand-panel-gutters", DisableGutters || Parent?.DisableGutters == true)
|
||||
.AddClass("expand-panel-dense", Dense || Parent?.Dense == true)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly sets the height for the Collapse element to override the css default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public int? MaxHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RenderFragment to be displayed in the expansion panel which will override header text if defined.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public RenderFragment TitleContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The text to be displayed in the expansion panel.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, expand icon will not show
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool HideIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom hide icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public string Icon { get; set; } = Icons.Material.Filled.ExpandMore;
|
||||
|
||||
/// <summary>
|
||||
/// If true, removes vertical padding from childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed from childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when IsExpanded changes.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<bool> IsExpandedChanged { get; set; }
|
||||
|
||||
internal event Action<ExpansionPanel> NotifyIsExpandedChanged;
|
||||
/// <summary>
|
||||
/// Expansion state of the panel (two-way bindable)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set
|
||||
{
|
||||
if (_isExpanded == value)
|
||||
return;
|
||||
_isExpanded = value;
|
||||
|
||||
NotifyIsExpandedChanged?.Invoke(this);
|
||||
IsExpandedChanged.InvokeAsync(_isExpanded).ContinueWith(t =>
|
||||
{
|
||||
if (_collapseIsExpanded != _isExpanded)
|
||||
{
|
||||
_collapseIsExpanded = _isExpanded;
|
||||
InvokeAsync(() => StateHasChanged());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the initial expansion state. Do not use in combination with IsExpanded.
|
||||
/// Combine with MultiExpansion to have more than one panel start open.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool IsInitiallyExpanded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the component will be disabled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
public bool NextPanelExpanded
|
||||
{
|
||||
get => _nextPanelExpanded;
|
||||
set
|
||||
{
|
||||
if (_nextPanelExpanded == value)
|
||||
return;
|
||||
_nextPanelExpanded = value;
|
||||
//InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
#region Events
|
||||
|
||||
public void ToggleExpansion()
|
||||
{
|
||||
@ -177,6 +49,152 @@ public partial class ExpansionPanel : UIComponent, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when IsExpanded changes.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<bool> IsExpandedChanged { get; set; }
|
||||
|
||||
internal event Action<ExpansionPanel> NotifyIsExpandedChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
[CascadingParameter] private ExpansionPanels Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RenderFragment to be displayed in the expansion panel which will override header text if defined.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public RenderFragment TitleContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The text to be displayed in the expansion panel.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("expand-panel")
|
||||
.AddClass("panel-expanded", IsExpanded)
|
||||
.AddClass("panel-next-expanded", NextPanelExpanded)
|
||||
.AddClass("disabled", Disabled)
|
||||
.AddClass($"elevation-{Parent?.Elevation.ToString()}")
|
||||
.AddClass($"expand-panel-border", Parent?.DisableBorders != true)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string PanelContentClassname =>
|
||||
new CssBuilder("expand-panel-content")
|
||||
.AddClass("expand-panel-gutters", DisableGutters || Parent?.DisableGutters == true)
|
||||
.AddClass("expand-panel-dense", Dense || Parent?.Dense == true)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly sets the height for the Collapse element to override the css default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public int? MaxHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, expand icon will not show
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool HideIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom hide icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public string Icon { get; set; } = Icons.Material.Filled.ExpandMore;
|
||||
|
||||
/// <summary>
|
||||
/// If true, removes vertical padding from childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed from childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expansion state of the panel (two-way bindable)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set
|
||||
{
|
||||
if (_isExpanded == value)
|
||||
return;
|
||||
_isExpanded = value;
|
||||
|
||||
NotifyIsExpandedChanged?.Invoke(this);
|
||||
IsExpandedChanged.InvokeAsync(_isExpanded).ContinueWith(t =>
|
||||
{
|
||||
if (_collapseIsExpanded != _isExpanded)
|
||||
{
|
||||
_collapseIsExpanded = _isExpanded;
|
||||
InvokeAsync(() => StateHasChanged());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, the component will be disabled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// Sets the initial expansion state. Do not use in combination with IsExpanded.
|
||||
/// Combine with MultiExpansion to have more than one panel start open.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool IsInitiallyExpanded { get; set; }
|
||||
|
||||
public bool NextPanelExpanded
|
||||
{
|
||||
get => _nextPanelExpanded;
|
||||
set
|
||||
{
|
||||
if (_nextPanelExpanded == value)
|
||||
return;
|
||||
_nextPanelExpanded = value;
|
||||
//InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// NOTE: we can't throw here because we need to be able to instanciate the type for the API Docs to infer default values
|
||||
@ -196,4 +214,6 @@ public partial class ExpansionPanel : UIComponent, IDisposable
|
||||
{
|
||||
Parent?.RemovePanel(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -7,63 +7,8 @@ namespace Connected.Components;
|
||||
|
||||
public partial class ExpansionPanels : UIComponent
|
||||
{
|
||||
protected string Classname =>
|
||||
new CssBuilder("expansion-panels")
|
||||
.AddClass($"expansion-panels-square", Square)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// If true, border-radius is set to 0.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool Square { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, multiple panels can be expanded at the same time.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool MultiExpansion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The higher the number, the heavier the drop-shadow. 0 for no shadow.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public int Elevation { set; get; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// If true, removes vertical padding from all panels' childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed from all panels' childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the borders around each panel will be removed.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool DisableBorders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
private List<ExpansionPanel> _panels = new();
|
||||
|
||||
#region Events
|
||||
internal void AddPanel(ExpansionPanel panel)
|
||||
{
|
||||
if (MultiExpansion == false && _panels.Any(p => p.IsExpanded))
|
||||
@ -109,13 +54,6 @@ public partial class ExpansionPanels : UIComponent
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
[Obsolete("Use CollapseAllExcept instead.")]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public void CloseAllExcept(ExpansionPanel panel)
|
||||
{
|
||||
CollapseAllExcept(panel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collapses all panels except the given one.
|
||||
/// </summary>
|
||||
@ -154,4 +92,69 @@ public partial class ExpansionPanels : UIComponent
|
||||
}
|
||||
this.InvokeAsync(UpdateAll);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
private List<ExpansionPanel> _panels = new();
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("expansion-panels")
|
||||
.AddClass($"expansion-panels-square", Square)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// If true, border-radius is set to 0.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool Square { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The higher the number, the heavier the drop-shadow. 0 for no shadow.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public int Elevation { set; get; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// If true, removes vertical padding from all panels' childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed from all panels' childcontent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the borders around each panel will be removed.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Appearance)]
|
||||
public bool DisableBorders { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, multiple panels can be expanded at the same time.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ExpansionPanel.Behavior)]
|
||||
public bool MultiExpansion { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,53 @@ namespace Connected.Components;
|
||||
//TODO Maybe can inherit from MudBaseInput?
|
||||
public partial class Field : UIComponent
|
||||
{
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Button click event if set and Adornment used.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<MouseEventArgs> OnAdornmentClick { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Data)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ErrorText that will be displayed if Error true
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Validation)]
|
||||
public string ErrorText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HelperText will be displayed below the text field.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string HelperText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If string has value the label text will be displayed in the input, and scaled down at the top if the field has value.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Text that will be used if Adornment is set to Start or End, the Text overrides Glyph.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string AdornmentText { get; set; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("input")
|
||||
.AddClass($"input-{Variant.ToDescription()}")
|
||||
@ -41,12 +88,7 @@ public partial class Field : UIComponent
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Data)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Will adjust vertical spacing.
|
||||
@ -62,20 +104,6 @@ public partial class Field : UIComponent
|
||||
[Category(CategoryTypes.Field.Validation)]
|
||||
public bool Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ErrorText that will be displayed if Error true
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Validation)]
|
||||
public string ErrorText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HelperText will be displayed below the text field.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string HelperText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the field will take up the full width of its container.
|
||||
/// </summary>
|
||||
@ -83,13 +111,6 @@ public partial class Field : UIComponent
|
||||
[Category(CategoryTypes.Field.Appearance)]
|
||||
public bool FullWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If string has value the label text will be displayed in the input, and scaled down at the top if the field has value.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Variant can be Text, Filled or Outlined.
|
||||
/// </summary>
|
||||
@ -111,13 +132,6 @@ public partial class Field : UIComponent
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string AdornmentIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Text that will be used if Adornment is set to Start or End, the Text overrides Glyph.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Behavior)]
|
||||
public string AdornmentText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Adornment if used. By default, it is set to None.
|
||||
/// </summary>
|
||||
@ -139,11 +153,6 @@ public partial class Field : UIComponent
|
||||
[Category(CategoryTypes.Field.Appearance)]
|
||||
public Size IconSize { get; set; } = Size.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Button click event if set and Adornment used.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<MouseEventArgs> OnAdornmentClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the inner contents padding is removed.
|
||||
/// </summary>
|
||||
@ -157,4 +166,6 @@ public partial class Field : UIComponent
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Field.Appearance)]
|
||||
public bool DisableUnderLine { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -12,32 +12,11 @@ namespace Connected.Components;
|
||||
|
||||
public partial class FileUpload<T> : FormComponent<T, string>
|
||||
{
|
||||
public FileUpload() : base(new DefaultConverter<T>()) { }
|
||||
|
||||
#region Variables
|
||||
private readonly string _id = $"mud_fileupload_{Guid.NewGuid()}";
|
||||
#endregion
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("file-upload")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// The value of the MudFileUpload component.
|
||||
/// If T is <see cref="IBrowserFile">IBrowserFile</see>, it represents a single file.
|
||||
/// If T is <see cref="IReadOnlyCollection{IBrowserFile}">IReadOnlyList<IBrowserFile></see>, it represents multiple files
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public T Files
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value != null && _value.Equals(value))
|
||||
return;
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Triggered when the internal OnChange event fires
|
||||
/// </summary>
|
||||
@ -51,48 +30,6 @@ public partial class FileUpload<T> : FormComponent<T, string>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public EventCallback<InputFileChangeEventArgs> OnFilesChanged { get; set; }
|
||||
/// <summary>
|
||||
/// Renders the button that triggers the input. Required for functioning.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public RenderFragment<string> ButtonTemplate { get; set; }
|
||||
/// <summary>
|
||||
/// Renders the selected files, if desired.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public RenderFragment<T> SelectedTemplate { get; set; }
|
||||
/// <summary>
|
||||
/// If true, OnFilesChanged will not trigger if validation fails
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public bool SuppressOnChangeWhenInvalid { get; set; }
|
||||
/// <summary>
|
||||
/// Sets the file types this input will accept
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public string Accept { get; set; }
|
||||
/// <summary>
|
||||
/// If false, the inner FileInput will be visible
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public bool Hidden { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Css classes to apply to the internal InputFile
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public string InputClass { get; set; }
|
||||
/// <summary>
|
||||
/// Style to apply to the internal InputFile
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public string InputStyle { get; set; }
|
||||
|
||||
private async Task OnChange(InputFileChangeEventArgs args)
|
||||
{
|
||||
@ -112,6 +49,86 @@ public partial class FileUpload<T> : FormComponent<T, string>
|
||||
if (!HasError || !SuppressOnChangeWhenInvalid) //only trigger FilesChanged if validation passes or SuppressOnChangeWhenInvalid is false
|
||||
await OnFilesChanged.InvokeAsync(args);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// The value of the MudFileUpload component.
|
||||
/// If T is <see cref="IBrowserFile">IBrowserFile</see>, it represents a single file.
|
||||
/// If T is <see cref="IReadOnlyCollection{IBrowserFile}">IReadOnlyList<IBrowserFile></see>, it represents multiple files
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public T Files
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value != null && _value.Equals(value))
|
||||
return;
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("file-upload")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renders the button that triggers the input. Required for functioning.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public RenderFragment<string> ButtonTemplate { get; set; }
|
||||
/// <summary>
|
||||
/// Renders the selected files, if desired.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public RenderFragment<T> SelectedTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If false, the inner FileInput will be visible
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public bool Hidden { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Css classes to apply to the internal InputFile
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public string InputClass { get; set; }
|
||||
/// <summary>
|
||||
/// Style to apply to the internal InputFile
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Appearance)]
|
||||
public string InputStyle { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, OnFilesChanged will not trigger if validation fails
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public bool SuppressOnChangeWhenInvalid { get; set; }
|
||||
/// <summary>
|
||||
/// Sets the file types this input will accept
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FileUpload.Behavior)]
|
||||
public string Accept { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
public FileUpload() : base(new DefaultConverter<T>()) { }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
@ -120,4 +137,7 @@ public partial class FileUpload<T> : FormComponent<T, string>
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -7,11 +7,7 @@ namespace Connected.Components;
|
||||
|
||||
public partial class FocusTrap : IDisposable
|
||||
{
|
||||
protected string Classname =>
|
||||
new CssBuilder("outline-none")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
#region Variables
|
||||
protected ElementReference _firstBumper;
|
||||
protected ElementReference _lastBumper;
|
||||
protected ElementReference _fallback;
|
||||
@ -21,50 +17,10 @@ public partial class FocusTrap : IDisposable
|
||||
private bool _disabled;
|
||||
private bool _initialized;
|
||||
|
||||
/// <summary>
|
||||
/// Child content of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FocusTrap.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the focus will no longer loop inside the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FocusTrap.Behavior)]
|
||||
public bool Disabled
|
||||
{
|
||||
get => _disabled;
|
||||
set
|
||||
{
|
||||
if (_disabled != value)
|
||||
{
|
||||
_disabled = value;
|
||||
_initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines on which element to set the focus when the component is created or enabled.
|
||||
/// When DefaultFocus.Element is used, the focus will be set to the FocusTrap itself, so the user will have to press TAB key once to focus the first tabbable element.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FocusTrap.Behavior)]
|
||||
public DefaultFocus DefaultFocus { get; set; } = DefaultFocus.FirstChild;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender)
|
||||
await SaveFocusAsync();
|
||||
|
||||
if (!_initialized)
|
||||
await InitializeFocusAsync();
|
||||
}
|
||||
bool _shouldRender = true;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
private Task OnBottomFocusAsync(FocusEventArgs args)
|
||||
{
|
||||
return FocusLastAsync();
|
||||
@ -142,9 +98,50 @@ public partial class FocusTrap : IDisposable
|
||||
{
|
||||
return _root.SaveFocusAsync().AsTask();
|
||||
}
|
||||
#endregion
|
||||
|
||||
bool _shouldRender = true;
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FocusTrap.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("outline-none")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Defines on which element to set the focus when the component is created or enabled.
|
||||
/// When DefaultFocus.Element is used, the focus will be set to the FocusTrap itself, so the user will have to press TAB key once to focus the first tabbable element.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FocusTrap.Behavior)]
|
||||
public DefaultFocus DefaultFocus { get; set; } = DefaultFocus.FirstChild;
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, the focus will no longer loop inside the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FocusTrap.Behavior)]
|
||||
public bool Disabled
|
||||
{
|
||||
get => _disabled;
|
||||
set
|
||||
{
|
||||
if (_disabled != value)
|
||||
{
|
||||
_disabled = value;
|
||||
_initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
if (_shouldRender)
|
||||
@ -153,9 +150,25 @@ public partial class FocusTrap : IDisposable
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender)
|
||||
await SaveFocusAsync();
|
||||
|
||||
if (!_initialized)
|
||||
await InitializeFocusAsync();
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disabled)
|
||||
RestoreFocusAsync().AndForget(TaskOption.Safe);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -6,37 +6,23 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Form : UIComponent, IDisposable, IForm
|
||||
{
|
||||
protected string Classname =>
|
||||
new CssBuilder("form")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidatedData)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Validation status. True if the form is valid and without errors. This parameter is two-way bindable.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidationResult)]
|
||||
public bool IsValid
|
||||
{
|
||||
get => _valid && ChildForms.All(x => x.IsValid);
|
||||
set
|
||||
{
|
||||
_valid = value;
|
||||
}
|
||||
}
|
||||
|
||||
#region Variables
|
||||
// Note: w/o any children the form is automatically valid.
|
||||
// It stays valid, as long as non-required fields are added or
|
||||
// a required field is added or the user touches a field that fails validation.
|
||||
private bool _valid = true;
|
||||
|
||||
private bool _touched = false;
|
||||
|
||||
protected HashSet<IFormComponent> _formControls = new();
|
||||
protected HashSet<string> _errors = new();
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
private bool _shouldRender = true; // <-- default is true, we need the form children to render
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
private void SetIsValid(bool value)
|
||||
{
|
||||
if (IsValid == value)
|
||||
@ -45,47 +31,6 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
IsValidChanged.InvokeAsync(IsValid).AndForget();
|
||||
}
|
||||
|
||||
// Note: w/o any children the form is automatically valid.
|
||||
// It stays valid, as long as non-required fields are added or
|
||||
// a required field is added or the user touches a field that fails validation.
|
||||
|
||||
/// <summary>
|
||||
/// True if any field of the field was touched. This parameter is readonly.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public bool IsTouched { get => _touched; set {/* readonly parameter! */ } }
|
||||
|
||||
private bool _touched = false;
|
||||
|
||||
/// <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 ChangeTextImmediately="true".
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public int ValidationDelay { get; set; } = 300;
|
||||
|
||||
/// <summary>
|
||||
/// When true, the form will not re-render its child contents on validation updates (i.e. when IsValid changes).
|
||||
/// This is an optimization which can be necessary especially for larger forms on older devices.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public bool SuppressRenderingOnValidation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// When true, will not cause a page refresh on Enter if any input has focus.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// https://www.w3.org/TR/2018/SPSD-html5-20180327/forms.html#implicit-submission
|
||||
/// Usually this is not wanted, as it can cause a page refresh in the middle of editing a form.
|
||||
/// When the form is in a dialog this will cause the dialog to close. So by default we suppress it.
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public bool SuppressImplicitSubmission { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when IsValid changes.
|
||||
/// </summary>
|
||||
@ -101,60 +46,8 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<FormFieldChangedEventArgs> FieldChanged { get; set; }
|
||||
|
||||
// keeps track of validation. if the input was validated at least once the value will be true
|
||||
protected HashSet<IFormComponent> _formControls = new();
|
||||
protected HashSet<string> _errors = new();
|
||||
|
||||
/// <summary>
|
||||
/// A default validation func or a validation attribute to use for form controls that don't have one.
|
||||
/// Supported types are:
|
||||
/// <para>Func<T, bool> ... will output the standard error message "Invalid" if false</para>
|
||||
/// <para>Func<T, string> ... outputs the result as error message, no error if null </para>
|
||||
/// <para>Func<T, IEnumerable< string >> ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>Func<object, string, IEnumerable< string >> input Form.Model, Full Path of Member ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>Func<T, Task< bool >> ... will output the standard error message "Invalid" if false</para>
|
||||
/// <para>Func<T, Task< string >> ... outputs the result as error message, no error if null</para>
|
||||
/// <para>Func<T, Task<IEnumerable< string >>> ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>Func<object, string, Task<IEnumerable< string >>> input Form.Model, Full Path of Member ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>System.ComponentModel.DataAnnotations.ValidationAttribute instances</para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.Validation)]
|
||||
public object Validation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a field already has a validation, override it with <see cref="Validation"/>.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.Validation)]
|
||||
public bool? OverrideFieldValidation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Validation error messages.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidationResult)]
|
||||
public string[] Errors
|
||||
{
|
||||
get => _errors.ToArray();
|
||||
set { /* readonly */ }
|
||||
}
|
||||
|
||||
[Parameter] public EventCallback<string[]> ErrorsChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the top-level model object for the form. Used with Fluent Validation
|
||||
/// </summary>
|
||||
#nullable enable
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidatedData)]
|
||||
public object? Model { get; set; }
|
||||
#nullable disable
|
||||
|
||||
private HashSet<Form> ChildForms { get; set; } = new HashSet<Form>();
|
||||
|
||||
[CascadingParameter] private Form ParentForm { get; set; }
|
||||
|
||||
void IForm.FieldChanged(IFormComponent formControl, object newValue)
|
||||
{
|
||||
FieldChanged.InvokeAsync(new FormFieldChangedEventArgs { Field = formControl, NewValue = newValue }).AndForget();
|
||||
@ -173,8 +66,6 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
_formControls.Remove(formControl);
|
||||
}
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
/// <summary>
|
||||
/// Called by any input of the form to signal that its value changed.
|
||||
/// </summary>
|
||||
@ -195,8 +86,6 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
|
||||
private void OnTimerComplete(object stateInfo) => InvokeAsync(OnEvaluateForm);
|
||||
|
||||
private bool _shouldRender = true; // <-- default is true, we need the form children to render
|
||||
|
||||
protected async Task OnEvaluateForm()
|
||||
{
|
||||
_errors.Clear();
|
||||
@ -282,7 +171,143 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
|
||||
EvaluateForm(debounce: false);
|
||||
}
|
||||
private void SetDefaultControlValidation(IFormComponent formComponent)
|
||||
{
|
||||
if (Validation == null) return;
|
||||
|
||||
if (!formComponent.IsForNull && (formComponent.Validation == null || (OverrideFieldValidation ?? true)))
|
||||
{
|
||||
formComponent.Validation = Validation;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidatedData)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
private HashSet<Form> ChildForms { get; set; } = new HashSet<Form>();
|
||||
[CascadingParameter] private Form ParentForm { get; set; }
|
||||
|
||||
|
||||
// keeps track of validation. if the input was validated at least once the value will be true
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A default validation func or a validation attribute to use for form controls that don't have one.
|
||||
/// Supported types are:
|
||||
/// <para>Func<T, bool> ... will output the standard error message "Invalid" if false</para>
|
||||
/// <para>Func<T, string> ... outputs the result as error message, no error if null </para>
|
||||
/// <para>Func<T, IEnumerable< string >> ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>Func<object, string, IEnumerable< string >> input Form.Model, Full Path of Member ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>Func<T, Task< bool >> ... will output the standard error message "Invalid" if false</para>
|
||||
/// <para>Func<T, Task< string >> ... outputs the result as error message, no error if null</para>
|
||||
/// <para>Func<T, Task<IEnumerable< string >>> ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>Func<object, string, Task<IEnumerable< string >>> input Form.Model, Full Path of Member ... outputs all the returned error messages, no error if empty</para>
|
||||
/// <para>System.ComponentModel.DataAnnotations.ValidationAttribute instances</para>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.Validation)]
|
||||
public object Validation { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Validation error messages.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidationResult)]
|
||||
public string[] Errors
|
||||
{
|
||||
get => _errors.ToArray();
|
||||
set { /* readonly */ }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the top-level model object for the form. Used with Fluent Validation
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidatedData)]
|
||||
public object? Model { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("form")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
|
||||
// Note: w/o any children the form is automatically valid.
|
||||
// It stays valid, as long as non-required fields are added or
|
||||
// a required field is added or the user touches a field that fails validation.
|
||||
|
||||
|
||||
/// <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 ChangeTextImmediately="true".
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public int ValidationDelay { get; set; } = 300;
|
||||
|
||||
/// <summary>
|
||||
/// Validation status. True if the form is valid and without errors. This parameter is two-way bindable.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.ValidationResult)]
|
||||
public bool IsValid
|
||||
{
|
||||
get => _valid && ChildForms.All(x => x.IsValid);
|
||||
set
|
||||
{
|
||||
_valid = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if any field of the field was touched. This parameter is readonly.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public bool IsTouched { get => _touched; set {/* readonly parameter! */ } }
|
||||
|
||||
/// <summary>
|
||||
/// When true, the form will not re-render its child contents on validation updates (i.e. when IsValid changes).
|
||||
/// This is an optimization which can be necessary especially for larger forms on older devices.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public bool SuppressRenderingOnValidation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// When true, will not cause a page refresh on Enter if any input has focus.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// https://www.w3.org/TR/2018/SPSD-html5-20180327/forms.html#implicit-submission
|
||||
/// Usually this is not wanted, as it can cause a page refresh in the middle of editing a form.
|
||||
/// When the form is in a dialog this will cause the dialog to close. So by default we suppress it.
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Form.Behavior)]
|
||||
public bool SuppressImplicitSubmission { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// If a field already has a validation, override it with <see cref="Validation"/>.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.Validation)]
|
||||
public bool? OverrideFieldValidation { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
@ -299,16 +324,6 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
return base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
private void SetDefaultControlValidation(IFormComponent formComponent)
|
||||
{
|
||||
if (Validation == null) return;
|
||||
|
||||
if (!formComponent.IsForNull && (formComponent.Validation == null || (OverrideFieldValidation ?? true)))
|
||||
{
|
||||
formComponent.Validation = Validation;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (ParentForm != null)
|
||||
@ -323,4 +338,21 @@ public partial class Form : UIComponent, IDisposable, IForm
|
||||
{
|
||||
_timer?.Dispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,13 +6,7 @@ namespace Connected.Components;
|
||||
public partial class Grid
|
||||
{
|
||||
|
||||
#region Event callbacks
|
||||
#endregion
|
||||
|
||||
#region Content placeholders
|
||||
#endregion
|
||||
|
||||
#region Styling properties
|
||||
#region Styling
|
||||
|
||||
private CssBuilder CompiledClassList
|
||||
{
|
||||
@ -42,8 +36,5 @@ public partial class Grid
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
@ -5,10 +5,7 @@ namespace Connected.Components;
|
||||
public partial class Item
|
||||
{
|
||||
|
||||
#region Event callbacks
|
||||
#endregion
|
||||
|
||||
#region Content placeholders
|
||||
#region Content
|
||||
|
||||
[CascadingParameter]
|
||||
private Grid Parent { get; set; }
|
||||
@ -25,7 +22,7 @@ public partial class Item
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styling properties
|
||||
#region Styling
|
||||
|
||||
private CssBuilder CompiledClassList
|
||||
{
|
||||
@ -50,7 +47,7 @@ public partial class Item
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle events
|
||||
#region Lifecycle
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
@ -58,19 +55,8 @@ public partial class Item
|
||||
//if (Parent == null)
|
||||
// throw new ArgumentNullException(nameof(Parent), "Item must exist within a Grid");
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ToDo false,auto,true on all sizes.
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -7,61 +7,24 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Hidden : UIComponent, IAsyncDisposable
|
||||
{
|
||||
#region Variables
|
||||
private Breakpoint _currentBreakpoint = Breakpoint.None;
|
||||
private bool _serviceIsReady = false;
|
||||
private Guid _breakpointServiceSubscriptionId;
|
||||
private bool _isHidden = true;
|
||||
|
||||
[Inject] public IBreakpointService BreakpointService { get; set; }
|
||||
|
||||
[CascadingParameter] public Breakpoint CurrentBreakpointFromProvider { get; set; } = Breakpoint.None;
|
||||
|
||||
/// <summary>
|
||||
/// The screen size(s) depending on which the ChildContent should not be rendered (or should be, if Invert is true)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public Breakpoint Breakpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Inverts the Breakpoint, so that the ChildContent is only rendered when the breakpoint matches the screen size.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public bool Invert { get; set; }
|
||||
|
||||
private bool _isHidden = true;
|
||||
|
||||
/// <summary>
|
||||
/// True if the component is not visible (two-way bindable)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public bool IsHidden
|
||||
{
|
||||
get => _isHidden;
|
||||
set
|
||||
{
|
||||
if (_isHidden != value)
|
||||
{
|
||||
_isHidden = value;
|
||||
IsHiddenChanged.InvokeAsync(_isHidden);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Fires when the breakpoint changes visibility of the component
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<bool> IsHiddenChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
protected void Update(Breakpoint currentBreakpoint)
|
||||
{
|
||||
if (CurrentBreakpointFromProvider != Breakpoint.None)
|
||||
@ -82,7 +45,54 @@ public partial class Hidden : UIComponent, IAsyncDisposable
|
||||
|
||||
IsHidden = hidden;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
/// <summary>
|
||||
/// The screen size(s) depending on which the ChildContent should not be rendered (or should be, if Invert is true)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public Breakpoint Breakpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Inverts the Breakpoint, so that the ChildContent is only rendered when the breakpoint matches the screen size.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public bool Invert { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the component is not visible (two-way bindable)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Hidden.Behavior)]
|
||||
public bool IsHidden
|
||||
{
|
||||
get => _isHidden;
|
||||
set
|
||||
{
|
||||
if (_isHidden != value)
|
||||
{
|
||||
_isHidden = value;
|
||||
IsHiddenChanged.InvokeAsync(_isHidden);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
base.OnParametersSet();
|
||||
@ -115,4 +125,6 @@ public partial class Hidden : UIComponent, IAsyncDisposable
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync() => await BreakpointService.Unsubscribe(_breakpointServiceSubscriptionId);
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -10,9 +10,12 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Highlighter : UIComponent
|
||||
{
|
||||
#region Variables
|
||||
private Memory<string> _fragments;
|
||||
private string _regex;
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// The whole text in which a fragment will be highlighted
|
||||
/// </summary>
|
||||
@ -33,27 +36,34 @@ public partial class Highlighter : UIComponent
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Highlighter.Behavior)]
|
||||
public IEnumerable<string> HighlightedTexts { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
/// <summary>
|
||||
/// Whether or not the highlighted text is case sensitive
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Highlighter.Behavior)]
|
||||
public bool CaseSensitive { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, highlights the text until the next regex boundary
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Highlighter.Behavior)]
|
||||
public bool UntilNextBoundary { get; set; }
|
||||
public bool HighlightUntilNextBoundary { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
//TODO
|
||||
//Accept regex highlightings
|
||||
// [Parameter] public bool IsRegex { get; set; }
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
_fragments = GetFragments(Text, HighlightedText, HighlightedTexts, out _regex, CaseSensitive, UntilNextBoundary);
|
||||
_fragments = GetFragments(Text, HighlightedText, HighlightedTexts, out _regex, CaseSensitive, HighlightUntilNextBoundary);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,24 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Icon : UIComponent
|
||||
{
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// GlyphTitle of the icon used for accessibility.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Icon.Behavior)]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Icon.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("icon-root")
|
||||
.AddClass($"icon-default", Color == ThemeColor.Default)
|
||||
@ -23,13 +41,6 @@ public partial class Icon : UIComponent
|
||||
[Category(CategoryTypes.Icon.Behavior)]
|
||||
public string Glyph { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GlyphTitle of the icon used for accessibility.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Icon.Behavior)]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Size of the icon.
|
||||
/// </summary>
|
||||
@ -50,11 +61,7 @@ public partial class Icon : UIComponent
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Icon.Behavior)]
|
||||
public string ViewBox { get; set; } = "0 0 24 24";
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Icon.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// MudBlazor licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Connected.Annotations;
|
||||
using Connected.Extensions;
|
||||
using Connected.Utilities;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@ -11,7 +10,39 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Image : UIComponent
|
||||
{
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Specifies the path to the image.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Src { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies an alternate text for the image.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Alt { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the height of the image in px.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int? Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the width of the image in px.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int? Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The higher the number, the heavier the drop-shadow.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int Elevation { set; get; }
|
||||
private CssBuilder CompiledClassList
|
||||
{
|
||||
get
|
||||
@ -31,36 +62,6 @@ public partial class Image : UIComponent
|
||||
[Parameter]
|
||||
public bool Fluid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the path to the image.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Src { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies an alternate text for the image.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Alt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the height of the image in px.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int? Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the width of the image in px.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int? Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The higher the number, the heavier the drop-shadow.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int Elevation { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// Controls how the image should be resized.
|
||||
/// </summary>
|
||||
@ -78,4 +79,6 @@ public partial class Image : UIComponent
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? ClassList { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -2,28 +2,11 @@
|
||||
@typeparam T
|
||||
@inherits InputBase<T>
|
||||
|
||||
<CascadingValue Name="SubscribeToParentForm" Value="@base.SubscribeToParentForm" IsFixed="true">
|
||||
<div class="@CompiledWrapperClass.Build()">
|
||||
<InputControl Label="@Label"
|
||||
Variant="@Variant"
|
||||
HelperText="@HelperText"
|
||||
HelperTextOnFocus="@HelperTextOnFocus"
|
||||
CounterText="@GetCounterText()"
|
||||
FullWidth="@FullWidth"
|
||||
class="@CompiledHelperContainerClassList.Build()"
|
||||
Error="@HasErrors"
|
||||
ErrorText="@GetErrorText()"
|
||||
ErrorId="@ErrorId"
|
||||
Disabled="@Disabled"
|
||||
Margin="@Margin"
|
||||
Required="@Required"
|
||||
ForId="@FieldId">
|
||||
<InputContent>
|
||||
<CascadingValue Name="SubscribeToParentForm" Value="false" IsFixed="true">
|
||||
|
||||
<div class="@WrapperClassList" style="@Style">
|
||||
@if (Adornment == Adornment.Start)
|
||||
{
|
||||
<InputAdornment Class="@CompiledAdornmentClass.Build()"
|
||||
<InputAdornment Class="@AdornmentClassList"
|
||||
Icon="@AdornmentIcon"
|
||||
Color="@AdornmentColor"
|
||||
Size="@IconSize"
|
||||
@ -34,12 +17,11 @@
|
||||
/>
|
||||
}
|
||||
|
||||
@if (NumberOfLines > 1)
|
||||
@if (Lines > 1)
|
||||
{
|
||||
<textarea class="@CompiledInputClass.Build()"
|
||||
<textarea class="@InputClassList"
|
||||
@ref="ElementReference"
|
||||
rows="@NumberOfLines"
|
||||
@attributes="@Attributes"
|
||||
rows="@Lines"
|
||||
type="@InputTypeString"
|
||||
placeholder="@Placeholder"
|
||||
disabled=@Disabled
|
||||
@ -59,7 +41,7 @@
|
||||
@onkeyup:preventDefault="@KeyUpPreventDefault"
|
||||
@onmousewheel="@OnMouseWheel"
|
||||
@onwheel="@OnMouseWheel"
|
||||
aria-invalid="@HasError.ToString().ToLower()"
|
||||
aria-invalid="@GetErrorText()"
|
||||
aria-describedby="@ErrorId"
|
||||
>
|
||||
@Text
|
||||
@ -69,13 +51,12 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<input class="@CompiledInputClass.Build()"
|
||||
<input class="@InputClassList"
|
||||
@ref="ElementReference"
|
||||
@attributes="@Attributes"
|
||||
step="@Step"
|
||||
type="@InputTypeString"
|
||||
value="@_internalText"
|
||||
@oninput="OnInput"
|
||||
step="@Step"
|
||||
@onchange="OnChange"
|
||||
placeholder="@Placeholder"
|
||||
disabled=@Disabled
|
||||
@ -92,7 +73,7 @@
|
||||
@onkeyup:preventDefault="@KeyUpPreventDefault"
|
||||
@onmousewheel="@OnMouseWheel"
|
||||
@onwheel="@OnMouseWheel"
|
||||
aria-invalid="@HasError.ToString().ToLower()"
|
||||
aria-invalid="@GetErrorText()"
|
||||
aria-describedby="@ErrorId"
|
||||
/>
|
||||
@*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@
|
||||
@ -101,7 +82,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="@CompiledInputClass.Build()"
|
||||
<div class="@InputClassList"
|
||||
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
|
||||
@onblur="@OnBlurred" @ref="@_elementReference1"
|
||||
>
|
||||
@ -111,7 +92,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="@CompiledInputClass.Build()"
|
||||
<div class="@InputClassList"
|
||||
style="@("display:"+(InputType == InputType.Hidden && ChildContent != null ? "inline" : "none"))"
|
||||
tabindex="@(InputType == InputType.Hidden && ChildContent != null ? 0 : -1)"
|
||||
@onblur="@OnBlurred" @ref="@_elementReference1"
|
||||
@ -123,16 +104,17 @@
|
||||
|
||||
@if (_showClearable && !Disabled)
|
||||
{
|
||||
<IconButton ClassList="@CompiledClearButtonClassList.Build()"
|
||||
Icon="@ClearIcon"
|
||||
<GlyphButton ClassList="@ClearButtonClassList"
|
||||
Glyph="@ClearIcon"
|
||||
Clicked="@ClearButtonClickHandlerAsync"
|
||||
aria-label="Clear"
|
||||
tabindex="-1"
|
||||
/>
|
||||
}
|
||||
|
||||
@if (Adornment == Adornment.End)
|
||||
{
|
||||
<InputAdornment Class="@CompiledAdornmentClass.Build()"
|
||||
<InputAdornment Class="@AdornmentClassList"
|
||||
Icon="@AdornmentIcon"
|
||||
Color="@AdornmentColor"
|
||||
Size="@IconSize"
|
||||
@ -145,25 +127,18 @@
|
||||
|
||||
@if (Variant == Variant.Outlined)
|
||||
{
|
||||
<div class="input-outlined-border"></div>
|
||||
<div class="mud-input-outlined-border"></div>
|
||||
}
|
||||
|
||||
@if (!HideSpinButtons)
|
||||
{
|
||||
<div class="input-numeric-spin">
|
||||
<Button Variant="Variant.Text" Clicked="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
|
||||
<Icon Icon="@NumericUpIcon" Size="@GetButtonSize()" />
|
||||
<div class="mud-input-numeric-spin">
|
||||
<Button Variant="Variant.Text" @onclick="OnIncrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
|
||||
<Icon aria-label="Increment" Glyph="@NumericUpIcon" Size="@GetButtonSize()" />
|
||||
</Button>
|
||||
<Button Variant="Variant.Text" Clicked="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
|
||||
<Icon Icon="@NumericDownIcon" Size="@GetButtonSize()" />
|
||||
<Button Variant="Variant.Text" @onclick="OnDecrement" Disabled="@(Disabled || ReadOnly)" tabindex="-1">
|
||||
<Icon aria-label="Decrement" Glyph="@NumericDownIcon" Size="@GetButtonSize()" />
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
</CascadingValue>
|
||||
</InputContent>
|
||||
</InputControl>
|
||||
</div>
|
||||
</CascadingValue>
|
||||
|
||||
|
||||
|
||||
|
@ -45,6 +45,7 @@ public partial class Input<T> : InputBase<T>
|
||||
// This method is called when Value property needs to be refreshed from the current Text property, so typically because Text property has changed.
|
||||
// We want to debounce only text-input, not a value being set, so the debouncing is only done when updateText==false (because that indicates the
|
||||
// change came from a Text setter)
|
||||
|
||||
if (updateText)
|
||||
{
|
||||
// we have a change coming not from the Text setter, no debouncing is needed
|
||||
@ -72,11 +73,36 @@ public partial class Input<T> : InputBase<T>
|
||||
}
|
||||
protected Task OnInput(ChangeEventArgs args)
|
||||
{
|
||||
var input = args.Value.ToString();
|
||||
/*if (InputType==InputType.Number)
|
||||
{
|
||||
if (!Helper.IsNumeric(input))
|
||||
{
|
||||
input = Regex.Replace(input, "[^0-9.]", "");
|
||||
Text = input;
|
||||
UpdateValuePropertyAsync(true);
|
||||
}
|
||||
}*/
|
||||
if (!ChangeTextImmediately)
|
||||
return Task.CompletedTask;
|
||||
_isFocused = true;
|
||||
return SetTextAsync(args?.Value as string);
|
||||
return SetTextAsync(input);
|
||||
}
|
||||
|
||||
protected virtual void OnKeyDown(KeyboardEventArgs obj)
|
||||
{
|
||||
if (InputType == InputType.Number)
|
||||
{
|
||||
if (Helper.IsNumeric(obj.Key))
|
||||
{
|
||||
_isFocused = true;
|
||||
base.OnKeyDown.InvokeAsync(obj).AndForget();
|
||||
}
|
||||
} else
|
||||
{
|
||||
_isFocused = true;
|
||||
base.OnKeyDown.InvokeAsync(obj).AndForget();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task OnChange(ChangeEventArgs args)
|
||||
@ -95,7 +121,6 @@ public partial class Input<T> : InputBase<T>
|
||||
await SetTextAsync(args?.Value as string);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -178,8 +203,6 @@ public partial class Input<T> : InputBase<T>
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Style properties
|
||||
|
||||
/// <summary>
|
||||
@ -209,25 +232,52 @@ public partial class Input<T> : InputBase<T>
|
||||
[Parameter] public bool Clearable { get; set; } = false;
|
||||
|
||||
#region Wrapper class
|
||||
/*[Parameter]
|
||||
public string WrapperClass { get; set; } = string.Empty;*/
|
||||
|
||||
/*protected string WrapperClass => InputCssHelper.GetClassname(this,
|
||||
() => HasNativeHtmlPlaceholder() || !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(Placeholder));*/
|
||||
|
||||
[Parameter]
|
||||
public string WrapperClass { get; set; } = string.Empty;
|
||||
protected CssBuilder CompiledWrapperClass
|
||||
public string ClassList { get; set; } = string.Empty;
|
||||
|
||||
protected string WrapperClassList
|
||||
{
|
||||
get
|
||||
{
|
||||
return new CssBuilder("input")
|
||||
/*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)
|
||||
.Build();*/
|
||||
|
||||
var clasList = 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("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);
|
||||
.AddClass(ClassList)
|
||||
.Build();
|
||||
return clasList;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User styles, applied on top of the component's own classes and styles.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
|
||||
|
||||
#endregion
|
||||
@ -235,8 +285,8 @@ public partial class Input<T> : InputBase<T>
|
||||
#region Input field class
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } = string.Empty;
|
||||
protected CssBuilder CompiledInputClass
|
||||
public string InputClass { get; set; } = string.Empty;
|
||||
protected string InputClassList
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -245,7 +295,10 @@ public partial class Input<T> : InputBase<T>
|
||||
.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(Class);
|
||||
.AddClass(InputClass)
|
||||
.Build();
|
||||
|
||||
//return new CssBuilder().AddClass(InputCssHelper.GetInputClassname(this)).Build();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -253,7 +306,7 @@ public partial class Input<T> : InputBase<T>
|
||||
#region Adornment class
|
||||
[Parameter]
|
||||
public string AdornmentClass { get; set; } = string.Empty;
|
||||
protected CssBuilder CompiledAdornmentClass
|
||||
protected string AdornmentClassList
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -261,7 +314,10 @@ public partial class Input<T> : InputBase<T>
|
||||
.AddClass($"input-adornment-{Adornment.ToDescription()}", Adornment != Adornment.None)
|
||||
.AddClass($"text", !string.IsNullOrEmpty(AdornmentText))
|
||||
.AddClass($"input-root-filled-shrink", Variant == Variant.Filled)
|
||||
.AddClass(AdornmentClass);
|
||||
.AddClass(AdornmentClass)
|
||||
.Build();
|
||||
|
||||
//return new CssBuilder().AddClass(InputCssHelper.GetAdornmentClassname(this)).Build();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -269,7 +325,7 @@ public partial class Input<T> : InputBase<T>
|
||||
#region Clear icon class
|
||||
[Parameter]
|
||||
public string ClearButtonClass { get; set; } = string.Empty;
|
||||
protected CssBuilder CompiledClearButtonClassList
|
||||
protected string ClearButtonClassList
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -277,8 +333,9 @@ public partial class Input<T> : InputBase<T>
|
||||
.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);
|
||||
.AddClass("micon-button-edge-margin-end", Adornment != Adornment.End && HideSpinButtons == true)
|
||||
.AddClass(ClearButtonClass)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -290,7 +347,7 @@ public partial class Input<T> : InputBase<T>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? HelperContainerClass { get; set; }
|
||||
protected CssBuilder CompiledHelperContainerClassList
|
||||
protected string HelperContainerClassList
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -298,7 +355,8 @@ public partial class Input<T> : InputBase<T>
|
||||
.AddClass($"px-1", Variant == Variant.Filled)
|
||||
.AddClass($"px-2", Variant == Variant.Outlined)
|
||||
.AddClass($"px-1", Variant == Variant.Text)
|
||||
.AddClass(HelperContainerClass);
|
||||
.AddClass(HelperContainerClass)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +372,6 @@ public partial class Input<T> : InputBase<T>
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Content placeholders
|
||||
|
||||
/// <summary>
|
||||
@ -336,6 +393,9 @@ public partial class Input<T> : InputBase<T>
|
||||
|
||||
private double _textChangeInterval;
|
||||
|
||||
[Parameter]
|
||||
public int Lines { get; set; } = 1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Interval to be awaited in MILLISECONDS before changing the Text value
|
||||
@ -423,7 +483,6 @@ public partial class Input<T> : InputBase<T>
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Lifecycle events
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
@ -460,5 +519,4 @@ public partial class Input<T> : InputBase<T>
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
{
|
||||
@if (AdornmentClick.HasDelegate)
|
||||
{
|
||||
<IconButton Icon="@Icon" Clicked="@AdornmentClick" Edge="@Edge" Size="@Size" Color="@Color" aria-label="@(!string.IsNullOrEmpty(AriaLabel) ? AriaLabel : "Icon Button")" tabindex="-1" />
|
||||
<GlyphButton Glyph="@Icon" Clicked="@AdornmentClick" Edge="@Edge" Size="@Size" Color="@Color" aria-label="@(!string.IsNullOrEmpty(AriaLabel) ? AriaLabel : "Icon Button")" tabindex="-1" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<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" />
|
||||
<Icon Class="range-input-separator mud-flip-x-rtl" Glyph="@SeparatorIcon" Color="@ThemeColor.Default" />
|
||||
<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" />
|
||||
|
||||
|
@ -6,6 +6,45 @@ namespace Connected.Components;
|
||||
|
||||
public partial class InputControl : UIComponent
|
||||
{
|
||||
#region Content
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should be the Input
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment InputContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ErrorText that will be displayed if Error true
|
||||
/// </summary>
|
||||
[Parameter] public string ErrorText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HelperText will be displayed below the text field.
|
||||
/// </summary>
|
||||
[Parameter] public string HelperText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current character counter, displayed below the text field.
|
||||
/// </summary>
|
||||
[Parameter] public string CounterText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If string has value the label text will be displayed in the input, and scaled down at the top if the input has value.
|
||||
/// </summary>
|
||||
[Parameter] public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If string has value the label "for" attribute will be added.
|
||||
/// </summary>
|
||||
[Parameter] public string ForId { get; set; } = string.Empty;
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("input-control")
|
||||
.AddClass("input-required", when: () => Required)
|
||||
@ -27,64 +66,16 @@ public partial class InputControl : UIComponent
|
||||
.AddClass("input-error", Error)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should be the Input
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment InputContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Will adjust vertical spacing.
|
||||
/// </summary>
|
||||
[Parameter] public Margin Margin { get; set; } = Margin.None;
|
||||
|
||||
/// <summary>
|
||||
/// If true, will apply mud-input-required class to the output div
|
||||
/// </summary>
|
||||
[Parameter] public bool Required { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the label will be displayed in an error state.
|
||||
/// </summary>
|
||||
[Parameter] public bool Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ErrorText that will be displayed if Error true
|
||||
/// </summary>
|
||||
[Parameter] public string ErrorText { get; set; }
|
||||
/// <summary>
|
||||
/// The ErrorId that will be used by aria-describedby if Error true
|
||||
/// </summary>
|
||||
[Parameter] public string ErrorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HelperText will be displayed below the text field.
|
||||
/// </summary>
|
||||
[Parameter] public string HelperText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the helper text will only be visible on focus.
|
||||
/// </summary>
|
||||
[Parameter] public bool HelperTextOnFocus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current character counter, displayed below the text field.
|
||||
/// </summary>
|
||||
[Parameter] public string CounterText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the input will take up the full width of its container.
|
||||
/// </summary>
|
||||
[Parameter] public bool FullWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If string has value the label text will be displayed in the input, and scaled down at the top if the input has value.
|
||||
/// </summary>
|
||||
[Parameter] public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Variant can be Text, Filled or Outlined.
|
||||
@ -95,9 +86,29 @@ public partial class InputControl : UIComponent
|
||||
/// If true, the input element will be disabled.
|
||||
/// </summary>
|
||||
[Parameter] public bool Disabled { get; set; }
|
||||
#endregion
|
||||
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, the label will be displayed in an error state.
|
||||
/// </summary>
|
||||
[Parameter] public bool Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If string has value the label "for" attribute will be added.
|
||||
/// If true, will apply mud-input-required class to the output div
|
||||
/// </summary>
|
||||
[Parameter] public string ForId { get; set; } = string.Empty;
|
||||
[Parameter] public bool Required { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the helper text will only be visible on focus.
|
||||
/// </summary>
|
||||
[Parameter] public bool HelperTextOnFocus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ErrorId that will be used by aria-describedby if Error true
|
||||
/// </summary>
|
||||
[Parameter] public string ErrorId { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Layout : DrawerContainer
|
||||
{
|
||||
#region Styling
|
||||
protected override CssBuilder CompiledClassList
|
||||
{
|
||||
get
|
||||
@ -22,8 +23,14 @@ public partial class Layout : DrawerContainer
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
public Layout()
|
||||
{
|
||||
Fixed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -8,6 +8,45 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Link : UIComponent
|
||||
{
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Link click event.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<MouseEventArgs> OnClick { get; set; }
|
||||
|
||||
protected async Task OnClickHandler(MouseEventArgs ev)
|
||||
{
|
||||
if (Disabled) return;
|
||||
await OnClick.InvokeAsync(ev);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
private Dictionary<string, object> Attributes
|
||||
{
|
||||
get => Disabled ? CustomAttributes : new Dictionary<string, object>(CustomAttributes)
|
||||
{
|
||||
{ "href", Href },
|
||||
{ "target", Target }
|
||||
};
|
||||
}
|
||||
/// <summary>
|
||||
/// The URL, which is the actual link.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public string Href { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The target attribute specifies where to open the link, if Link is specified. Possible values: _blank | _self | _parent | _top | <i>framename</i>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public string Target { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("typography mud-link")
|
||||
.AddClass($"{Color.ToDescription()}-text")
|
||||
@ -20,14 +59,12 @@ public partial class Link : UIComponent
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
private Dictionary<string, object> Attributes
|
||||
{
|
||||
get => Disabled ? CustomAttributes : new Dictionary<string, object>(CustomAttributes)
|
||||
{
|
||||
{ "href", Href },
|
||||
{ "target", Target }
|
||||
};
|
||||
}
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the component. It supports the theme colors.
|
||||
@ -50,42 +87,13 @@ public partial class Link : UIComponent
|
||||
[Category(CategoryTypes.Link.Appearance)]
|
||||
public Underline Underline { get; set; } = Underline.Hover;
|
||||
|
||||
/// <summary>
|
||||
/// The URL, which is the actual link.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public string Href { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The target attribute specifies where to open the link, if Link is specified. Possible values: _blank | _self | _parent | _top | <i>framename</i>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public string Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Link click event.
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<MouseEventArgs> OnClick { get; set; }
|
||||
|
||||
protected async Task OnClickHandler(MouseEventArgs ev)
|
||||
{
|
||||
if (Disabled) return;
|
||||
await OnClick.InvokeAsync(ev);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the navlink will be disabled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Link.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -6,131 +6,30 @@ namespace Connected.Components;
|
||||
|
||||
public partial class List : UIComponent, IDisposable
|
||||
{
|
||||
protected string Classname =>
|
||||
new CssBuilder("list")
|
||||
.AddClass("list-padding", !DisablePadding)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
#region Variables
|
||||
[CascadingParameter] protected List ParentList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the selected List Item.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public ThemeColor Color { get; set; } = ThemeColor.Primary;
|
||||
private HashSet<ListItem> _items = new();
|
||||
private HashSet<List> _childLists = new();
|
||||
private ListItem _selectedItem;
|
||||
private object _selectedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
internal bool CanSelect { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set true to make the list items clickable. This is also the precondition for list selection to work.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public bool Clickable { get; set; }
|
||||
internal event Action ParametersChanged;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// If true, vertical padding will be removed from the list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisablePadding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, compact vertical padding will be applied to all list items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed on all list items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, will disable the list item if it has onclick.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current selected list item.
|
||||
/// Note: make the list Clickable for item selection to work.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public ListItem SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set
|
||||
{
|
||||
if (_selectedItem == value)
|
||||
return;
|
||||
SetSelectedValue(_selectedItem?.Value, force: true);
|
||||
}
|
||||
}
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the selection changed
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<ListItem> SelectedItemChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current selected value.
|
||||
/// Note: make the list Clickable for item selection to work.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public object SelectedValue
|
||||
{
|
||||
get => _selectedValue;
|
||||
set
|
||||
{
|
||||
SetSelectedValue(value, force: true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the selection changed
|
||||
/// </summary>
|
||||
[Parameter] public EventCallback<object> SelectedValueChanged { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (ParentList != null)
|
||||
{
|
||||
ParentList.Register(this);
|
||||
CanSelect = ParentList.CanSelect;
|
||||
}
|
||||
else
|
||||
{
|
||||
CanSelect = SelectedItemChanged.HasDelegate || SelectedValueChanged.HasDelegate || SelectedValue != null;
|
||||
}
|
||||
}
|
||||
|
||||
internal event Action ParametersChanged;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
base.OnParametersSet();
|
||||
ParametersChanged?.Invoke();
|
||||
}
|
||||
|
||||
private HashSet<ListItem> _items = new();
|
||||
private HashSet<List> _childLists = new();
|
||||
private ListItem _selectedItem;
|
||||
private object _selectedValue;
|
||||
|
||||
internal void Register(ListItem item)
|
||||
{
|
||||
_items.Add(item);
|
||||
@ -182,13 +81,129 @@ public partial class List : UIComponent, IDisposable
|
||||
SelectedItemChanged.InvokeAsync(_selectedItem).AndForget();
|
||||
ParentList?.SetSelectedValue(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
internal bool CanSelect { get; private set; }
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current selected list item.
|
||||
/// Note: make the list Clickable for item selection to work.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public ListItem SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set
|
||||
{
|
||||
if (_selectedItem == value)
|
||||
return;
|
||||
SetSelectedValue(_selectedItem?.Value, force: true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current selected value.
|
||||
/// Note: make the list Clickable for item selection to work.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public object SelectedValue
|
||||
{
|
||||
get => _selectedValue;
|
||||
set
|
||||
{
|
||||
SetSelectedValue(value, force: true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("list")
|
||||
.AddClass("list-padding", !DisablePadding)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// The color of the selected List Item.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public ThemeColor Color { get; set; } = ThemeColor.Primary;
|
||||
|
||||
/// <summary>
|
||||
/// If true, vertical padding will be removed from the list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisablePadding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, compact vertical padding will be applied to all list items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed on all list items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, will disable the list item if it has onclick.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set true to make the list items clickable. This is also the precondition for list selection to work.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public bool Clickable { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (ParentList != null)
|
||||
{
|
||||
ParentList.Register(this);
|
||||
CanSelect = ParentList.CanSelect;
|
||||
}
|
||||
else
|
||||
{
|
||||
CanSelect = SelectedItemChanged.HasDelegate || SelectedValueChanged.HasDelegate || SelectedValue != null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
base.OnParametersSet();
|
||||
ParametersChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ParametersChanged = null;
|
||||
ParentList?.Unregister(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,14 +6,14 @@
|
||||
{
|
||||
<div class="list-item-avatar">
|
||||
<Avatar Class="@AvatarClass">
|
||||
<Icon Icon="@Avatar" Color="@IconColor" Size="@IconSize" />
|
||||
<Icon Glyph="@Avatar" Color="@IconColor" Size="@IconSize" />
|
||||
</Avatar>
|
||||
</div>
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(Icon))
|
||||
{
|
||||
<div class="list-item-icon">
|
||||
<Icon Icon="@Icon" Color="@IconColor" Size="@IconSize" />
|
||||
<Icon Glyph="@Icon" Color="@IconColor" Size="@IconSize" />
|
||||
</div>
|
||||
}
|
||||
<div class="list-item-text @(Inset? "list-item-text-inset" : "")">
|
||||
@ -30,7 +30,7 @@
|
||||
</div>
|
||||
@if (NestedList != null)
|
||||
{
|
||||
<Icon Icon="@($"{(_expanded ? ExpandLessIcon : ExpandMoreIcon)}")" Size="@IconSize" Color="@AdornmentColor" />
|
||||
<Icon Glyph="@($"{(_expanded ? ExpandLessIcon : ExpandMoreIcon)}")" Size="@IconSize" Color="@AdornmentColor" />
|
||||
}
|
||||
</div>
|
||||
@if (NestedList != null)
|
||||
|
@ -9,196 +9,23 @@ namespace Connected.Components;
|
||||
|
||||
public partial class ListItem : UIComponent, IDisposable
|
||||
{
|
||||
protected string Classname =>
|
||||
new CssBuilder("list-item")
|
||||
.AddClass("list-item-dense", (Dense ?? List?.Dense) ?? false)
|
||||
.AddClass("list-item-gutters", !DisableGutters && !(List?.DisableGutters == true))
|
||||
.AddClass("list-item-clickable", List?.Clickable)
|
||||
.AddClass("ripple", List?.Clickable == true && !DisableRipple && !Disabled)
|
||||
.AddClass($"selected-item mud-{List?.Color.ToDescription()}-text mud-{List?.Color.ToDescription()}-hover", _selected && !Disabled)
|
||||
.AddClass("list-item-disabled", Disabled)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
#region Variables
|
||||
[Inject] protected NavigationManager UriHelper { get; set; }
|
||||
|
||||
[CascadingParameter] protected List List { get; set; }
|
||||
|
||||
private bool _onClickHandlerPreventDefault = false;
|
||||
|
||||
/// <summary>
|
||||
/// The text to display
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Text { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public object Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Avatar to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Link to a URL when clicked.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public string Href { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, force browser to redirect outside component router-space.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public bool ForceLoad { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Avatar CSS Class to apply if Avatar is set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public string AvatarClass { get; set; }
|
||||
|
||||
private bool _disabled;
|
||||
/// <summary>
|
||||
/// If true, will disable the list item if it has onclick.
|
||||
/// The value can be overridden by the parent list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public bool Disabled
|
||||
{
|
||||
get => _disabled || (List?.Disabled ?? false);
|
||||
set => _disabled = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, disables ripple effect.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableRipple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Glyph Size.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public Size IconSize { get; set; } = Size.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the adornment if used. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public ThemeColor AdornmentColor { get; set; } = ThemeColor.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Custom expand less icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public string ExpandLessIcon { get; set; } = Icons.Material.Filled.ExpandLess;
|
||||
|
||||
/// <summary>
|
||||
/// Custom expand more icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public string ExpandMoreIcon { get; set; } = Icons.Material.Filled.ExpandMore;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the List Subheader will be indented.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool Inset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, compact vertical padding will be used.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool? Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expand or collapse nested list. Two-way bindable. Note: if you directly set this to
|
||||
/// true or false (instead of using two-way binding) it will force the nested list's expansion state.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public bool Expanded
|
||||
{
|
||||
get => _expanded;
|
||||
set
|
||||
{
|
||||
if (_expanded == value)
|
||||
return;
|
||||
_expanded = value;
|
||||
_ = ExpandedChanged.InvokeAsync(value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _expanded;
|
||||
|
||||
private Typo _textTypo;
|
||||
|
||||
private bool _selected;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
[Parameter]
|
||||
public EventCallback<bool> ExpandedChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, expands the nested list on first display
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public bool InitiallyExpanded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Command parameter.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public object CommandParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Command executed when the user clicks on an element.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public ICommand Command { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Display content of this list item. If set, this overrides Text
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public bool OnClickHandlerPreventDefault
|
||||
@ -207,13 +34,6 @@ public partial class ListItem : UIComponent, IDisposable
|
||||
set => _onClickHandlerPreventDefault = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add child list items here to create a nested list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment NestedList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List click event.
|
||||
/// </summary>
|
||||
@ -252,18 +72,6 @@ public partial class ListItem : UIComponent, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_expanded = InitiallyExpanded;
|
||||
if (List != null)
|
||||
{
|
||||
List.Register(this);
|
||||
OnListParametersChanged();
|
||||
List.ParametersChanged += OnListParametersChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private Typo _textTypo;
|
||||
private void OnListParametersChanged()
|
||||
{
|
||||
if ((Dense ?? List?.Dense) ?? false)
|
||||
@ -277,8 +85,6 @@ public partial class ListItem : UIComponent, IDisposable
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private bool _selected;
|
||||
|
||||
internal void SetSelected(bool selected)
|
||||
{
|
||||
if (Disabled)
|
||||
@ -289,6 +95,217 @@ public partial class ListItem : UIComponent, IDisposable
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// The text to display
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Text { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Selecting)]
|
||||
public object Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Avatar to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom expand less icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public string ExpandLessIcon { get; set; } = Icons.Material.Filled.ExpandLess;
|
||||
|
||||
/// <summary>
|
||||
/// Custom expand more icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public string ExpandMoreIcon { get; set; } = Icons.Material.Filled.ExpandMore;
|
||||
|
||||
/// <summary>
|
||||
/// Display content of this list item. If set, this overrides Text
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add child list items here to create a nested list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment NestedList { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("list-item")
|
||||
.AddClass("list-item-dense", (Dense ?? List?.Dense) ?? false)
|
||||
.AddClass("list-item-gutters", !DisableGutters && !(List?.DisableGutters == true))
|
||||
.AddClass("list-item-clickable", List?.Clickable)
|
||||
.AddClass("ripple", List?.Clickable == true && !DisableRipple && !Disabled)
|
||||
.AddClass($"selected-item mud-{List?.Color.ToDescription()}-text mud-{List?.Color.ToDescription()}-hover", _selected && !Disabled)
|
||||
.AddClass("list-item-disabled", Disabled)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// Link to a URL when clicked.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public string Href { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Avatar CSS Class to apply if Avatar is set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public string AvatarClass { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, will disable the list item if it has onclick.
|
||||
/// The value can be overridden by the parent list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public bool Disabled
|
||||
{
|
||||
get => _disabled || (List?.Disabled ?? false);
|
||||
set => _disabled = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, disables ripple effect.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableRipple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Glyph Size.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public Size IconSize { get; set; } = Size.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the adornment if used. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public ThemeColor AdornmentColor { get; set; } = ThemeColor.Default;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the List Subheader will be indented.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool Inset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, compact vertical padding will be used.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool? Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the left and right padding is removed.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, force browser to redirect outside component router-space.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public bool ForceLoad { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expand or collapse nested list. Two-way bindable. Note: if you directly set this to
|
||||
/// true or false (instead of using two-way binding) it will force the nested list's expansion state.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public bool Expanded
|
||||
{
|
||||
get => _expanded;
|
||||
set
|
||||
{
|
||||
if (_expanded == value)
|
||||
return;
|
||||
_expanded = value;
|
||||
_ = ExpandedChanged.InvokeAsync(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, expands the nested list on first display
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Expanding)]
|
||||
public bool InitiallyExpanded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Command parameter.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public object CommandParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Command executed when the user clicks on an element.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.ClickAction)]
|
||||
public ICommand Command { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_expanded = InitiallyExpanded;
|
||||
if (List != null)
|
||||
{
|
||||
List.Register(this);
|
||||
OnListParametersChanged();
|
||||
List.ParametersChanged += OnListParametersChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
@ -301,4 +318,7 @@ public partial class ListItem : UIComponent, IDisposable
|
||||
catch (Exception) { /*ignore*/ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace Connected.Components;
|
||||
|
||||
public partial class ListSubheader : UIComponent
|
||||
{
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("list-subheader")
|
||||
.AddClass("list-subheader-gutters", !DisableGutters)
|
||||
@ -13,10 +14,6 @@ public partial class ListSubheader : UIComponent
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool DisableGutters { get; set; }
|
||||
@ -24,4 +21,13 @@ public partial class ListSubheader : UIComponent
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public bool Inset { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Components;
|
||||
namespace Connected.Components;
|
||||
public partial class MainContent
|
||||
{
|
||||
#region Styling
|
||||
private CssBuilder CompiledClassList
|
||||
{
|
||||
get
|
||||
@ -13,12 +14,16 @@ public partial class MainContent
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A space separated list of class names, added on top of the default class list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? ClassList { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -54,9 +54,9 @@
|
||||
|
||||
@if (_showClearable && !Disabled)
|
||||
{
|
||||
<IconButton Class="@ClearButtonClassname"
|
||||
<GlyphButton Class="@ClearButtonClassname"
|
||||
Color="@ThemeColor.Default"
|
||||
Icon="@ClearIcon"
|
||||
Glyph="@ClearIcon"
|
||||
Size="@Size.Small"
|
||||
Clicked="@HandleClearButton" />
|
||||
}
|
||||
|
@ -14,52 +14,7 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Mask : InputBase<string>, IDisposable
|
||||
{
|
||||
public Mask()
|
||||
{
|
||||
TextUpdateSuppression = false;
|
||||
}
|
||||
|
||||
protected string Classname =>
|
||||
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: () => !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(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string InputClassname =>
|
||||
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(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string AdornmentClassname =>
|
||||
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(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string ClearButtonClassname =>
|
||||
new CssBuilder()
|
||||
// .AddClass("me-n1", Adornment == Adornment.End && HideSpinButtons == false)
|
||||
.AddClass("icon-button-edge-end", Adornment == Adornment.End)
|
||||
// .AddClass("me-6", Adornment != Adornment.End && HideSpinButtons == false)
|
||||
.AddClass("icon-button-edge-margin-end", Adornment != Adornment.End)
|
||||
.Build();
|
||||
|
||||
|
||||
#region Variables
|
||||
private ElementReference _elementReference;
|
||||
private ElementReference _elementReference1;
|
||||
private IJsEvent _jsEvent;
|
||||
@ -74,40 +29,12 @@ public partial class Mask : InputBase<string>, IDisposable
|
||||
|
||||
private IMask _mask = new PatternMask("** **-** **");
|
||||
|
||||
/// <summary>
|
||||
/// ChildContent will only be displayed if InputType.Hidden and if its not null. Required for Select
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.General.Appearance)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provide a masking object. Built-in masks are PatternMask, MultiMask, RegexMask and BlockMask
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.General.Data)]
|
||||
public IMask MaskKind
|
||||
{
|
||||
get => _mask;
|
||||
set => SetMask(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of the input element. It should be a valid HTML5 input type.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.ListAppearance)]
|
||||
public InputType InputType { get; set; } = InputType.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Show clear button.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.ListBehavior)]
|
||||
public bool Clearable { get; set; } = false;
|
||||
|
||||
private bool _showClearable;
|
||||
|
||||
private bool _updating;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
private void UpdateClearable(object value)
|
||||
{
|
||||
var showClearable = Clearable && !string.IsNullOrWhiteSpace(Text);
|
||||
@ -121,67 +48,6 @@ public partial class Mask : InputBase<string>, IDisposable
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.ListAppearance)]
|
||||
public EventCallback<MouseEventArgs> OnClearButtonClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom clear icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.General.Appearance)]
|
||||
public string ClearIcon { get; set; } = Icons.Material.Filled.Clear;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Text != MaskKind.Text)
|
||||
await SetTextAsync(MaskKind.Text, updateValue: false);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
_jsEvent = _jsEventFactory.Create();
|
||||
|
||||
await _jsEvent.Connect(_elementId,
|
||||
new JsEventOptions
|
||||
{
|
||||
//EnableLogging = true,
|
||||
TargetClass = "input-slot",
|
||||
TagName = "INPUT"
|
||||
});
|
||||
_jsEvent.CaretPositionChanged += OnCaretPositionChanged;
|
||||
_jsEvent.Paste += OnPaste;
|
||||
_jsEvent.Select += OnSelect;
|
||||
|
||||
_keyInterceptor = _keyInterceptorFactory.Create();
|
||||
|
||||
await _keyInterceptor.Connect(_elementId, new KeyInterceptorOptions()
|
||||
{
|
||||
//EnableLogging = true,
|
||||
TargetClass = "input-slot",
|
||||
Keys =
|
||||
{
|
||||
new KeyOptions
|
||||
{
|
||||
Key = " ", PreventDown = "key+none"
|
||||
}, //prevent scrolling page, toggle open/close
|
||||
new KeyOptions { Key = "ArrowUp", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = "ArrowDown", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = "PageUp", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = "PageDown", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = @"/^.$/", PreventDown = "key+none|key+shift" },
|
||||
new KeyOptions { Key = "/./", SubscribeDown = true },
|
||||
new KeyOptions { Key = "Backspace", PreventDown = "key+none" },
|
||||
new KeyOptions { Key = "Delete", PreventDown = "key+none" },
|
||||
},
|
||||
});
|
||||
_keyInterceptor.KeyDown += HandleKeyDownInternally;
|
||||
}
|
||||
if (_isFocused && MaskKind.Selection == null)
|
||||
SetCaretPosition(MaskKind.CaretPos, _selection, render: false);
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
private async void HandleKeyDownInternally(KeyboardEventArgs args)
|
||||
{
|
||||
await HandleKeyDown(args);
|
||||
@ -224,8 +90,6 @@ public partial class Mask : InputBase<string>, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private bool _updating;
|
||||
|
||||
private async Task Update()
|
||||
{
|
||||
var caret = MaskKind.CaretPos;
|
||||
@ -417,6 +281,95 @@ public partial class Mask : InputBase<string>, IDisposable
|
||||
MaskKind.Delete();
|
||||
await Update();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
|
||||
/// <summary>
|
||||
/// Custom clear icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.General.Appearance)]
|
||||
public string ClearIcon { get; set; } = Icons.Material.Filled.Clear;
|
||||
|
||||
/// <summary>
|
||||
/// ChildContent will only be displayed if InputType.Hidden and if its not null. Required for Select
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.General.Appearance)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
|
||||
/// <summary>
|
||||
/// Provide a masking object. Built-in masks are PatternMask, MultiMask, RegexMask and BlockMask
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.General.Data)]
|
||||
public IMask MaskKind
|
||||
{
|
||||
get => _mask;
|
||||
set => SetMask(value);
|
||||
}
|
||||
protected string Classname =>
|
||||
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: () => !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(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string InputClassname =>
|
||||
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(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string AdornmentClassname =>
|
||||
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(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string ClearButtonClassname =>
|
||||
new CssBuilder()
|
||||
// .AddClass("me-n1", Adornment == Adornment.End && HideSpinButtons == false)
|
||||
.AddClass("icon-button-edge-end", Adornment == Adornment.End)
|
||||
// .AddClass("me-6", Adornment != Adornment.End && HideSpinButtons == false)
|
||||
.AddClass("icon-button-edge-margin-end", Adornment != Adornment.End)
|
||||
.Build();
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// Show clear button.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.ListBehavior)]
|
||||
public bool Clearable { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Type of the input element. It should be a valid HTML5 input type.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.FormComponent.ListAppearance)]
|
||||
public InputType InputType { get; set; } = InputType.Text;
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
@ -435,4 +388,63 @@ public partial class Mask : InputBase<string>, IDisposable
|
||||
_keyInterceptor?.Dispose();
|
||||
}
|
||||
}
|
||||
public Mask()
|
||||
{
|
||||
TextUpdateSuppression = false;
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Text != MaskKind.Text)
|
||||
await SetTextAsync(MaskKind.Text, updateValue: false);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
_jsEvent = _jsEventFactory.Create();
|
||||
|
||||
await _jsEvent.Connect(_elementId,
|
||||
new JsEventOptions
|
||||
{
|
||||
//EnableLogging = true,
|
||||
TargetClass = "input-slot",
|
||||
TagName = "INPUT"
|
||||
});
|
||||
_jsEvent.CaretPositionChanged += OnCaretPositionChanged;
|
||||
_jsEvent.Paste += OnPaste;
|
||||
_jsEvent.Select += OnSelect;
|
||||
|
||||
_keyInterceptor = _keyInterceptorFactory.Create();
|
||||
|
||||
await _keyInterceptor.Connect(_elementId, new KeyInterceptorOptions()
|
||||
{
|
||||
//EnableLogging = true,
|
||||
TargetClass = "input-slot",
|
||||
Keys =
|
||||
{
|
||||
new KeyOptions
|
||||
{
|
||||
Key = " ", PreventDown = "key+none"
|
||||
}, //prevent scrolling page, toggle open/close
|
||||
new KeyOptions { Key = "ArrowUp", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = "ArrowDown", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = "PageUp", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = "PageDown", PreventDown = "key+none" }, // prevent scrolling page
|
||||
new KeyOptions { Key = @"/^.$/", PreventDown = "key+none|key+shift" },
|
||||
new KeyOptions { Key = "/./", SubscribeDown = true },
|
||||
new KeyOptions { Key = "Backspace", PreventDown = "key+none" },
|
||||
new KeyOptions { Key = "Delete", PreventDown = "key+none" },
|
||||
},
|
||||
});
|
||||
_keyInterceptor.KeyDown += HandleKeyDownInternally;
|
||||
}
|
||||
if (_isFocused && MaskKind.Selection == null)
|
||||
SetCaretPosition(MaskKind.CaretPos, _selection, render: false);
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<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)" />
|
||||
<GlyphButton Variant="@Variant" Glyph="@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">
|
||||
|
@ -9,136 +9,14 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Menu : UIComponent, IActivatable
|
||||
{
|
||||
protected string Classname =>
|
||||
new CssBuilder("menu")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string ActivatorClassname =>
|
||||
new CssBuilder("menu-activator")
|
||||
.AddClass("disabled", Disabled)
|
||||
.Build();
|
||||
|
||||
#region Variables
|
||||
private bool _isOpen;
|
||||
private bool _isMouseOver = false;
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User class names for the list, separated by space
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public string ListClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User class names for the popover, separated by space
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public string PopoverClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set will turn the button into a MudIconButton.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||
|
||||
/// <summary>
|
||||
/// Glyph placed before the text if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string StartIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph placed after the text if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string EndIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the button. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public ThemeColor Color { get; set; } = ThemeColor.Default;
|
||||
|
||||
/// <summary>
|
||||
/// The button Size of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public Size Size { get; set; } = Size.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// The button variant to use.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public Variant Variant { get; set; } = Variant.Text;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, compact vertical padding will be applied to all menu items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the list menu will be same width as the parent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public bool FullWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the maxheight the menu can have when open.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public int? MaxHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, instead of positioning the menu at the left upper corner, position at the exact cursor location.
|
||||
/// This makes sense for larger activators
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupBehavior)]
|
||||
public bool PositionAtCursor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, instead of positioning the menu at the left upper corner, position at the exact cursor location.
|
||||
/// This makes sense for larger activators
|
||||
/// </summary>
|
||||
[Obsolete("Use PositionAtCursor instead.", true)]
|
||||
[Parameter]
|
||||
public bool PositionAtCurser
|
||||
{
|
||||
get => PositionAtCursor;
|
||||
set => PositionAtCursor = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place a MudButton, a MudIconButton or any other component capable of acting as an activator. This will
|
||||
/// override the standard button and all parameters which concern it.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public RenderFragment ActivatorContent { get; set; }
|
||||
public string PopoverStyle { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Specify the activation event when ActivatorContent is set
|
||||
/// </summary>
|
||||
@ -146,106 +24,6 @@ public partial class Menu : UIComponent, IActivatable
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public MouseEvent ActivationEvent { get; set; } = MouseEvent.LeftClick;
|
||||
|
||||
/// <summary>
|
||||
/// Set the anchor origin point to determen where the popover will open from.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public Origin AnchorOrigin { get; set; } = Origin.TopLeft;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the transform origin point for the popover.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public Origin TransformOrigin { get; set; } = Origin.TopLeft;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the direction the select menu will start from relative to its parent.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Use AnchorOrigin or TransformOrigin instead.", true)]
|
||||
[Parameter] public Direction Direction { get; set; } = Direction.Bottom;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the select menu will open either before or after the input depending on the direction.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Use AnchorOrigin or TransformOrigin instead.", true)]
|
||||
[Parameter] public bool OffsetY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the select menu will open either above or bellow the input depending on the direction.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Use AnchorOrigin or TransformOrigin instead.", true)]
|
||||
[Parameter] public bool OffsetX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true if you want to prevent page from scrolling when the menu is open
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public bool LockScroll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, menu will be disabled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, disables ripple effect.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public bool DisableRipple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, no drop-shadow will be used.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public bool DisableElevation { get; set; }
|
||||
|
||||
#region Obsolete members from previous MudButtonBase inherited structure
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Linking is not supported. MudMenu is not a MudBaseButton anymore.", true)]
|
||||
[Parameter] public string Link { get; set; }
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Linking is not supported. MudMenu is not a MudBaseButton anymore.", true)]
|
||||
[Parameter] public string Target { get; set; }
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("MudMenu is not a MudBaseButton anymore.", true)]
|
||||
[Parameter] public string HtmlTag { get; set; } = "button";
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("MudMenu is not a MudBaseButton anymore.", true)]
|
||||
[Parameter] public ButtonType ButtonType { get; set; }
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("MudMenu is not a MudBaseButton anymore.", true)]
|
||||
[Parameter] public ICommand Command { get; set; }
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("MudMenu is not a MudBaseButton anymore.", true)]
|
||||
[Parameter] public object CommandParameter { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Add menu items here
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupBehavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
public string PopoverStyle { get; set; }
|
||||
|
||||
public void CloseMenu()
|
||||
{
|
||||
_isOpen = false;
|
||||
@ -332,4 +110,203 @@ public partial class Menu : UIComponent, IActivatable
|
||||
CloseMenu();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set will turn the button into a MudIconButton.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph placed before the text if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string StartIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph placed after the text if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public string EndIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Place a MudButton, a MudIconButton or any other component capable of acting as an activator. This will
|
||||
/// override the standard button and all parameters which concern it.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public RenderFragment ActivatorContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Add menu items here
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupBehavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
|
||||
/// <summary>
|
||||
/// If true, the select menu will open either before or after the input depending on the direction.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Use AnchorOrigin or TransformOrigin instead.", true)]
|
||||
[Parameter] public bool OffsetY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the select menu will open either above or bellow the input depending on the direction.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Use AnchorOrigin or TransformOrigin instead.", true)]
|
||||
[Parameter] public bool OffsetX { get; set; }
|
||||
protected string Classname =>
|
||||
new CssBuilder("menu")
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string ActivatorClassname =>
|
||||
new CssBuilder("menu-activator")
|
||||
.AddClass("disabled", Disabled)
|
||||
.Build();
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// User class names for the list, separated by space
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public string ListClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User class names for the popover, separated by space
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public string PopoverClass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the button. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public ThemeColor Color { get; set; } = ThemeColor.Default;
|
||||
|
||||
/// <summary>
|
||||
/// The button Size of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public Size Size { get; set; } = Size.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// The button variant to use.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public Variant Variant { get; set; } = Variant.Text;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, compact vertical padding will be applied to all menu items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public bool Dense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the list menu will be same width as the parent.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public bool FullWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the maxheight the menu can have when open.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public int? MaxHeight { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// Set to true if you want to prevent page from scrolling when the menu is open
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public bool LockScroll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, menu will be disabled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Behavior)]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, disables ripple effect.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public bool DisableRipple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, no drop-shadow will be used.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.Appearance)]
|
||||
public bool DisableElevation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, instead of positioning the menu at the left upper corner, position at the exact cursor location.
|
||||
/// This makes sense for larger activators
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupBehavior)]
|
||||
public bool PositionAtCursor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the anchor origin point to determen where the popover will open from.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public Origin AnchorOrigin { get; set; } = Origin.TopLeft;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the transform origin point for the popover.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
||||
public Origin TransformOrigin { get; set; } = Origin.TopLeft;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the direction the select menu will start from relative to its parent.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
[Obsolete("Use AnchorOrigin or TransformOrigin instead.", true)]
|
||||
[Parameter] public Direction Direction { get; set; } = Direction.Bottom;
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -7,53 +7,15 @@ namespace Connected.Components;
|
||||
|
||||
public partial class MenuItem : UIComponent
|
||||
{
|
||||
#region Variables
|
||||
[CascadingParameter] public Menu Menu { get; set; }
|
||||
|
||||
[Parameter][Category(CategoryTypes.Menu.Behavior)] public RenderFragment ChildContent { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.Behavior)] public bool Disabled { get; set; }
|
||||
|
||||
[Inject] public NavigationManager UriHelper { get; set; }
|
||||
[Inject] public IJsApiService JsApiService { get; set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// If set to a URL, clicking the button will open the referenced document. Use Target to specify where (Obsolete replaced by Href)
|
||||
/// </summary>
|
||||
[Obsolete("Use Href Instead.", false)]
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.ClickAction)]
|
||||
public string Link { get => Href; set => Href = value; }
|
||||
|
||||
/// <summary>
|
||||
/// If set to a URL, clicking the button will open the referenced document. Use Target to specify where
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.ClickAction)]
|
||||
public string Href { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to be used for this menu entry
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||
/// <summary>
|
||||
/// The Glyph Size.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public Size IconSize { get; set; } = Size.Medium;
|
||||
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public string Target { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public bool ForceLoad { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public ICommand Command { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public object CommandParameter { get; set; }
|
||||
|
||||
#region Events
|
||||
[Parameter] public EventCallback<MouseEventArgs> OnClick { get; set; }
|
||||
[Parameter] public EventCallback<TouchEventArgs> OnTouch { get; set; }
|
||||
|
||||
@ -102,4 +64,53 @@ public partial class MenuItem : UIComponent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// If set to a URL, clicking the button will open the referenced document. Use Target to specify where (Obsolete replaced by Href)
|
||||
/// </summary>
|
||||
[Obsolete("Use Href Instead.", false)]
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.ClickAction)]
|
||||
public string Link { get => Href; set => Href = value; }
|
||||
|
||||
/// <summary>
|
||||
/// If set to a URL, clicking the button will open the referenced document. Use Target to specify where
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Menu.ClickAction)]
|
||||
public string Href { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to be used for this menu entry
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||
/// <summary>
|
||||
/// The Glyph Size.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.List.Appearance)]
|
||||
public Size IconSize { get; set; } = Size.Medium;
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public string Target { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public bool ForceLoad { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public ICommand Command { get; set; }
|
||||
[Parameter][Category(CategoryTypes.Menu.ClickAction)] public object CommandParameter { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -6,9 +6,106 @@ namespace Connected.Components;
|
||||
|
||||
public partial class MessageBox : UIComponent
|
||||
{
|
||||
#region Variables
|
||||
[Inject] private IDialogService DialogService { get; set; }
|
||||
|
||||
[CascadingParameter] private DialogInstance DialogInstance { get; set; }
|
||||
private bool _isVisible;
|
||||
private bool IsInline => DialogInstance == null;
|
||||
private IDialogReference _reference;
|
||||
private ActivatableCallback _yesCallback, _cancelCallback, _noCallback;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Fired when the yes button is clicked
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnYes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the no button is clicked
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the cancel button is clicked or the msg box was closed via the X
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnCancel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the inline dialog's display status changes.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> IsVisibleChanged { get; set; }
|
||||
|
||||
public async Task<bool?> Show(DialogOptions options = null)
|
||||
{
|
||||
if (DialogService == null)
|
||||
return null;
|
||||
var parameters = new DialogParameters()
|
||||
{
|
||||
[nameof(Title)] = Title,
|
||||
[nameof(TitleContent)] = TitleContent,
|
||||
[nameof(Message)] = Message,
|
||||
[nameof(MarkupMessage)] = MarkupMessage,
|
||||
[nameof(MessageContent)] = MessageContent,
|
||||
[nameof(CancelText)] = CancelText,
|
||||
[nameof(CancelButton)] = CancelButton,
|
||||
[nameof(NoText)] = NoText,
|
||||
[nameof(NoButton)] = NoButton,
|
||||
[nameof(YesText)] = YesText,
|
||||
[nameof(YesButton)] = YesButton,
|
||||
};
|
||||
_reference = await DialogService.ShowAsync<MessageBox>(parameters: parameters, options: options, title: Title);
|
||||
var result = await _reference.Result;
|
||||
if (result.Cancelled || result.Data is not bool data)
|
||||
return null;
|
||||
return data;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_reference?.Close();
|
||||
}
|
||||
|
||||
private void OnYesActivated(object arg1, MouseEventArgs arg2) => OnYesClicked();
|
||||
|
||||
private void OnNoActivated(object arg1, MouseEventArgs arg2) => OnNoClicked();
|
||||
|
||||
private void OnCancelActivated(object arg1, MouseEventArgs arg2) => OnCancelClicked();
|
||||
|
||||
private void OnYesClicked() => DialogInstance.Close(DialogResult.Ok(true));
|
||||
|
||||
private void OnNoClicked() => DialogInstance.Close(DialogResult.Ok(false));
|
||||
|
||||
private void OnCancelClicked() => DialogInstance.Close(DialogResult.Cancel());
|
||||
|
||||
private void HandleKeyDown(KeyboardEventArgs args)
|
||||
{
|
||||
if (args.Key == "Escape")
|
||||
{
|
||||
OnCancelClicked();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Define the message box title as a renderfragment (overrides GlyphTitle)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public RenderFragment TitleContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Define the message box body as a renderfragment (overrides Message)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public RenderFragment MessageContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The message box title. If null or empty, title will be hidden
|
||||
@ -17,13 +114,6 @@ public partial class MessageBox : UIComponent
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Define the message box title as a renderfragment (overrides GlyphTitle)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public RenderFragment TitleContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The message box message as string.
|
||||
/// </summary>
|
||||
@ -38,14 +128,6 @@ public partial class MessageBox : UIComponent
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public MarkupString MarkupMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Define the message box body as a renderfragment (overrides Message)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public RenderFragment MessageContent { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Text of the cancel button. Leave null to hide the button.
|
||||
/// </summary>
|
||||
@ -90,25 +172,9 @@ public partial class MessageBox : UIComponent
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.MessageBox.Behavior)]
|
||||
public RenderFragment YesButton { get; set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the yes button is clicked
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnYes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the no button is clicked
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the cancel button is clicked or the msg box was closed via the X
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> OnCancel { get; set; }
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// Bind this two-way to show and close an inlined message box. Has no effect on opened msg boxes
|
||||
/// </summary>
|
||||
@ -133,50 +199,9 @@ public partial class MessageBox : UIComponent
|
||||
IsVisibleChanged.InvokeAsync(value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool _isVisible;
|
||||
private bool IsInline => DialogInstance == null;
|
||||
|
||||
private IDialogReference _reference;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the inline dialog's display status changes.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> IsVisibleChanged { get; set; }
|
||||
|
||||
public async Task<bool?> Show(DialogOptions options = null)
|
||||
{
|
||||
if (DialogService == null)
|
||||
return null;
|
||||
var parameters = new DialogParameters()
|
||||
{
|
||||
[nameof(Title)] = Title,
|
||||
[nameof(TitleContent)] = TitleContent,
|
||||
[nameof(Message)] = Message,
|
||||
[nameof(MarkupMessage)] = MarkupMessage,
|
||||
[nameof(MessageContent)] = MessageContent,
|
||||
[nameof(CancelText)] = CancelText,
|
||||
[nameof(CancelButton)] = CancelButton,
|
||||
[nameof(NoText)] = NoText,
|
||||
[nameof(NoButton)] = NoButton,
|
||||
[nameof(YesText)] = YesText,
|
||||
[nameof(YesButton)] = YesButton,
|
||||
};
|
||||
_reference = await DialogService.ShowAsync<MessageBox>(parameters: parameters, options: options, title: Title);
|
||||
var result = await _reference.Result;
|
||||
if (result.Cancelled || result.Data is not bool data)
|
||||
return null;
|
||||
return data;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_reference?.Close();
|
||||
}
|
||||
|
||||
private ActivatableCallback _yesCallback, _cancelCallback, _noCallback;
|
||||
|
||||
#region Lifecycle
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
@ -187,25 +212,6 @@ public partial class MessageBox : UIComponent
|
||||
if (CancelButton != null)
|
||||
_cancelCallback = new ActivatableCallback() { ActivateCallback = OnCancelActivated };
|
||||
}
|
||||
|
||||
private void OnYesActivated(object arg1, MouseEventArgs arg2) => OnYesClicked();
|
||||
|
||||
private void OnNoActivated(object arg1, MouseEventArgs arg2) => OnNoClicked();
|
||||
|
||||
private void OnCancelActivated(object arg1, MouseEventArgs arg2) => OnCancelClicked();
|
||||
|
||||
private void OnYesClicked() => DialogInstance.Close(DialogResult.Ok(true));
|
||||
|
||||
private void OnNoClicked() => DialogInstance.Close(DialogResult.Ok(false));
|
||||
|
||||
private void OnCancelClicked() => DialogInstance.Close(DialogResult.Cancel());
|
||||
|
||||
private void HandleKeyDown(KeyboardEventArgs args)
|
||||
{
|
||||
if (args.Key == "Escape")
|
||||
{
|
||||
OnCancelClicked();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -5,14 +5,14 @@
|
||||
<button @onclick="ExpandedToggle" tabindex="0" class="@ButtonClassname">
|
||||
@if (!String.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<Icon Icon="@Icon" Color="@IconColor" Class="@IconClassname" />
|
||||
<Icon Glyph="@Icon" Color="@IconColor" Class="@IconClassname" />
|
||||
}
|
||||
<div Class="nav-link-text">
|
||||
@Title
|
||||
</div>
|
||||
@if (!HideExpandIcon)
|
||||
{
|
||||
<Icon Icon="@ExpandIcon" class="@ExpandIconClassname" />
|
||||
<Icon Glyph="@ExpandIcon" class="@ExpandIconClassname" />
|
||||
}
|
||||
</button>
|
||||
<Collapse Expanded="@Expanded" MaxHeight="@MaxHeight" Class="navgroup-collapse">
|
||||
|
@ -6,6 +6,47 @@ namespace Connected.Components;
|
||||
|
||||
public partial class NavGroup : UIComponent
|
||||
{
|
||||
#region Variables
|
||||
private bool _expanded;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
protected void ExpandedToggle()
|
||||
{
|
||||
_expanded = !Expanded;
|
||||
ExpandedChanged.InvokeAsync(_expanded);
|
||||
}
|
||||
[Parameter] public EventCallback<bool> ExpandedChanged { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors, default value uses the themes drawer icon color.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Default;
|
||||
|
||||
/// <summary>
|
||||
/// If set, overrides the default expand icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public string ExpandIcon { get; set; } = @Icons.Filled.ArrowDropDown;
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("nav-group")
|
||||
.AddClass(AdditionalClassList)
|
||||
@ -29,24 +70,26 @@ public partial class NavGroup : UIComponent
|
||||
.AddClass($"transform-disabled", Expanded && Disabled)
|
||||
.Build();
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors, default value uses the themes drawer icon color.
|
||||
/// If true, hides expand-icon at the end of the NavGroup.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Default;
|
||||
public bool HideExpandIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly sets the height for the Collapse element to override the css default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public int? MaxHeight { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true, the button will be disabled.
|
||||
/// </summary>
|
||||
@ -61,7 +104,7 @@ public partial class NavGroup : UIComponent
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public bool DisableRipple { get; set; }
|
||||
|
||||
private bool _expanded;
|
||||
|
||||
/// <summary>
|
||||
/// If true, expands the nav group, otherwise collapse it.
|
||||
/// Two-way bindable
|
||||
@ -80,37 +123,6 @@ public partial class NavGroup : UIComponent
|
||||
ExpandedChanged.InvokeAsync(_expanded);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
[Parameter] public EventCallback<bool> ExpandedChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, hides expand-icon at the end of the NavGroup.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public bool HideExpandIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly sets the height for the Collapse element to override the css default.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public int? MaxHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, overrides the default expand icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public string ExpandIcon { get; set; } = @Icons.Filled.ArrowDropDown;
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
protected void ExpandedToggle()
|
||||
{
|
||||
_expanded = !Expanded;
|
||||
ExpandedChanged.InvokeAsync(_expanded);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
ActiveClass="@ActiveClass">
|
||||
@if (!string.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<Icon Icon="@Icon" Color="@IconColor" Class="@IconClassname"/>
|
||||
<Icon Glyph="@Icon" Color="@IconColor" Class="@IconClassname" />
|
||||
}
|
||||
<div class="nav-link-text">
|
||||
@ChildContent
|
||||
@ -26,7 +26,7 @@
|
||||
ActiveClass="@ActiveClass">
|
||||
@if (!string.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<Icon Icon="@Icon" Color="@IconColor" Class="@IconClassname" />
|
||||
<Icon Glyph="@Icon" Color="@IconColor" Class="@IconClassname" />
|
||||
}
|
||||
<div Class="nav-link-text">
|
||||
@ChildContent
|
||||
|
@ -7,6 +7,34 @@ namespace Connected.Components;
|
||||
|
||||
public partial class NavLink : SelectItemBase
|
||||
{
|
||||
#region Events
|
||||
[CascadingParameter] INavigationEventReceiver NavigationEventReceiver { get; set; }
|
||||
|
||||
protected Task HandleNavigation()
|
||||
{
|
||||
if (!Disabled && NavigationEventReceiver != null)
|
||||
{
|
||||
return NavigationEventReceiver.OnNavigation();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Glyph to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.ClickAction)]
|
||||
public string Target { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("nav-item")
|
||||
.AddClass($"ripple", !DisableRipple && !Disabled)
|
||||
@ -23,6 +51,26 @@ public partial class NavLink : SelectItemBase
|
||||
.AddClass($"nav-link-icon-default", IconColor == ThemeColor.Default)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors, default value uses the themes drawer icon color.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Default;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// User class names when active, separated by space.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ComponentBase.Common)]
|
||||
public string ActiveClass { get; set; } = "active";
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
protected Dictionary<string, object> Attributes
|
||||
{
|
||||
get => Disabled ? null : new Dictionary<string, object>()
|
||||
@ -32,44 +80,9 @@ public partial class NavLink : SelectItemBase
|
||||
{ "rel", !string.IsNullOrWhiteSpace(Target) ? "noopener noreferrer" : string.Empty }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Glyph to use if set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon. It supports the theme colors, default value uses the themes drawer icon color.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public ThemeColor IconColor { get; set; } = ThemeColor.Default;
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
public NavLinkMatch Match { get; set; } = NavLinkMatch.Prefix;
|
||||
#endregion
|
||||
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.ClickAction)]
|
||||
public string Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User class names when active, separated by space.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.ComponentBase.Common)]
|
||||
public string ActiveClass { get; set; } = "active";
|
||||
|
||||
[CascadingParameter] INavigationEventReceiver NavigationEventReceiver { get; set; }
|
||||
|
||||
protected Task HandleNavigation()
|
||||
{
|
||||
if (!Disabled && NavigationEventReceiver != null)
|
||||
{
|
||||
return NavigationEventReceiver.OnNavigation();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,13 @@ namespace Connected.Components;
|
||||
|
||||
public partial class NavMenu : UIComponent
|
||||
{
|
||||
|
||||
#region Content
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("navmenu")
|
||||
.AddClass($"navmenu-{Color.ToDescription()}")
|
||||
@ -17,9 +24,6 @@ public partial class NavMenu : UIComponent
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
[Category(CategoryTypes.NavMenu.Behavior)]
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the active NavLink.
|
||||
/// </summary>
|
||||
@ -54,5 +58,6 @@ public partial class NavMenu : UIComponent
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.NavMenu.Appearance)]
|
||||
public bool Dense { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -8,40 +8,57 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Overlay : UIComponent, IDisposable
|
||||
{
|
||||
#region Variables
|
||||
private bool _visible;
|
||||
|
||||
protected string Classname =>
|
||||
new CssBuilder("overlay")
|
||||
.AddClass("overlay-absolute", Absolute)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
protected string ScrimClassname =>
|
||||
new CssBuilder("overlay-scrim")
|
||||
.AddClass("overlay-dark", DarkBackground)
|
||||
.AddClass("overlay-light", LightBackground)
|
||||
.Build();
|
||||
|
||||
protected string Styles =>
|
||||
new StyleBuilder()
|
||||
.AddStyle("z-index", $"{ZIndex}", ZIndex != 5)
|
||||
.Build();
|
||||
|
||||
[Inject] public IScrollManager ScrollManager { get; set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Child content of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// Fires when Visible changes
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<bool> VisibleChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the overlay is clicked
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<MouseEventArgs> OnClick { get; set; }
|
||||
protected internal void OnClickHandler(MouseEventArgs ev)
|
||||
{
|
||||
if (AutoClose)
|
||||
Visible = false;
|
||||
OnClick.InvokeAsync(ev);
|
||||
if (Command?.CanExecute(CommandParameter) ?? false)
|
||||
{
|
||||
Command.Execute(CommandParameter);
|
||||
}
|
||||
}
|
||||
|
||||
//locks the scroll attaching a CSS class to the specified element, in this case the body
|
||||
void BlockScroll()
|
||||
{
|
||||
ScrollManager.LockScrollAsync("body", LockScrollClass);
|
||||
}
|
||||
|
||||
//removes the CSS class that prevented scrolling
|
||||
void UnblockScroll()
|
||||
{
|
||||
ScrollManager.UnlockScrollAsync("body", LockScrollClass);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
/// <summary>
|
||||
/// If true overlay will be visible. Two-way bindable.
|
||||
/// </summary>
|
||||
@ -58,20 +75,22 @@ public partial class Overlay : UIComponent, IDisposable
|
||||
VisibleChanged.InvokeAsync(_visible);
|
||||
}
|
||||
}
|
||||
protected string Classname =>
|
||||
new CssBuilder("overlay")
|
||||
.AddClass("overlay-absolute", Absolute)
|
||||
.AddClass(AdditionalClassList)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// If true overlay will set Visible false on click.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.ClickAction)]
|
||||
public bool AutoClose { get; set; }
|
||||
protected string ScrimClassname =>
|
||||
new CssBuilder("overlay-scrim")
|
||||
.AddClass("overlay-dark", DarkBackground)
|
||||
.AddClass("overlay-light", LightBackground)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// If true (default), the Document.body element will not be able to scroll
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.Behavior)]
|
||||
public bool LockScroll { get; set; } = true;
|
||||
protected string Styles =>
|
||||
new StyleBuilder()
|
||||
.AddStyle("z-index", $"{ZIndex}", ZIndex != 5)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// The css class that will be added to body if lockscroll is used.
|
||||
@ -107,6 +126,22 @@ public partial class Overlay : UIComponent, IDisposable
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.Behavior)]
|
||||
public int ZIndex { get; set; } = 5;
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If true overlay will set Visible false on click.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.ClickAction)]
|
||||
public bool AutoClose { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true (default), the Document.body element will not be able to scroll
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.Behavior)]
|
||||
public bool LockScroll { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Command parameter.
|
||||
@ -121,23 +156,9 @@ public partial class Overlay : UIComponent, IDisposable
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Overlay.ClickAction)]
|
||||
public ICommand Command { get; set; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the overlay is clicked
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<MouseEventArgs> OnClick { get; set; }
|
||||
protected internal void OnClickHandler(MouseEventArgs ev)
|
||||
{
|
||||
if (AutoClose)
|
||||
Visible = false;
|
||||
OnClick.InvokeAsync(ev);
|
||||
if (Command?.CanExecute(CommandParameter) ?? false)
|
||||
{
|
||||
Command.Execute(CommandParameter);
|
||||
}
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
//if not visible or CSS `position:absolute`, don't lock scroll
|
||||
protected override void OnAfterRender(bool firstTime)
|
||||
{
|
||||
@ -151,22 +172,35 @@ public partial class Overlay : UIComponent, IDisposable
|
||||
|
||||
}
|
||||
|
||||
//locks the scroll attaching a CSS class to the specified element, in this case the body
|
||||
void BlockScroll()
|
||||
{
|
||||
ScrollManager.LockScrollAsync("body", LockScrollClass);
|
||||
}
|
||||
|
||||
//removes the CSS class that prevented scrolling
|
||||
void UnblockScroll()
|
||||
{
|
||||
ScrollManager.UnlockScrollAsync("body", LockScrollClass);
|
||||
}
|
||||
|
||||
//When disposing the overlay, remove the class that prevented scrolling
|
||||
public void Dispose()
|
||||
{
|
||||
UnblockScroll();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,46 +9,15 @@ namespace Connected.Components;
|
||||
|
||||
public partial class PageContentNavigation : IAsyncDisposable
|
||||
{
|
||||
#region Variables
|
||||
private List<PageContentSection> _sections = new();
|
||||
private IScrollSpy _scrollSpy;
|
||||
|
||||
[Inject] IScrollSpyFactory ScrollSpyFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The displayed section within the MudPageContentNavigation
|
||||
/// </summary>
|
||||
public IEnumerable<PageContentSection> Sections => _sections.AsEnumerable();
|
||||
|
||||
/// <summary>
|
||||
/// The currently active session. null if there is no section selected
|
||||
/// </summary>
|
||||
public PageContentSection ActiveSection => _sections.FirstOrDefault(x => x.IsActive == true);
|
||||
|
||||
/// <summary>
|
||||
/// The text displayed about the section links. Defaults to "Conents"
|
||||
/// </summary>
|
||||
[Parameter] public string Headline { get; set; } = "Contents";
|
||||
|
||||
/// <summary>
|
||||
/// The css selector used to identifify the HTML elements that should be observed for viewport changes
|
||||
/// </summary>
|
||||
[Parameter] public string SectionClassSelector { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// If there are mutliple levels, this can specified to make a mapping between a level class likw "second-level" and the level in the hierarchy
|
||||
/// </summary>
|
||||
[Parameter] public IDictionary<string, int> HierarchyMapper { get; set; } = new Dictionary<string, int>();
|
||||
|
||||
/// <summary>
|
||||
/// If there are multiple levels, this property controls they visibility of them.
|
||||
/// </summary>
|
||||
[Parameter] public ContentNavigationExpandBehaviour ExpandBehaviour { get; set; } = ContentNavigationExpandBehaviour.Always;
|
||||
|
||||
/// <summary>
|
||||
/// If this option is true the first added section will become active when there is no other indication of an active session. Default value is false
|
||||
/// </summary>
|
||||
[Parameter] public bool ActivateFirstSectionAsDefault { get; set; } = false;
|
||||
private Dictionary<PageContentSection, PageContentSection> _parentMapper = new();
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
private Task OnNavLinkClick(string id)
|
||||
{
|
||||
SelectActiveSection(id);
|
||||
@ -99,7 +68,7 @@ public partial class PageContentNavigation : IAsyncDisposable
|
||||
/// <param name="forceUpdate">If true, StateHasChanged is called, forcing a rerender of the component</param>
|
||||
public void AddSection(string sectionName, string sectionId, bool forceUpdate) => AddSection(new(sectionName, sectionId), forceUpdate);
|
||||
|
||||
private Dictionary<PageContentSection, PageContentSection> _parentMapper = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add a section to the content navigation
|
||||
@ -139,13 +108,54 @@ public partial class PageContentNavigation : IAsyncDisposable
|
||||
/// Rerender the component
|
||||
/// </summary>
|
||||
public void Update() => StateHasChanged();
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// The displayed section within the MudPageContentNavigation
|
||||
/// </summary>
|
||||
public IEnumerable<PageContentSection> Sections => _sections.AsEnumerable();
|
||||
|
||||
/// <summary>
|
||||
/// The currently active session. null if there is no section selected
|
||||
/// </summary>
|
||||
public PageContentSection ActiveSection => _sections.FirstOrDefault(x => x.IsActive == true);
|
||||
|
||||
/// <summary>
|
||||
/// The text displayed about the section links. Defaults to "Conents"
|
||||
/// </summary>
|
||||
[Parameter] public string Headline { get; set; } = "Contents";
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
/// <summary>
|
||||
/// The css selector used to identifify the HTML elements that should be observed for viewport changes
|
||||
/// </summary>
|
||||
[Parameter] public string SectionClassSelector { get; set; } = string.Empty;
|
||||
#endregion
|
||||
|
||||
#region Behavior
|
||||
/// <summary>
|
||||
/// If there are mutliple levels, this can specified to make a mapping between a level class likw "second-level" and the level in the hierarchy
|
||||
/// </summary>
|
||||
[Parameter] public IDictionary<string, int> HierarchyMapper { get; set; } = new Dictionary<string, int>();
|
||||
|
||||
/// <summary>
|
||||
/// If there are multiple levels, this property controls they visibility of them.
|
||||
/// </summary>
|
||||
[Parameter] public ContentNavigationExpandBehaviour ExpandBehaviour { get; set; } = ContentNavigationExpandBehaviour.Always;
|
||||
|
||||
/// <summary>
|
||||
/// If this option is true the first added section will become active when there is no other indication of an active session. Default value is false
|
||||
/// </summary>
|
||||
[Parameter] public bool ActivateFirstSectionAsDefault { get; set; } = false;
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_scrollSpy = ScrollSpyFactory.Create();
|
||||
}
|
||||
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
@ -169,4 +179,6 @@ public partial class PageContentNavigation : IAsyncDisposable
|
||||
_scrollSpy.ScrollSectionSectionCentered -= ScrollSpy_ScrollSectionSectionCentered;
|
||||
return _scrollSpy.DisposeAsync();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -6,13 +6,13 @@
|
||||
@if (ShowFirstButton)
|
||||
{
|
||||
<li class="@ItemClassname">
|
||||
<IconButton Icon="@FirstIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" Clicked="@(() => OnClickControlButton(Page.First))" aria-label="First page"></IconButton>
|
||||
<GlyphButton Glyph="@FirstIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" Clicked="@(() => OnClickControlButton(Page.First))" aria-label="First page"></GlyphButton>
|
||||
</li>
|
||||
}
|
||||
@if (ShowPreviousButton)
|
||||
{
|
||||
<li class="@ItemClassname">
|
||||
<IconButton Icon="@BeforeIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" Clicked="@(() => OnClickControlButton(Page.Previous))" aria-label="Previous page"></IconButton>
|
||||
<GlyphButton Glyph="@BeforeIcon" Size="@Size" Variant="@Variant" Disabled="@(Selected == 1 || Disabled)" Clicked="@(() => OnClickControlButton(Page.Previous))" aria-label="Previous page"></GlyphButton>
|
||||
</li>
|
||||
}
|
||||
@foreach (var state in GeneratePagination())
|
||||
@ -39,13 +39,13 @@
|
||||
@if (ShowNextButton)
|
||||
{
|
||||
<li class="@ItemClassname">
|
||||
<IconButton Icon="@NextIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" Clicked="@(() => OnClickControlButton(Page.Next))" aria-label="Next page"></IconButton>
|
||||
<GlyphButton Glyph="@NextIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" Clicked="@(() => OnClickControlButton(Page.Next))" aria-label="Next page"></GlyphButton>
|
||||
</li>
|
||||
}
|
||||
@if (ShowLastButton)
|
||||
{
|
||||
<li class="@ItemClassname">
|
||||
<IconButton Icon="@LastIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" Clicked="@(() => OnClickControlButton(Page.Last))" aria-label="Last page"></IconButton>
|
||||
<GlyphButton Glyph="@LastIcon" Variant="@Variant" Size="@Size" Disabled="@(Selected == Count || Disabled)" Clicked="@(() => OnClickControlButton(Page.Last))" aria-label="Last page"></GlyphButton>
|
||||
</li>
|
||||
}
|
||||
</Element>
|
@ -10,6 +10,16 @@ namespace Connected.Components;
|
||||
|
||||
public partial class Paper : UIComponent
|
||||
{
|
||||
#region Content
|
||||
/// <summary>
|
||||
/// Child content of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Paper.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Styling
|
||||
protected string Classname =>
|
||||
new CssBuilder("paper")
|
||||
.AddClass($"paper-outlined", Outlined)
|
||||
@ -91,10 +101,6 @@ public partial class Paper : UIComponent
|
||||
[Category(CategoryTypes.Paper.Appearance)]
|
||||
public string MinWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of the component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
[Category(CategoryTypes.Paper.Behavior)]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -4,13 +4,13 @@
|
||||
@if (ReadOnly)
|
||||
{
|
||||
<span class="@ClassName">
|
||||
<Icon Icon="@ItemIcon" Size="@Size"></Icon>
|
||||
<Icon Glyph="@ItemIcon" Size="@Size"></Icon>
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@ClassName" @onmouseover="HandleMouseOver" @onclick="HandleClick" @onmouseout="HandleMouseOut ">
|
||||
<input class="rating-input" type="radio" tabindex="-1" value="@ItemValue" name="@Rating?.Name" disabled="@Disabled" checked="@(IsChecked)" @attributes="CustomAttributes" />
|
||||
<Icon Icon="@ItemIcon" Size="@Size"></Icon>
|
||||
<Icon Glyph="@ItemIcon" Size="@Size"></Icon>
|
||||
</span>
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
@if (!HideIcon)
|
||||
{
|
||||
<div class="snackbar-icon">
|
||||
<Icon Icon="@Icon" Color="@IconColor" Size="@IconSize" />
|
||||
<Icon Glyph="@Icon" Color="@IconColor" Size="@IconSize" />
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
@if (ShowCloseIcon)
|
||||
{
|
||||
<IconButton Icon="@CloseIcon" Size="Size.Small" Class="ms-2" Clicked="CloseIconClicked" />
|
||||
<GlyphButton Glyph="@CloseIcon" Size="Size.Small" Class="ms-2" Clicked="CloseIconClicked" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<span class="switch-thumb d-flex align-center justify-center">
|
||||
@if (!string.IsNullOrEmpty(ThumbIcon))
|
||||
{
|
||||
<Icon Color="@ThumbIconColor" Icon="@ThumbIcon" Style=" height:16px; width:16px;" />
|
||||
<Icon Color="@ThumbIconColor" Glyph="@ThumbIcon" Style=" height:16px; width:16px;" />
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<div class="d-flex">
|
||||
@if (GroupDefinition.Expandable)
|
||||
{
|
||||
<IconButton Class="table-row-expander" Icon="@(IsExpanded ? ExpandIcon : CollapseIcon)" Clicked="@(() => IsExpanded = !IsExpanded)" />
|
||||
<GlyphButton Class="table-row-expander" Glyph="@(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" 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" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@FirstIcon" Disabled="@BackButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.First))" aria-label="First page" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@BeforeIcon" Disabled="@BackButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Previous))" aria-label="Previous page" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@NextIcon" Disabled="@ForwardButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Next))" aria-label="Next page" />
|
||||
<GlyphButton Class="flip-x-rtl" Glyph="@LastIcon" Disabled="@ForwardButtonsDisabled" Clicked="@(() => Table.NavigateTo(Page.Last))" aria-label="Last page" />
|
||||
</div>
|
||||
}
|
||||
@if (HorizontalAlignment == HorizontalAlignment.Start ||
|
||||
|
@ -12,11 +12,11 @@
|
||||
{
|
||||
@if (_direction != SortDirection.None)
|
||||
{
|
||||
<Icon Icon="@SortIcon" Class="@GetSortIconClass()" />
|
||||
<Icon Glyph="@SortIcon" Class="@GetSortIconClass()" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Icon="@SortIcon" Class="table-sort-label-icon"/>
|
||||
<Icon Glyph="@SortIcon" Class="table-sort-label-icon" />
|
||||
}
|
||||
}
|
||||
@if (AppendIcon)
|
||||
|
@ -15,19 +15,19 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<IconButton Size="@Size.Small" Icon="@Icons.Outlined.Edit" Class="pa-0" Clicked="StartEditingItem" Disabled="Context.EditButtonDisabled(Item)" />
|
||||
<GlyphButton Size="@Size.Small" Glyph="@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" Clicked="FinishEdit" Size="@Size.Small" Disabled="@(!(Context?.Table.Validator?.IsValid ?? false))" />
|
||||
<GlyphButton Class="pa-0" Glyph="@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" Clicked="CancelEdit" Size="@Size.Small" />
|
||||
<GlyphButton Class="pa-0 ml-4" Glyph="@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" Clicked="StartEditingItem" Disabled="Context.EditButtonDisabled(Item)" />
|
||||
<GlyphButton Size="@Size.Small" Glyph="@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" Clicked="FinishEdit" Size="@Size.Small" Disabled="@(!(Context?.Table.Validator?.IsValid ?? false))" />
|
||||
<GlyphButton Class="pa-0" Glyph="@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" Clicked="CancelEdit" Size="@Size.Small" />
|
||||
<GlyphButton Class="pa-0 ml-4" Glyph="@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" Clicked="@AddTab" />
|
||||
<GlyphButton Glyph="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" Clicked="@AddTab" />
|
||||
</Tooltip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<IconButton Icon="@AddTabIcon" Class="@AddIconClass" Style="@AddIconStyle" Clicked="@AddTab" />
|
||||
<GlyphButton Glyph="@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" Clicked="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
|
||||
<GlyphButton Glyph="@CloseTabIcon" Class="@CloseIconClass" Style="@CloseIconStyle" Clicked="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
|
||||
</Tooltip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<IconButton Icon="@CloseTabIcon" Class="@CloseIconClass" Style="@CloseIconStyle" Clicked="EventCallback.Factory.Create<MouseEventArgs>(this, () => CloseTab.InvokeAsync(context))" />
|
||||
<GlyphButton Glyph="@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">
|
||||
<IconButton Icon="@_prevIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollPrev())" Disabled="@_prevButtonDisabled" />
|
||||
<GlyphButton Glyph="@_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">
|
||||
<IconButton Icon="@_nextIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollNext())" Disabled="@_nextButtonDisabled" />
|
||||
<GlyphButton Glyph="@_nextIcon" Color="@ScrollIconColor" Clicked="@((e) => ScrollNext())" Disabled="@_nextButtonDisabled" />
|
||||
</div>
|
||||
}
|
||||
@if (HeaderPosition == TabHeaderPosition.After && Header != null)
|
||||
@ -91,11 +91,11 @@
|
||||
}
|
||||
else if (String.IsNullOrEmpty(panel.Text) && !String.IsNullOrEmpty(panel.Icon))
|
||||
{
|
||||
<Icon Icon="@panel.Icon" Color="@IconColor" />
|
||||
<Icon Glyph="@panel.Icon" Color="@IconColor" />
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(panel.Text) && !String.IsNullOrEmpty(panel.Icon))
|
||||
{
|
||||
<Icon Icon="@panel.Icon" Color="@IconColor" Class="tab-icon-text" />
|
||||
<Icon Glyph="@panel.Icon" Color="@IconColor" Class="tab-icon-text" />
|
||||
@((MarkupString)panel.Text)
|
||||
}
|
||||
@if (TabPanelHeaderPosition == TabHeaderPosition.After && TabPanelHeader != null)
|
||||
|
@ -20,7 +20,7 @@
|
||||
@if (!string.IsNullOrEmpty(Icon))
|
||||
{
|
||||
<div class="treeview-item-icon">
|
||||
<Icon Icon="@Icon" Color="@IconColor" />
|
||||
<Icon Glyph="@Icon" Color="@IconColor" />
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
@if (!string.IsNullOrEmpty(EndIcon))
|
||||
{
|
||||
<div class="treeview-item-icon">
|
||||
<Icon Icon="@EndIcon" Color="@EndIconColor" />
|
||||
<Icon Glyph="@EndIcon" Color="@EndIconColor" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="treeview-item-arrow">
|
||||
@if (Visible)
|
||||
{
|
||||
<IconButton Clicked="@ToggleAsync" Icon="@(Loading ? LoadingIcon : ExpandedIcon)" Color="@(Loading ? LoadingIconColor : ExpandedIconColor)" Class="@Classname"></IconButton>
|
||||
<GlyphButton Clicked="@ToggleAsync" Glyph="@(Loading ? LoadingIcon : ExpandedIcon)" Color="@(Loading ? LoadingIconColor : ExpandedIconColor)" Class="@Classname"></GlyphButton>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
@ -20,4 +20,16 @@ public static class Helper
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsNumeric(string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
var number = Double.Parse(input);
|
||||
return true;
|
||||
} catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user