|
|
|
@ -3,6 +3,7 @@ using Connected.Extensions;
|
|
|
|
|
using Connected.Services;
|
|
|
|
|
using Connected.Utilities;
|
|
|
|
|
using Microsoft.AspNetCore.Components;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
|
|
|
|
|
namespace Connected.Components;
|
|
|
|
|
|
|
|
|
@ -12,54 +13,192 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|
|
|
|
private ElementReference _contentRef;
|
|
|
|
|
private DrawerClipMode _clipMode;
|
|
|
|
|
private bool? _isOpenWhenLarge = null;
|
|
|
|
|
private bool _open, _rtl, _isRendered, _initial = true, _keepInitialState, _fixed = true;
|
|
|
|
|
private Breakpoint _breakpoint = Breakpoint.Md, _screenBreakpoint = Breakpoint.None;
|
|
|
|
|
private bool _open;
|
|
|
|
|
private bool _rtl;
|
|
|
|
|
private bool _isRendered;
|
|
|
|
|
private bool _initial = true;
|
|
|
|
|
private bool _keepInitialState;
|
|
|
|
|
private bool _fixed = true;
|
|
|
|
|
private Breakpoint _breakpoint = Breakpoint.Md;
|
|
|
|
|
private Breakpoint _screenBreakpoint = Breakpoint.None;
|
|
|
|
|
private Guid _breakpointListenerSubscriptionId;
|
|
|
|
|
|
|
|
|
|
private bool OverlayVisible => _open && !DisableOverlay &&
|
|
|
|
|
(Variant == DrawerVariant.Temporary ||
|
|
|
|
|
(_screenBreakpoint < Breakpoint && Variant == DrawerVariant.Mini) ||
|
|
|
|
|
(_screenBreakpoint < Breakpoint && Variant == DrawerVariant.Responsive));
|
|
|
|
|
#region EventCallbacks
|
|
|
|
|
|
|
|
|
|
protected string Classname =>
|
|
|
|
|
new CssBuilder("drawer")
|
|
|
|
|
.AddClass($"drawer-fixed", Fixed)
|
|
|
|
|
.AddClass($"drawer-pos-{GetPosition()}")
|
|
|
|
|
.AddClass($"drawer--open", Open)
|
|
|
|
|
.AddClass($"drawer--closed", !Open)
|
|
|
|
|
.AddClass($"drawer--initial", _initial)
|
|
|
|
|
.AddClass($"drawer-{Breakpoint.ToDescription()}")
|
|
|
|
|
.AddClass($"drawer-clipped-{_clipMode.ToDescription()}")
|
|
|
|
|
.AddClass($"theme-{Color.ToDescription()}", Color != ThemeColor.Default)
|
|
|
|
|
.AddClass($"elevation-{Elevation}")
|
|
|
|
|
.AddClass($"drawer-{Variant.ToDescription()}")
|
|
|
|
|
.AddClass(AdditionalClassList)
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
protected string OverlayClass =>
|
|
|
|
|
new CssBuilder("drawer-overlay mud-overlay-drawer")
|
|
|
|
|
.AddClass($"drawer-pos-{GetPosition()}")
|
|
|
|
|
.AddClass($"drawer-overlay--open", Open)
|
|
|
|
|
.AddClass($"drawer-overlay-{Variant.ToDescription()}")
|
|
|
|
|
.AddClass($"drawer-overlay-{Breakpoint.ToDescription()}")
|
|
|
|
|
.AddClass($"drawer-overlay--initial", _initial)
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
protected string Stylename =>
|
|
|
|
|
new StyleBuilder()
|
|
|
|
|
//.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))
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
[Inject] public IBreakpointService Breakpointistener { get; set; }
|
|
|
|
|
[Parameter] public EventCallback<bool> OpenChanged { get; set; }
|
|
|
|
|
|
|
|
|
|
public async Task OnNavigation()
|
|
|
|
|
{
|
|
|
|
|
if (Variant == DrawerVariant.Temporary ||
|
|
|
|
|
(Variant == DrawerVariant.Responsive && await Breakpointistener.GetBreakpoint() < Breakpoint))
|
|
|
|
|
{
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ResizeListener_OnBreakpointChanged(object sender, Breakpoint breakpoint)
|
|
|
|
|
{
|
|
|
|
|
if (!_isRendered)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
InvokeAsync(() => UpdateBreakpointState(breakpoint));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void UpdateBreakpointState(Breakpoint breakpoint)
|
|
|
|
|
{
|
|
|
|
|
var isStateChanged = false;
|
|
|
|
|
if (breakpoint == Breakpoint.None)
|
|
|
|
|
{
|
|
|
|
|
breakpoint = await Breakpointistener.GetBreakpoint();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (breakpoint < Breakpoint && _screenBreakpoint >= Breakpoint && (Variant == DrawerVariant.Responsive || Variant == DrawerVariant.Mini))
|
|
|
|
|
{
|
|
|
|
|
_isOpenWhenLarge = Open;
|
|
|
|
|
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
else if (breakpoint >= Breakpoint && _screenBreakpoint < Breakpoint && (Variant == DrawerVariant.Responsive || Variant == DrawerVariant.Mini))
|
|
|
|
|
{
|
|
|
|
|
if (Open && PreserveOpenState)
|
|
|
|
|
{
|
|
|
|
|
DrawerContainer?.FireDrawersChanged();
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
else if (_isOpenWhenLarge != null)
|
|
|
|
|
{
|
|
|
|
|
await OpenChanged.InvokeAsync(_isOpenWhenLarge.Value);
|
|
|
|
|
_isOpenWhenLarge = null;
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_breakpoint != _screenBreakpoint)
|
|
|
|
|
{
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
_screenBreakpoint = breakpoint;
|
|
|
|
|
|
|
|
|
|
if (isStateChanged)
|
|
|
|
|
{
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal string GetPosition()
|
|
|
|
|
{
|
|
|
|
|
switch (Anchor)
|
|
|
|
|
{
|
|
|
|
|
case Anchor.Start:
|
|
|
|
|
return RightToLeft ? "right" : "left";
|
|
|
|
|
case Anchor.End:
|
|
|
|
|
return RightToLeft ? "left" : "right";
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Anchor.ToDescription();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private bool closeOnMouseLeave = false;
|
|
|
|
|
|
|
|
|
|
public async void OnMouseEnter()
|
|
|
|
|
{
|
|
|
|
|
if (Variant == DrawerVariant.Mini && !Open && OpenMiniOnHover)
|
|
|
|
|
{
|
|
|
|
|
closeOnMouseLeave = true;
|
|
|
|
|
await OpenChanged.InvokeAsync(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async void OnMouseLeave()
|
|
|
|
|
{
|
|
|
|
|
if (Variant == DrawerVariant.Mini && Open && closeOnMouseLeave)
|
|
|
|
|
{
|
|
|
|
|
closeOnMouseLeave = false;
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
#region Content placeholders
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Child content of component.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
public RenderFragment ChildContent { get; set; }
|
|
|
|
|
|
|
|
|
|
[CascadingParameter] DrawerContainer DrawerContainer { get; set; }
|
|
|
|
|
|
|
|
|
|
[Inject] public IBreakpointService Breakpointistener { get; set; }
|
|
|
|
|
|
|
|
|
|
[CascadingParameter(Name = "RightToLeft")]
|
|
|
|
|
bool RightToLeft
|
|
|
|
|
{
|
|
|
|
@ -74,11 +213,73 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Styling properties
|
|
|
|
|
|
|
|
|
|
private CssBuilder CompiledClassList
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new CssBuilder("drawer")
|
|
|
|
|
.AddClass($"drawer-fixed", Fixed)
|
|
|
|
|
.AddClass($"drawer-pos-{GetPosition()}")
|
|
|
|
|
.AddClass($"drawer--open", Open)
|
|
|
|
|
.AddClass($"drawer--closed", !Open)
|
|
|
|
|
.AddClass($"drawer--initial", _initial)
|
|
|
|
|
.AddClass($"drawer-{Breakpoint.ToDescription()}")
|
|
|
|
|
.AddClass($"drawer-clipped-{_clipMode.ToDescription()}")
|
|
|
|
|
//.AddClass($"theme-{Color.ToDescription()}", Color != ThemeColor.Default)
|
|
|
|
|
.AddClass($"elevation-{Elevation}")
|
|
|
|
|
.AddClass($"drawer-{Variant.ToDescription()}")
|
|
|
|
|
.AddClass(ClassList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected StyleBuilder CompiledStyleList
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new StyleBuilder()
|
|
|
|
|
.AddStyle(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));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected CssBuilder CompiledOverlayClass
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new CssBuilder("drawer-overlay mud-overlay-drawer")
|
|
|
|
|
.AddClass($"drawer-pos-{GetPosition()}")
|
|
|
|
|
.AddClass($"drawer-overlay--open", Open)
|
|
|
|
|
.AddClass($"drawer-overlay-{Variant.ToDescription()}")
|
|
|
|
|
.AddClass($"drawer-overlay-{Breakpoint.ToDescription()}")
|
|
|
|
|
.AddClass($"drawer-overlay--initial", _initial);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A space separated list of class names, added on top of the default class list.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
public string? ClassList { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A space separated list of class names, added on top of the default class list.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
public string? StyleList { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// If true, drawer position will be fixed. (CSS position: fixed;)
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public bool Fixed
|
|
|
|
|
{
|
|
|
|
|
get => _fixed && DrawerContainer is Layout;
|
|
|
|
@ -94,63 +295,78 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|
|
|
|
/// The higher the number, the heavier the drop-shadow. 0 for no shadow.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Appearance)]
|
|
|
|
|
public int Elevation { set; get; } = 1;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Side from which the drawer will appear.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public Anchor Anchor { get; set; } = Anchor.Start;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The color of the component. It supports the theme colors.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Appearance)]
|
|
|
|
|
public ThemeColor Color { get; set; } = ThemeColor.Default;
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Variant of the drawer. It specifies how the drawer will be displayed.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public DrawerVariant Variant { get; set; } = DrawerVariant.Responsive;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Child content of component.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public RenderFragment ChildContent { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Show overlay for responsive and temporary drawers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public bool DisableOverlay { get; set; } = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Preserve open state for responsive drawer when window resized above <see cref="Breakpoint" />.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public bool PreserveOpenState { get; set; } = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Open drawer automatically on mouse enter when <see cref="Variant" /> parameter is set to <see cref="DrawerVariant.Mini" />.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public bool OpenMiniOnHover { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Specify how the drawer should behave inside a MudLayout. It affects the position relative to <b>MudAppbar</b>
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
public DrawerClipMode ClipMode
|
|
|
|
|
{
|
|
|
|
|
get => _clipMode;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (_clipMode == value)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_clipMode = value;
|
|
|
|
|
if (Fixed)
|
|
|
|
|
{
|
|
|
|
|
DrawerContainer?.FireDrawersChanged();
|
|
|
|
|
}
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool OverlayVisible => _open && !DisableOverlay &&
|
|
|
|
|
(Variant == DrawerVariant.Temporary ||
|
|
|
|
|
(_screenBreakpoint < Breakpoint && Variant == DrawerVariant.Mini) ||
|
|
|
|
|
(_screenBreakpoint < Breakpoint && Variant == DrawerVariant.Responsive));
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Switching point for responsive drawers
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public Breakpoint Breakpoint
|
|
|
|
|
{
|
|
|
|
|
get => _breakpoint;
|
|
|
|
@ -173,7 +389,6 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|
|
|
|
/// Sets the opened state on the drawer. Can be used with two-way binding to close itself on navigation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public bool Open
|
|
|
|
|
{
|
|
|
|
|
get => _open;
|
|
|
|
@ -192,121 +407,15 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|
|
|
|
{
|
|
|
|
|
_keepInitialState = false;
|
|
|
|
|
}
|
|
|
|
|
if (_isRendered && value && (Anchor == Anchor.Top || Anchor == Anchor.Bottom))
|
|
|
|
|
/*if (_isRendered && value && (Anchor == Anchor.Top || Anchor == Anchor.Bottom))
|
|
|
|
|
{
|
|
|
|
|
_ = UpdateHeight();
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
DrawerContainer?.FireDrawersChanged();
|
|
|
|
|
OpenChanged.InvokeAsync(_open);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Parameter] public EventCallback<bool> OpenChanged { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Width of left/right drawer. Only for non-fixed drawers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Appearance)]
|
|
|
|
|
public string Width { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Width of left/right drawer. Only for non-fixed drawers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Appearance)]
|
|
|
|
|
public string MiniWidth { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Height of top/bottom temporary drawer
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Appearance)]
|
|
|
|
|
public string Height { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Specify how the drawer should behave inside a MudLayout. It affects the position relative to <b>MudAppbar</b>
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Parameter]
|
|
|
|
|
[Category(CategoryTypes.Drawer.Behavior)]
|
|
|
|
|
public DrawerClipMode ClipMode
|
|
|
|
|
{
|
|
|
|
|
get => _clipMode;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (_clipMode == value)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_clipMode = value;
|
|
|
|
|
if (Fixed)
|
|
|
|
|
{
|
|
|
|
|
DrawerContainer?.FireDrawersChanged();
|
|
|
|
|
}
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
_screenBreakpoint = result.Breakpoint;
|
|
|
|
|
if (_screenBreakpoint < Breakpoint && _open)
|
|
|
|
|
{
|
|
|
|
|
_keepInitialState = true;
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_isRendered = true;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(Height) && (Anchor == Anchor.Bottom || Anchor == Anchor.Top))
|
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CloseDrawer()
|
|
|
|
|
{
|
|
|
|
|
if (Open)
|
|
|
|
@ -315,97 +424,7 @@ public partial class Drawer : UIComponent, IDisposable, INavigationEventReceiver
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task OnNavigation()
|
|
|
|
|
{
|
|
|
|
|
if (Variant == DrawerVariant.Temporary ||
|
|
|
|
|
(Variant == DrawerVariant.Responsive && await Breakpointistener.GetBreakpoint() < Breakpoint))
|
|
|
|
|
{
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ResizeListener_OnBreakpointChanged(object sender, Breakpoint breakpoint)
|
|
|
|
|
{
|
|
|
|
|
if (!_isRendered)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
InvokeAsync(() => UpdateBreakpointState(breakpoint));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task UpdateHeight()
|
|
|
|
|
{
|
|
|
|
|
_height = (await _contentRef.MudGetBoundingClientRectAsync())?.Height ?? 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void UpdateBreakpointState(Breakpoint breakpoint)
|
|
|
|
|
{
|
|
|
|
|
var isStateChanged = false;
|
|
|
|
|
if (breakpoint == Breakpoint.None)
|
|
|
|
|
{
|
|
|
|
|
breakpoint = await Breakpointistener.GetBreakpoint();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (breakpoint < Breakpoint && _screenBreakpoint >= Breakpoint && (Variant == DrawerVariant.Responsive || Variant == DrawerVariant.Mini))
|
|
|
|
|
{
|
|
|
|
|
_isOpenWhenLarge = Open;
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
else if (breakpoint >= Breakpoint && _screenBreakpoint < Breakpoint && (Variant == DrawerVariant.Responsive || Variant == DrawerVariant.Mini))
|
|
|
|
|
{
|
|
|
|
|
if (Open && PreserveOpenState)
|
|
|
|
|
{
|
|
|
|
|
DrawerContainer?.FireDrawersChanged();
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
else if (_isOpenWhenLarge != null)
|
|
|
|
|
{
|
|
|
|
|
await OpenChanged.InvokeAsync(_isOpenWhenLarge.Value);
|
|
|
|
|
_isOpenWhenLarge = null;
|
|
|
|
|
isStateChanged = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_screenBreakpoint = breakpoint;
|
|
|
|
|
if (isStateChanged)
|
|
|
|
|
{
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal string GetPosition()
|
|
|
|
|
{
|
|
|
|
|
switch (Anchor)
|
|
|
|
|
{
|
|
|
|
|
case Anchor.Start:
|
|
|
|
|
return RightToLeft ? "right" : "left";
|
|
|
|
|
case Anchor.End:
|
|
|
|
|
return RightToLeft ? "left" : "right";
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Anchor.ToDescription();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private bool closeOnMouseLeave = false;
|
|
|
|
|
|
|
|
|
|
public async void OnMouseEnter()
|
|
|
|
|
{
|
|
|
|
|
if (Variant == DrawerVariant.Mini && !Open && OpenMiniOnHover)
|
|
|
|
|
{
|
|
|
|
|
closeOnMouseLeave = true;
|
|
|
|
|
await OpenChanged.InvokeAsync(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async void OnMouseLeave()
|
|
|
|
|
{
|
|
|
|
|
if (Variant == DrawerVariant.Mini && Open && closeOnMouseLeave)
|
|
|
|
|
{
|
|
|
|
|
closeOnMouseLeave = false;
|
|
|
|
|
await OpenChanged.InvokeAsync(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|