using Connected.Annotations;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
namespace Connected.Components;
public partial class ScrollToTop : IDisposable
{
private IScrollListener _scrollListener;
protected string Classname =>
new CssBuilder("mud-scroll-to-top")
.AddClass("visible", Visible && string.IsNullOrWhiteSpace(VisibleCssClass))
.AddClass("hidden", !Visible && string.IsNullOrWhiteSpace(HiddenCssClass))
.AddClass(VisibleCssClass, Visible && !string.IsNullOrWhiteSpace(VisibleCssClass))
.AddClass(HiddenCssClass, !Visible && !string.IsNullOrWhiteSpace(HiddenCssClass))
.AddClass(Class)
.Build();
[Inject] IScrollListenerFactory ScrollListenerFactory { get; set; }
[Inject] IScrollManager ScrollManager { get; set; }
[Parameter]
[Category(CategoryTypes.ScrollToTop.Behavior)]
public RenderFragment ChildContent { get; set; }
///
/// The CSS selector to which the scroll event will be attached
///
[Parameter]
[Category(CategoryTypes.ScrollToTop.Behavior)]
public string Selector { get; set; }
///
/// If set to true, it starts Visible. If sets to false, it will become visible when the TopOffset amount of scrolled pixels is reached
///
[Parameter]
[Category(CategoryTypes.ScrollToTop.Behavior)]
public bool Visible { get; set; }
///
/// CSS class for the Visible state. Here, apply some transitions and animations that will happen when the component becomes visible
///
[Parameter]
[Category(CategoryTypes.ScrollToTop.Appearance)]
public string VisibleCssClass { get; set; }
///
/// CSS class for the Hidden state. Here, apply some transitions and animations that will happen when the component becomes invisible
///
[Parameter]
[Category(CategoryTypes.ScrollToTop.Appearance)]
public string HiddenCssClass { get; set; }
///
/// The distance in pixels scrolled from the top of the selected element from which
/// the component becomes visible
///
[Parameter]
[Category(CategoryTypes.ScrollToTop.Behavior)]
public int TopOffset { get; set; } = 300;
///
/// Smooth or Auto
///
[Parameter]
[Category(CategoryTypes.ScrollToTop.Behavior)]
public ScrollBehavior ScrollBehavior { get; set; } = ScrollBehavior.Smooth;
///
/// Called when scroll event is fired
///
[Parameter] public EventCallback OnScroll { get; set; }
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
var selector = !string.IsNullOrWhiteSpace(Selector)
? Selector
: null;// null is defaulted to document element in JS function
_scrollListener = ScrollListenerFactory.Create(selector);
//subscribe to event
_scrollListener.OnScroll += ScrollListener_OnScroll;
}
}
///
/// event received when scroll in the selected element happens
///
/// ScrollListener instance
/// Information about the position of the scrolled element
private async void ScrollListener_OnScroll(object sender, ScrollEventArgs e)
{
await OnScroll.InvokeAsync(e);
var topOffset = e.NodeName == "#document"
? e.FirstChildBoundingClientRect.Top * -1
: e.ScrollTop;
if (topOffset >= TopOffset && Visible != true)
{
Visible = true;
await InvokeAsync(() => StateHasChanged());
}
if (topOffset < TopOffset && Visible == true)
{
Visible = false;
await InvokeAsync(() => StateHasChanged());
}
}
///
/// Scrolls to top when clicked
///
private void OnClick()
{
ScrollManager.ScrollToTopAsync(_scrollListener.Selector, ScrollBehavior);
}
///
/// Remove the event
///
public void Dispose()
{
if (_scrollListener == null) { return; }
_scrollListener.OnScroll -= ScrollListener_OnScroll;
_scrollListener.Dispose();
}
}