Changes: Drawer, Tabs, Layout
This commit is contained in:
parent
8d5445a509
commit
8c61578623
@ -37,6 +37,7 @@ public partial class Alert : UIComponent{
|
|||||||
[Parameter] public EventCallback<Alert> CloseClicked { get; set; }
|
[Parameter] public EventCallback<Alert> CloseClicked { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Content placeholders
|
#region Content placeholders
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Define the glyph used for the close button.
|
/// Define the glyph used for the close button.
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
using Connected.Annotations;
|
using Connected.Extensions;
|
||||||
using Connected.Extensions;
|
|
||||||
using Connected.Services;
|
using Connected.Services;
|
||||||
using Connected.Utilities;
|
using Connected.Utilities;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using System.ComponentModel;
|
|
||||||
|
|
||||||
namespace Connected.Components;
|
namespace Connected.Components;
|
||||||
|
|
||||||
@ -101,7 +99,6 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|||||||
return Anchor.ToDescription();
|
return Anchor.ToDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool closeOnMouseLeave = false;
|
private bool closeOnMouseLeave = false;
|
||||||
|
|
||||||
public async void OnMouseEnter()
|
public async void OnMouseEnter()
|
||||||
@ -122,69 +119,6 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
if (Variant != DrawerVariant.Temporary)
|
|
||||||
{
|
|
||||||
DrawerContainer?.Add(this);
|
|
||||||
}
|
|
||||||
base.OnInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (firstRender)
|
|
||||||
{
|
|
||||||
//await UpdateHeight();
|
|
||||||
var result = await Breakpointistener.Subscribe(UpdateBreakpointState);
|
|
||||||
//var currentBreakpoint = result.Breakpoint;
|
|
||||||
|
|
||||||
_breakpointListenerSubscriptionId = result.SubscriptionId;
|
|
||||||
|
|
||||||
var refresh = false;
|
|
||||||
|
|
||||||
if (_screenBreakpoint != result.Breakpoint) refresh = true;
|
|
||||||
_screenBreakpoint = result.Breakpoint;
|
|
||||||
if (_screenBreakpoint < Breakpoint && _open)
|
|
||||||
{
|
|
||||||
_keepInitialState = true;
|
|
||||||
await OpenChanged.InvokeAsync(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isRendered = true;
|
|
||||||
if (Anchor == Anchor.Bottom || Anchor == Anchor.Top || _screenBreakpoint == Breakpoint.None)
|
|
||||||
{
|
|
||||||
refresh = true;
|
|
||||||
}
|
|
||||||
if (refresh) StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
await base.OnAfterRenderAsync(firstRender);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
int _disposeCount;
|
|
||||||
public virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (Interlocked.Increment(ref _disposeCount) == 1)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
DrawerContainer?.Remove(this);
|
|
||||||
|
|
||||||
if (_breakpointListenerSubscriptionId != default)
|
|
||||||
{
|
|
||||||
Breakpointistener.Unsubscribe(_breakpointListenerSubscriptionId).AndForget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Content placeholders
|
#region Content placeholders
|
||||||
@ -427,4 +361,71 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Lifecycle
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
if (Variant != DrawerVariant.Temporary)
|
||||||
|
{
|
||||||
|
DrawerContainer?.Add(this);
|
||||||
|
}
|
||||||
|
base.OnInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
//await UpdateHeight();
|
||||||
|
var result = await Breakpointistener.Subscribe(UpdateBreakpointState);
|
||||||
|
//var currentBreakpoint = result.Breakpoint;
|
||||||
|
|
||||||
|
_breakpointListenerSubscriptionId = result.SubscriptionId;
|
||||||
|
|
||||||
|
var refresh = false;
|
||||||
|
|
||||||
|
if (_screenBreakpoint != result.Breakpoint) refresh = true;
|
||||||
|
_screenBreakpoint = result.Breakpoint;
|
||||||
|
if (_screenBreakpoint < Breakpoint && _open)
|
||||||
|
{
|
||||||
|
_keepInitialState = true;
|
||||||
|
await OpenChanged.InvokeAsync(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isRendered = true;
|
||||||
|
if (Anchor == Anchor.Bottom || Anchor == Anchor.Top || _screenBreakpoint == Breakpoint.None)
|
||||||
|
{
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
if (refresh) StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _disposeCount;
|
||||||
|
public virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (Interlocked.Increment(ref _disposeCount) == 1)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
DrawerContainer?.Remove(this);
|
||||||
|
|
||||||
|
if (_breakpointListenerSubscriptionId != default)
|
||||||
|
{
|
||||||
|
Breakpointistener.Unsubscribe(_breakpointListenerSubscriptionId).AndForget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,6 @@ public partial class DrawerHeader : UIComponent
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string? StyleList { get; set; }
|
public string? StyleList { get; set; }
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
protected virtual CssBuilder CompiledClassList
|
protected virtual CssBuilder CompiledClassList
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -55,4 +53,8 @@ public partial class DrawerHeader : UIComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using Connected.Utilities;
|
using Connected.Utilities;
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace Connected.Components;
|
namespace Connected.Components;
|
||||||
|
|
||||||
@ -20,12 +19,6 @@ public partial class Layout : DrawerContainer
|
|||||||
{
|
{
|
||||||
return new StyleBuilder()
|
return new StyleBuilder()
|
||||||
.AddStyle(base.StyleList);
|
.AddStyle(base.StyleList);
|
||||||
//.AddStyle("width", Width, !string.IsNullOrWhiteSpace(Width) && !Fixed)
|
|
||||||
//.AddStyle("--mud-drawer-width", Width, !string.IsNullOrWhiteSpace(Width) && (!Fixed || Variant == DrawerVariant.Temporary))
|
|
||||||
//.AddStyle("height", Height, !string.IsNullOrWhiteSpace(Height))
|
|
||||||
//.AddStyle("--mud-drawer-content-height",string.IsNullOrWhiteSpace(Height) ? _height.ToPx() : Height,Anchor == Anchor.Bottom || Anchor == Anchor.Top)
|
|
||||||
//.AddStyle("visibility", "hidden", string.IsNullOrWhiteSpace(Height) && _height == 0 && (Anchor == Anchor.Bottom || Anchor == Anchor.Top));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,11 @@
|
|||||||
using Connected.Annotations;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace Connected.Components;
|
namespace Connected.Components;
|
||||||
|
|
||||||
public partial class DynamicTabs : Tabs
|
public partial class DynamicTabs : Tabs
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The icon used for the add button
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string AddTabIcon { get; set; } = Icons.Material.Filled.Add;
|
|
||||||
|
|
||||||
/// <summary>
|
#region Event callbacks
|
||||||
/// the icon used of the close button
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string CloseTabIcon { get; set; } = Icons.Material.Filled.Close;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The callback, when the add button has been clicked
|
/// The callback, when the add button has been clicked
|
||||||
@ -29,47 +17,68 @@ public partial class DynamicTabs : Tabs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter] public EventCallback<TabPanel> CloseTab { get; set; }
|
[Parameter] public EventCallback<TabPanel> CloseTab { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Content placeholders
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Styling properties
|
||||||
|
|
||||||
|
protected override string InternalClassName { get; } = "dynamic-tabs";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The icon used for the add button
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string AddTabIcon { get; set; } = Icons.Material.Filled.Add;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the icon used of the close button
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string CloseTabIcon { get; set; } = Icons.Material.Filled.Close;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Classes that are applied to the icon button of the add button
|
/// Classes that are applied to the icon button of the add button
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string AddIconClass { get; set; } = string.Empty;
|
public string AddIconClass { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Styles that are applied to the icon button of the add button
|
/// Styles that are applied to the icon button of the add button
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string AddIconStyle { get; set; } = string.Empty;
|
public string AddIconStyle { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Classes that are applied to the icon button of the close button
|
/// Classes that are applied to the icon button of the close button
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string CloseIconClass { get; set; } = string.Empty;
|
public string CloseIconClass { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Styles that are applied to the icon button of the close button
|
/// Styles that are applied to the icon button of the close button
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string CloseIconStyle { get; set; } = string.Empty;
|
public string CloseIconStyle { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tooltip that shown when a user hovers of the add button. Empty or null, if no tooltip should be visible
|
/// Tooltip that shown when a user hovers of the add button. Empty or null, if no tooltip should be visible
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public string AddIconToolTip { get; set; } = string.Empty;
|
public string AddIconToolTip { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tooltip that shown when a user hovers of the close button. Empty or null, if no tooltip should be visible
|
/// Tooltip that shown when a user hovers of the close button. Empty or null, if no tooltip should be visible
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public string CloseIconToolTip { get; set; } = string.Empty;
|
public string CloseIconToolTip { get; set; } = string.Empty;
|
||||||
|
|
||||||
protected override string InternalClassName { get; } = "dynamic-tabs";
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Lifecycle
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
@namespace Connected.Components
|
@namespace Connected.Components
|
||||||
@using Connected.Annotations;
|
|
||||||
@inherits UIComponent
|
@inherits UIComponent
|
||||||
|
|
||||||
@implements IAsyncDisposable
|
@implements IAsyncDisposable
|
||||||
|
|
||||||
@if (Parent?.KeepPanelsAlive == true)
|
@if (Parent?.KeepPanelsAlive == true)
|
||||||
@ -16,125 +16,3 @@ else
|
|||||||
@ChildContent
|
@ChildContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
private Boolean _disposed;
|
|
||||||
|
|
||||||
[CascadingParameter] private Tabs Parent { get; set; }
|
|
||||||
|
|
||||||
public ElementReference PanelRef;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Text will be displayed in the TabPanel as TabTitle.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public string Text { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Glyph placed before the text if set.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public string Icon { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, the tabpanel will be disabled.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public bool Disabled { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional information to be showed into a badge
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public object BadgeData { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional information to show the badge as a dot.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public bool BadgeDot { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color of the badge.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public ThemeColor BadgeColor { get; set; } = ThemeColor.Primary;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unique TabPanel ID. Useful for activation when Panels are dynamically generated.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public object ID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised when tab is clicked
|
|
||||||
/// </summary>
|
|
||||||
[Parameter] public EventCallback<MouseEventArgs> OnClick { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Child content of component.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment ChildContent { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tab content of component.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment TabContent { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tab content wrapper of component. It is used to wrap the content of a tab heading in a user supplied div or component.
|
|
||||||
/// Use @context in the TabWrapperContent to render the tab header within your custom wrapper.
|
|
||||||
/// This is most useful with tooltips, which must wrap the entire content they refer to.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment<RenderFragment> TabWrapperContent { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// TabPanel Tooltip. It will be ignored if TabContent is provided.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public string ToolTip { get; set; }
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
await base.OnAfterRenderAsync(firstRender);
|
|
||||||
if(firstRender == true && Parent != null)
|
|
||||||
{
|
|
||||||
await Parent.SetPanelRef(PanelRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
// NOTE: we must not throw here because we need the component to be able to live for the API docs to be able to infer default values
|
|
||||||
//if (Parent == null)
|
|
||||||
// throw new ArgumentNullException(nameof(Parent), "TabPanel must exist within a Tabs component");
|
|
||||||
base.OnInitialized();
|
|
||||||
|
|
||||||
Parent?.AddPanel(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
if(_disposed == true) { return; }
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
await Parent?.RemovePanel(this);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
111
src/Connected.Components/Components/Tabs/TabPanel.razor.cs
Normal file
111
src/Connected.Components/Components/Tabs/TabPanel.razor.cs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
|
||||||
|
namespace Connected.Components;
|
||||||
|
public partial class TabPanel : UIComponent
|
||||||
|
{
|
||||||
|
#region Event callbacks
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised when tab is clicked
|
||||||
|
/// </summary>
|
||||||
|
[Parameter] public EventCallback<MouseEventArgs> OnClick { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Content placeholders
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Child content of component.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment ChildContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tab content of component.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment TabContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tab content wrapper of component. It is used to wrap the content of a tab heading in a user supplied div or component.
|
||||||
|
/// Use @context in the TabWrapperContent to render the tab header within your custom wrapper.
|
||||||
|
/// This is most useful with tooltips, which must wrap the entire content they refer to.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment<RenderFragment> TabWrapperContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TabPanel Tooltip. It will be ignored if TabContent is provided.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string ToolTip { get; set; }
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
[CascadingParameter] private Tabs Parent { get; set; }
|
||||||
|
|
||||||
|
public ElementReference PanelRef;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Styling properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text will be displayed in the TabPanel as TabTitle.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Glyph placed before the text if set.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string Icon { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, the tabpanel will be disabled.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique TabPanel ID. Useful for activation when Panels are dynamically generated.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public object ID { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Lifecycle
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
if (firstRender == true && Parent != null)
|
||||||
|
{
|
||||||
|
await Parent.SetPanelRef(PanelRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
// NOTE: we must not throw here because we need the component to be able to live for the API docs to be able to infer default values
|
||||||
|
//if (Parent == null)
|
||||||
|
// throw new ArgumentNullException(nameof(Parent), "TabPanel must exist within a Tabs component");
|
||||||
|
base.OnInitialized();
|
||||||
|
|
||||||
|
Parent?.AddPanel(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (_disposed == true) { return; }
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
await Parent?.RemovePanel(this);
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -98,10 +98,6 @@
|
|||||||
<Icon Icon="@panel.Icon" Color="@IconColor" Class="tab-icon-text" />
|
<Icon Icon="@panel.Icon" Color="@IconColor" Class="tab-icon-text" />
|
||||||
@((MarkupString)panel.Text)
|
@((MarkupString)panel.Text)
|
||||||
}
|
}
|
||||||
@if (panel.BadgeData != null || panel.BadgeDot)
|
|
||||||
{
|
|
||||||
<Badge Dot="@panel.BadgeDot" Content="@panel.BadgeData" Color="@panel.BadgeColor" Class="tab-badge" />
|
|
||||||
}
|
|
||||||
@if (TabPanelHeaderPosition == TabHeaderPosition.After && TabPanelHeader != null)
|
@if (TabPanelHeaderPosition == TabHeaderPosition.After && TabPanelHeader != null)
|
||||||
{
|
{
|
||||||
<div class="tabs-panel-header mud-tabs-panel-header-after">
|
<div class="tabs-panel-header mud-tabs-panel-header-after">
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Connected.Annotations;
|
|
||||||
using Connected.Extensions;
|
using Connected.Extensions;
|
||||||
using Connected.Interop;
|
using Connected.Interop;
|
||||||
using Connected.Services;
|
using Connected.Services;
|
||||||
@ -11,6 +10,19 @@ namespace Connected.Components;
|
|||||||
|
|
||||||
public partial class Tabs : UIComponent, IAsyncDisposable
|
public partial class Tabs : UIComponent, IAsyncDisposable
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#region Event callbacks
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when ActivePanelIndex changes.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<int> ActivePanelIndexChanged { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Content placeholders
|
||||||
|
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
private int _activePanelIndex = 0;
|
private int _activePanelIndex = 0;
|
||||||
@ -30,172 +42,61 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
|
|
||||||
private IResizeObserver _resizeObserver;
|
private IResizeObserver _resizeObserver;
|
||||||
|
|
||||||
[CascadingParameter(Name = "RightToLeft")] public bool RightToLeft { get; set; }
|
|
||||||
|
|
||||||
[Inject] private IResizeObserverFactory _resizeObserverFactory { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, render all tabs and hide (display:none) every non-active.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public bool KeepPanelsAlive { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, sets the border-radius to theme default.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool Rounded { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, sets a border between the content and the toolbar depending on the position.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool Border { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, toolbar will be outlined.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool Outlined { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, centers the tabitems.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool Centered { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hides the active tab slider.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool HideSlider { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Glyph to use for left pagination.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string PrevIcon { get; set; } = Icons.Filled.ChevronLeft;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Glyph to use for right pagination.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string NextIcon { get; set; } = Icons.Filled.ChevronRight;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, always display the scroll buttons even if the tabs are smaller than the required with, buttons will be disabled if there is nothing to scroll.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool AlwaysShowScrollButtons { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the maxheight the component can have.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public int? MaxHeight { get; set; } = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the position of the tabs itself.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public Position Position { get; set; } = Position.Top;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color of the component. It supports the theme colors.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public ThemeColor Color { get; set; } = ThemeColor.Default;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color of the tab slider. It supports the theme colors.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public ThemeColor SliderColor { get; set; } = ThemeColor.Inherit;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color of the icon. It supports the theme colors.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color of the next/prev icons. It supports the theme colors.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public ThemeColor ScrollIconColor { get; set; } = ThemeColor.Inherit;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The higher the number, the heavier the drop-shadow, applies around the whole component.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public int Elevation { set; get; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, will apply elevation, rounded, outlined effects to the whole tab component instead of just toolbar.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool ApplyEffectsToContainer { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, disables ripple effect.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool DisableRipple { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, disables slider animation
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public bool DisableSliderAnimation { get => _disableSliderAnimation; set => _disableSliderAnimation = value; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Child content of component.
|
/// Child content of component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment ChildContent { get; set; }
|
public RenderFragment ChildContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A readonly list of the current panels. Panels should be added or removed through the RenderTree use this collection to get informations about the current panels
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<TabPanel> Panels { get; private set; }
|
||||||
|
|
||||||
|
private List<TabPanel> _panels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A render fragment that is added before or after (based on the value of HeaderPosition) the tabs inside the header panel of the tab control
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment<Tabs> Header { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A render fragment that is added before or after (based on the value of HeaderPosition) inside each tab panel
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment<TabPanel> TabPanelHeader { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Additional content specified by Header is placed either before the tabs, after or not at all
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public TabHeaderPosition HeaderPosition { get; set; } = TabHeaderPosition.After;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Additional content specified by Header is placed either before the tabs, after or not at all
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public TabHeaderPosition TabPanelHeaderPosition { get; set; } = TabHeaderPosition.After;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can be used in derived class to add a class to the main container. If not overwritten return an empty string
|
||||||
|
/// </summary>
|
||||||
|
protected virtual string InternalClassName { get; } = string.Empty;
|
||||||
|
|
||||||
|
private string _prevIcon;
|
||||||
|
|
||||||
|
private string _nextIcon;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This fragment is placed between toolbar and panels.
|
/// This fragment is placed between toolbar and panels.
|
||||||
/// It can be used to display additional content like an address line in a browser.
|
/// It can be used to display additional content like an address line in a browser.
|
||||||
/// The active tab will be the content of this RenderFragement
|
/// The active tab will be the content of this RenderFragement
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment<TabPanel> PrePanelContent { get; set; }
|
public RenderFragment<TabPanel> PrePanelContent { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom class/classes for TabPanel
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string TabPanelClass { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom class/classes for Selected Content Panel
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Appearance)]
|
|
||||||
public string PanelClass { get; set; }
|
|
||||||
|
|
||||||
public TabPanel ActivePanel { get; private set; }
|
public TabPanel ActivePanel { get; private set; }
|
||||||
|
|
||||||
@ -203,7 +104,6 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
/// The current active panel index. Also with Bidirectional Binding
|
/// The current active panel index. Also with Bidirectional Binding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public int ActivePanelIndex
|
public int ActivePanelIndex
|
||||||
{
|
{
|
||||||
get => _activePanelIndex;
|
get => _activePanelIndex;
|
||||||
@ -219,113 +119,9 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
[CascadingParameter(Name = "RightToLeft")] public bool RightToLeft { get; set; }
|
||||||
/// Fired when ActivePanelIndex changes.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
public EventCallback<int> ActivePanelIndexChanged { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
[Inject] private IResizeObserverFactory _resizeObserverFactory { get; set; }
|
||||||
/// A readonly list of the current panels. Panels should be added or removed through the RenderTree use this collection to get informations about the current panels
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<TabPanel> Panels { get; private set; }
|
|
||||||
|
|
||||||
private List<TabPanel> _panels;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A render fragment that is added before or after (based on the value of HeaderPosition) the tabs inside the header panel of the tab control
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment<Tabs> Header { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Additional content specified by Header is placed either before the tabs, after or not at all
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public TabHeaderPosition HeaderPosition { get; set; } = TabHeaderPosition.After;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A render fragment that is added before or after (based on the value of HeaderPosition) inside each tab panel
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public RenderFragment<TabPanel> TabPanelHeader { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Additional content specified by Header is placed either before the tabs, after or not at all
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Tabs.Behavior)]
|
|
||||||
public TabHeaderPosition TabPanelHeaderPosition { get; set; } = TabHeaderPosition.After;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Can be used in derived class to add a class to the main container. If not overwritten return an empty string
|
|
||||||
/// </summary>
|
|
||||||
protected virtual string InternalClassName { get; } = string.Empty;
|
|
||||||
|
|
||||||
private string _prevIcon;
|
|
||||||
|
|
||||||
private string _nextIcon;
|
|
||||||
|
|
||||||
#region Life cycle management
|
|
||||||
|
|
||||||
public Tabs()
|
|
||||||
{
|
|
||||||
_panels = new List<TabPanel>();
|
|
||||||
Panels = _panels.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
_resizeObserver = _resizeObserverFactory.Create();
|
|
||||||
base.OnInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
if (_resizeObserver == null)
|
|
||||||
{
|
|
||||||
_resizeObserver = _resizeObserverFactory.Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
Rerender();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (firstRender)
|
|
||||||
{
|
|
||||||
var items = _panels.Select(x => x.PanelRef).ToList();
|
|
||||||
items.Add(_tabsContentSize);
|
|
||||||
|
|
||||||
if (_panels.Count > 0)
|
|
||||||
ActivePanel = _panels[_activePanelIndex];
|
|
||||||
|
|
||||||
await _resizeObserver.Observe(items);
|
|
||||||
|
|
||||||
_resizeObserver.OnResized += OnResized;
|
|
||||||
|
|
||||||
Rerender();
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
_isRendered = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
if (_isDisposed == true)
|
|
||||||
return;
|
|
||||||
_isDisposed = true;
|
|
||||||
_resizeObserver.OnResized -= OnResized;
|
|
||||||
await _resizeObserver.DisposeAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Children
|
|
||||||
|
|
||||||
internal void AddPanel(TabPanel tabPanel)
|
internal void AddPanel(TabPanel tabPanel)
|
||||||
{
|
{
|
||||||
@ -414,37 +210,25 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Style and classes
|
#region Styling properties
|
||||||
|
|
||||||
protected string TabsClassnames =>
|
protected string TabsClassnames =>
|
||||||
new CssBuilder("tabs")
|
new CssBuilder("tabs")
|
||||||
.AddClass($"tabs-rounded", ApplyEffectsToContainer && Rounded)
|
|
||||||
.AddClass($"paper-outlined", ApplyEffectsToContainer && Outlined)
|
|
||||||
.AddClass($"elevation-{Elevation}", ApplyEffectsToContainer && Elevation != 0)
|
|
||||||
.AddClass($"tabs-reverse", Position == Position.Bottom)
|
|
||||||
.AddClass($"tabs-vertical", IsVerticalTabs())
|
|
||||||
.AddClass($"tabs-vertical-reverse", Position == Position.Right && !RightToLeft || (Position == Position.Left) && RightToLeft)
|
|
||||||
.AddClass(InternalClassName)
|
.AddClass(InternalClassName)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
protected string ToolbarClassnames =>
|
protected string ToolbarClassnames =>
|
||||||
new CssBuilder("tabs-toolbar")
|
new CssBuilder("tabs-toolbar")
|
||||||
.AddClass($"tabs-rounded", !ApplyEffectsToContainer && Rounded)
|
|
||||||
.AddClass($"tabs-vertical", IsVerticalTabs())
|
.AddClass($"tabs-vertical", IsVerticalTabs())
|
||||||
.AddClass($"tabs-toolbar-{Color.ToDescription()}", Color != ThemeColor.Default)
|
|
||||||
.AddClass($"tabs-border-{ConvertPosition(Position).ToDescription()}", Border)
|
|
||||||
.AddClass($"paper-outlined", !ApplyEffectsToContainer && Outlined)
|
|
||||||
.AddClass($"elevation-{Elevation}", !ApplyEffectsToContainer && Elevation != 0)
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
protected string WrapperClassnames =>
|
protected string WrapperClassnames =>
|
||||||
new CssBuilder("tabs-toolbar-wrapper")
|
new CssBuilder("tabs-toolbar-wrapper")
|
||||||
.AddClass($"tabs-centered", Centered)
|
|
||||||
.AddClass($"tabs-vertical", IsVerticalTabs())
|
.AddClass($"tabs-vertical", IsVerticalTabs())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
protected string WrapperScrollStyle =>
|
protected string WrapperScrollStyle =>
|
||||||
new StyleBuilder()
|
new StyleBuilder()
|
||||||
.AddStyle("transform", $"translateX({(-1 * _scrollPosition).ToString(CultureInfo.InvariantCulture)}px)", Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("transform", $"translateY({(-1 * _scrollPosition).ToString(CultureInfo.InvariantCulture)}px)", IsVerticalTabs())
|
.AddStyle("transform", $"translateY({(-1 * _scrollPosition).ToString(CultureInfo.InvariantCulture)}px)", IsVerticalTabs())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -456,30 +240,19 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
|
|
||||||
protected string SliderClass =>
|
protected string SliderClass =>
|
||||||
new CssBuilder("tab-slider")
|
new CssBuilder("tab-slider")
|
||||||
.AddClass($"{SliderColor.ToDescription()}", SliderColor != ThemeColor.Inherit)
|
|
||||||
.AddClass($"tab-slider-horizontal", Position is Position.Top or Position.Bottom)
|
|
||||||
.AddClass($"tab-slider-vertical", IsVerticalTabs())
|
.AddClass($"tab-slider-vertical", IsVerticalTabs())
|
||||||
.AddClass($"tab-slider-horizontal-reverse", Position == Position.Bottom)
|
|
||||||
.AddClass($"tab-slider-vertical-reverse", Position == Position.Right || Position == Position.Start && RightToLeft || Position == Position.End && !RightToLeft)
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
protected string MaxHeightStyles =>
|
protected string MaxHeightStyles =>
|
||||||
new StyleBuilder()
|
new StyleBuilder()
|
||||||
.AddStyle("max-height", MaxHeight.ToPx(), MaxHeight != null)
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
protected string SliderStyle => RightToLeft ?
|
protected string SliderStyle => RightToLeft ?
|
||||||
new StyleBuilder()
|
new StyleBuilder()
|
||||||
.AddStyle("width", _size.ToPx(), Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("right", _position.ToPx(), Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("transition", _disableSliderAnimation ? "none" : "right .3s cubic-bezier(.64,.09,.08,1);", Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("transition", _disableSliderAnimation ? "none" : "top .3s cubic-bezier(.64,.09,.08,1);", IsVerticalTabs())
|
.AddStyle("transition", _disableSliderAnimation ? "none" : "top .3s cubic-bezier(.64,.09,.08,1);", IsVerticalTabs())
|
||||||
.AddStyle("height", _size.ToPx(), IsVerticalTabs())
|
.AddStyle("height", _size.ToPx(), IsVerticalTabs())
|
||||||
.AddStyle("top", _position.ToPx(), IsVerticalTabs())
|
.AddStyle("top", _position.ToPx(), IsVerticalTabs())
|
||||||
.Build() : new StyleBuilder()
|
.Build() : new StyleBuilder()
|
||||||
.AddStyle("width", _size.ToPx(), Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("left", _position.ToPx(), Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("transition", _disableSliderAnimation ? "none" : "left .3s cubic-bezier(.64,.09,.08,1);", Position is Position.Top or Position.Bottom)
|
|
||||||
.AddStyle("transition", _disableSliderAnimation ? "none" : "top .3s cubic-bezier(.64,.09,.08,1);", IsVerticalTabs())
|
.AddStyle("transition", _disableSliderAnimation ? "none" : "top .3s cubic-bezier(.64,.09,.08,1);", IsVerticalTabs())
|
||||||
.AddStyle("height", _size.ToPx(), IsVerticalTabs())
|
.AddStyle("height", _size.ToPx(), IsVerticalTabs())
|
||||||
.AddStyle("top", _position.ToPx(), IsVerticalTabs())
|
.AddStyle("top", _position.ToPx(), IsVerticalTabs())
|
||||||
@ -532,9 +305,151 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
return tabStyle;
|
return tabStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the active tab slider.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool HideSlider { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color of the component. It supports the theme colors.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public ThemeColor Color { get; set; } = ThemeColor.Default;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color of the tab slider. It supports the theme colors.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public ThemeColor SliderColor { get; set; } = ThemeColor.Inherit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color of the icon. It supports the theme colors.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public ThemeColor IconColor { get; set; } = ThemeColor.Inherit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The color of the next/prev icons. It supports the theme colors.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public ThemeColor ScrollIconColor { get; set; } = ThemeColor.Inherit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, always display the scroll buttons even if the tabs are smaller than the required with, buttons will be disabled if there is nothing to scroll.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool AlwaysShowScrollButtons { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Glyph to use for left pagination.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string PrevIcon { get; set; } = Icons.Filled.ChevronLeft;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Glyph to use for right pagination.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string NextIcon { get; set; } = Icons.Filled.ChevronRight;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the position of the tabs itself.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Position Position { get; set; } = Position.Top;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, will apply elevation, rounded, outlined effects to the whole tab component instead of just toolbar.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool ApplyEffectsToContainer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, disables ripple effect.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool DisableRipple { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, disables slider animation
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool DisableSliderAnimation { get => _disableSliderAnimation; set => _disableSliderAnimation = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom class/classes for TabPanel
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string TabPanelClass { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom class/classes for Selected Content Panel
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string PanelClass { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, render all tabs and hide (display:none) every non-active.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool KeepPanelsAlive { get; set; } = false;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Rendering and placement
|
#region Lifecycle
|
||||||
|
|
||||||
|
public Tabs()
|
||||||
|
{
|
||||||
|
_panels = new List<TabPanel>();
|
||||||
|
Panels = _panels.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
_resizeObserver = _resizeObserverFactory.Create();
|
||||||
|
base.OnInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
|
if (_resizeObserver == null)
|
||||||
|
{
|
||||||
|
_resizeObserver = _resizeObserverFactory.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
var items = _panels.Select(x => x.PanelRef).ToList();
|
||||||
|
items.Add(_tabsContentSize);
|
||||||
|
|
||||||
|
if (_panels.Count > 0)
|
||||||
|
ActivePanel = _panels[_activePanelIndex];
|
||||||
|
|
||||||
|
await _resizeObserver.Observe(items);
|
||||||
|
|
||||||
|
_resizeObserver.OnResized += OnResized;
|
||||||
|
|
||||||
|
Rerender();
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
_isRendered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (_isDisposed == true)
|
||||||
|
return;
|
||||||
|
_isDisposed = true;
|
||||||
|
_resizeObserver.OnResized -= OnResized;
|
||||||
|
await _resizeObserver.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private void Rerender()
|
private void Rerender()
|
||||||
{
|
{
|
||||||
@ -605,10 +520,6 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
|
|
||||||
private double GetPanelLength(TabPanel panel) => panel == null ? 0.0 : GetRelevantSize(panel.PanelRef);
|
private double GetPanelLength(TabPanel panel) => panel == null ? 0.0 : GetRelevantSize(panel.PanelRef);
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region scrolling
|
|
||||||
|
|
||||||
private void SetScrollButtonVisibility()
|
private void SetScrollButtonVisibility()
|
||||||
{
|
{
|
||||||
_showScrollButtons = AlwaysShowScrollButtons || _allTabsSize > _toolbarContentSize;
|
_showScrollButtons = AlwaysShowScrollButtons || _allTabsSize > _toolbarContentSize;
|
||||||
@ -740,4 +651,5 @@ public partial class Tabs : UIComponent, IAsyncDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
@ -15,7 +15,6 @@ public partial class TextField<T> : DebouncedInput<T>
|
|||||||
/// Type of the input element. It should be a valid HTML5 input type.
|
/// Type of the input element. It should be a valid HTML5 input type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.FormComponent.Behavior)]
|
|
||||||
public InputType InputType { get; set; } = InputType.Text;
|
public InputType InputType { get; set; } = InputType.Text;
|
||||||
|
|
||||||
internal override InputType GetInputType() => InputType;
|
internal override InputType GetInputType() => InputType;
|
||||||
@ -26,7 +25,6 @@ public partial class TextField<T> : DebouncedInput<T>
|
|||||||
/// Show clear button.
|
/// Show clear button.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.FormComponent.Behavior)]
|
|
||||||
public bool Clearable { get; set; } = false;
|
public bool Clearable { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -117,7 +115,6 @@ public partial class TextField<T> : DebouncedInput<T>
|
|||||||
/// Note: when Mask is set, TextField will ignore some properties such as Lines, Pattern or HideSpinButtons, OnKeyDown and OnKeyUp, etc.
|
/// Note: when Mask is set, TextField will ignore some properties such as Lines, Pattern or HideSpinButtons, OnKeyDown and OnKeyUp, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[Category(CategoryTypes.General.Data)]
|
|
||||||
public IMask Mask
|
public IMask Mask
|
||||||
{
|
{
|
||||||
get => _maskReference?.MaskKind ?? _mask; // this might look strange, but it is absolutely necessary due to how Mask works.
|
get => _maskReference?.MaskKind ?? _mask; // this might look strange, but it is absolutely necessary due to how Mask works.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user