\ No newline at end of file
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs
index 8075bf413b..48f83584e7 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.razor.cs
@@ -1,6 +1,6 @@
namespace Bit.BlazorUI;
-public partial class BitDropMenu : BitComponentBase
+public partial class BitDropMenu : BitComponentBase, IAsyncDisposable
{
private bool _disposed;
private string _calloutId = default!;
@@ -82,13 +82,38 @@ public partial class BitDropMenu : BitComponentBase
[JSInvokable("CloseCallout")]
- public async Task __CloseCalloutBeforeAnotherCalloutIsOpened()
+ public async Task _CloseCalloutBeforeAnotherCalloutIsOpened()
{
await DismissCallout();
StateHasChanged();
}
+ [JSInvokable("OnStart")]
+ public async Task _OnStart(decimal startX, decimal startY)
+ {
+
+ }
+
+ [JSInvokable("OnMove")]
+ public async Task _OnMove(decimal diffX, decimal diffY)
+ {
+
+ }
+
+ [JSInvokable("OnEnd")]
+ public async Task _OnEnd(decimal diffX, decimal diffY)
+ {
+
+ }
+
+ [JSInvokable("OnClose")]
+ public async Task _OnClose()
+ {
+ await CloseCallout();
+ await InvokeAsync(StateHasChanged);
+ }
+
protected override string RootElementClass => "bit-drm";
@@ -109,13 +134,23 @@ protected override void RegisterCssStyles()
StyleBuilder.Register(() => IsOpen ? Styles?.Opened : string.Empty);
}
- protected override async Task OnInitializedAsync()
+ protected override void OnInitialized()
{
_dotnetObj = DotNetObjectReference.Create(this);
_calloutId = $"BitDropMenu-{UniqueId}-callout";
- await base.OnInitializedAsync();
+ base.OnInitialized();
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ await base.OnAfterRenderAsync(firstRender);
+
+ if (firstRender is false) return;
+ if (Responsive is false) return;
+
+ await _js.SwipesSetup(_calloutId, 0.25m, BitPanelPosition.End, Dir is BitDir.Rtl, _dotnetObj);
}
@@ -160,8 +195,7 @@ await _js.ToggleCallout(_dotnetObj,
0,
"",
"",
- false,
- RootElementClass);
+ false);
}
private async Task DismissCallout()
@@ -170,4 +204,43 @@ private async Task DismissCallout()
await OnDismiss.InvokeAsync();
}
+
+ private string GetCalloutCssClasses()
+ {
+ List
classes = ["bit-drm-cal"];
+
+ if (Classes?.Callout is not null)
+ {
+ classes.Add(Classes.Callout);
+ }
+
+ if (Responsive)
+ {
+ classes.Add("bit-drm-res");
+ }
+
+ return string.Join(' ', classes).Trim();
+ }
+
+
+
+ public async ValueTask DisposeAsync()
+ {
+ await DisposeAsync(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual async ValueTask DisposeAsync(bool disposing)
+ {
+ if (_disposed || disposing is false) return;
+
+ try
+ {
+ await _js.ClearCallout(_calloutId);
+ await _js.SwipesDispose(_calloutId);
+ }
+ catch (JSDisconnectedException) { } // we can ignore this exception here
+
+ _disposed = true;
+ }
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss b/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
index 9858b24068..3a29f0210c 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
@@ -1,4 +1,5 @@
@import "../../../Styles/functions.scss";
+@import "../../../Styles/media-queries.scss";
.bit-drm {
width: fit-content;
@@ -26,12 +27,6 @@
cursor: default;
}
}
-
- &.bit-rtl {
- .bit-drm-rsp {
- animation-name: bit-fade-show, bit-drp-trans-x-reverse;
- }
- }
}
.bit-drm-btn {
@@ -86,9 +81,28 @@
animation-timing-function: cubic-bezier(0.1, 0.9, 0.2, 1);
}
-.bit-drm-rsp {
- height: 100%;
- max-height: unset;
- box-shadow: $box-shadow-callout;
- animation-name: bit-fade-show, bit-drp-trans-x;
+.bit-drm-res {
+ @include lt-sm {
+ top: 0;
+ right: 0;
+ opacity: 0;
+ height: 100%;
+ display: block;
+ overflow: hidden;
+ max-height: unset;
+ animation-name: unset;
+ transform: translateX(100%);
+ box-shadow: $box-shadow-callout;
+ transition: transform 200ms ease-out, opacity 100ms linear;
+ }
+}
+
+.bit-rtl {
+ .bit-drm-res {
+ @include lt-sm {
+ left: 0;
+ right: unset;
+ transform: translateX(-100%);
+ }
+ }
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor
index b92b9bee92..5e8a3e956e 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor
@@ -18,9 +18,10 @@
- @foreach (var item in _items)
+ @foreach (var (item, idx) in _items.Select((item, idx) => (item, idx)))
{
- <_BitNavChild @key="GetItemKey(item)" Item="item" Depth="0" />
+ var key = GetItemKey(item, idx.ToString());
+ <_BitNavChild @key="@key" Key="@key" Item="item" Depth="0" />
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs
index 54d8959693..70ca783961 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/BitNav.razor.cs
@@ -688,6 +688,11 @@ internal BitNavItemTemplateRenderMode GetTemplateRenderMode(TItem item)
return item.GetValueFromProperty?>(NameSelectors.AdditionalUrls.Name);
}
+ internal string GetItemKey(TItem item, string defaultKey)
+ {
+ return GetKey(item) ?? $"{UniqueId}-{defaultKey}";
+ }
+
internal void SetItemExpanded(TItem item, bool value)
@@ -748,26 +753,6 @@ internal void UnregisterOption(BitNavOption option)
StateHasChanged();
}
- internal string GetItemKey(TItem item)
- {
- return GetKey(item) ?? Guid.NewGuid().ToString();
- }
-
- private bool ToggleItemAndParents(IList items, TItem item, bool isExpanded)
- {
- foreach (var parent in items)
- {
- var childItems = GetChildItems(parent);
- if (parent == item || (childItems.Any() && ToggleItemAndParents(childItems, item, isExpanded)))
- {
- SetItemExpanded(parent, isExpanded);
- return true;
- }
- }
-
- return false;
- }
-
protected override string RootElementClass => "bit-nav";
@@ -932,6 +917,21 @@ private void OnSetParameters()
_oldItems = Items;
}
+ private bool ToggleItemAndParents(IList items, TItem item, bool isExpanded)
+ {
+ foreach (var parent in items)
+ {
+ var childItems = GetChildItems(parent);
+ if (parent == item || (childItems.Any() && ToggleItemAndParents(childItems, item, isExpanded)))
+ {
+ SetItemExpanded(parent, isExpanded);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public void Dispose()
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor
index 5d74330a8d..4c2cf940fd 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor
@@ -19,8 +19,8 @@
var target = Nav.GetTarget(Item);
var renderLink = url.HasValue() || Nav.GetForceAnchor(Item);
var href = (isEnabled && (Nav.SelectedItem != Item || Nav.Reselectable)) ? url : null;
- var itemKey = Nav.GetItemKey(Item);
}
+
@if (Nav.RenderType is BitNavRenderType.Grouped && Parent is null)
{
@if (isSeparator)
@@ -118,7 +118,7 @@
{
<_BitNavItemContainer Href="@href"
Target="@target"
- OnClick="HandleOnClick"
+ OnClick="() => HandleOnClick(renderLink)"
RenderLink="renderLink"
Disabled="@(isEnabled is false)"
AriaLabel="@Nav.GetAriaLabel(Item)"
@@ -180,9 +180,10 @@
{
- @foreach (var item in childItems)
+ @foreach (var (item, idx) in childItems.Select((item, idx) => (item, idx)))
{
- <_BitNavChild @key="Nav.GetItemKey(item)" Item="item" Depth="Depth + 1" />
+ var key = Nav.GetItemKey(item, $"{Key}-{idx}");
+ <_BitNavChild @key="@key" Key="@key" Item="item" Depth="Depth + 1" />
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor.cs
index 71e43381aa..cd2271d7ab 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Nav/_BitNavChild.razor.cs
@@ -2,7 +2,7 @@
namespace Bit.BlazorUI;
-public partial class _BitNavChild : ComponentBase where TItem : class
+public partial class _BitNavChild where TItem : class
{
[CascadingParameter] protected BitNav Nav { get; set; } = default!;
@@ -12,11 +12,13 @@ public partial class _BitNavChild : ComponentBase where TItem : class
[Parameter] public TItem Item { get; set; } = default!;
+ [Parameter] public string? Key { get; set; }
+
[Parameter] public int Depth { get; set; }
- private async Task HandleOnClick()
+ private async Task HandleOnClick(bool renderLink)
{
if (Nav is null) return;
if (Nav.GetIsEnabled(Item) is false) return;
@@ -32,6 +34,10 @@ private async Task HandleOnClick()
if (Nav.SelectedItem != Item || Nav.Reselectable)
{
+ if (renderLink)
+ {
+ await Task.Yield(); // wait for the link to navigate first
+ }
await Nav.OnItemClick.InvokeAsync(Item);
}
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor b/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor
index 4d7f294cb6..5eee9d83fa 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor
@@ -15,7 +15,7 @@
- @foreach (var item in _items)
+ @foreach (var (item, idx) in _items.Select((item, idx) => (item, idx)))
{
var itm = item;
var url = GetUrl(item);
@@ -23,7 +23,8 @@
var isEnabled = GetIsEnabled(item);
var href = (isEnabled && (SelectedItem != itm || Reselectable)) ? url : null;
- <_BitNavBarChild Href="@href"
+ <_BitNavBarChild @key="@GetItemKey(item, idx.ToString())"
+ Href="@href"
Title="@GetTitle(item)"
Target="@GetTarget(item)"
Style="@GetItemCssStyle(item)"
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs
index edf68f0816..d75894e18f 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.razor.cs
@@ -243,9 +243,9 @@ private async Task SetSelectedItem(TItem item)
StateHasChanged();
}
- private string GetItemKey(TItem item)
+ private string GetItemKey(TItem item, string defaultKey)
{
- return GetKey(item) ?? Guid.NewGuid().ToString();
+ return GetKey(item) ?? $"{UniqueId}-{defaultKey}";
}
private async Task HandleOnClick(TItem item)
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
index 45aaba6ff9..be21d2f680 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
@@ -27,6 +27,11 @@
--bit-pgn-clr-btn-sel-bg-active: var(--bit-pgn-clr-sel-active);
--bit-pgn-clr-btn-sel-brd-active: var(--bit-pgn-clr-sel-active);
+ &.bit-rtl {
+ --bit-pgn-ico-transform-end: scaleX(-1);
+ --bit-pgn-ico-transform-start: scaleX(1);
+ }
+
&.bit-dis {
cursor: default;
color: $clr-fg-dis;
@@ -42,11 +47,6 @@
transform: var(--bit-pgn-ico-transform-end);
}
-.bit-rtl {
- --bit-pgn-ico-transform-end: scaleX(-1);
- --bit-pgn-ico-transform-start: scaleX(1);
-}
-
.bit-pgn-elp {
display: flex;
font-size: inherit;
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/Base/BitLoadingBase.cs b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/Base/BitLoadingBase.cs
index 4b537a8604..5b774859de 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/Base/BitLoadingBase.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/Base/BitLoadingBase.cs
@@ -2,6 +2,9 @@
namespace Bit.BlazorUI;
+///
+/// The original loading css came from https://loading.io/css/
+///
public abstract class BitLoadingBase : BitComponentBase
{
///
@@ -108,6 +111,12 @@ public override Task SetParametersAsync(ParameterView parameters)
+ internal new ElementClassBuilder ClassBuilder => base.ClassBuilder;
+
+ internal new ElementStyleBuilder StyleBuilder => base.StyleBuilder;
+
+
+
protected override void RegisterCssClasses()
{
ClassBuilder.Register(() => "bit-ldn");
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.razor.cs
index 8b2ea09005..d5fe1e3142 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.razor.cs
@@ -9,6 +9,7 @@ protected override void RegisterCssStyles()
base.RegisterCssStyles();
StyleBuilder.Register(() => $"--bit-ldn-hrt-24:{Convert(24)}px");
+ StyleBuilder.Register(() => $"--bit-ldn-hrt-28:{Convert(28)}px");
StyleBuilder.Register(() => $"--bit-ldn-hrt-32:{Convert(32)}px");
StyleBuilder.Register(() => $"--bit-ldn-hrt-40:{Convert(40)}px");
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.scss b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.scss
index 102012f62f..4771a20635 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.scss
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitHeartLoading.scss
@@ -12,8 +12,8 @@
.bit-ldn-hrt-chl {
position: absolute;
- top: var(--bit-ldn-hrt-32);
- left: var(--bit-ldn-hrt-32);
+ top: var(--bit-ldn-hrt-28);
+ left: var(--bit-ldn-hrt-28);
width: var(--bit-ldn-hrt-32);
height: var(--bit-ldn-hrt-32);
background: var(--bit-ldn-color);
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.razor.cs
index 30a799451e..36fc6c7a69 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.razor.cs
@@ -9,7 +9,8 @@ protected override void RegisterCssStyles()
base.RegisterCssStyles();
StyleBuilder.Register(() => $"--bit-ldn-rpl-4:{Convert(4)}px");
+ StyleBuilder.Register(() => $"--bit-ldn-rpl-8:{Convert(8)}px");
StyleBuilder.Register(() => $"--bit-ldn-rpl-36:{Convert(36)}px");
- StyleBuilder.Register(() => $"--bit-ldn-rpl-72:{Convert(72)}px");
+ StyleBuilder.Register(() => $"--bit-ldn-rpl-80:{Convert(80)}px");
}
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.scss b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.scss
index ae9eef883b..1726515222 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.scss
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRippleLoading.scss
@@ -22,34 +22,34 @@
@keyframes bit-ldn-rpl-anm {
0% {
- width: 0;
- height: 0;
opacity: 0;
top: var(--bit-ldn-rpl-36);
left: var(--bit-ldn-rpl-36);
+ width: var(--bit-ldn-rpl-8);
+ height: var(--bit-ldn-rpl-8);
}
4.9% {
- width: 0;
- height: 0;
opacity: 0;
top: var(--bit-ldn-rpl-36);
left: var(--bit-ldn-rpl-36);
+ width: var(--bit-ldn-rpl-8);
+ height: var(--bit-ldn-rpl-8);
}
5% {
- width: 0;
- height: 0;
opacity: 1;
top: var(--bit-ldn-rpl-36);
left: var(--bit-ldn-rpl-36);
+ width: var(--bit-ldn-rpl-8);
+ height: var(--bit-ldn-rpl-8);
}
100% {
top: 0px;
left: 0px;
opacity: 0;
- width: var(--bit-ldn-rpl-72);
- height: var(--bit-ldn-rpl-72);
+ width: var(--bit-ldn-rpl-80);
+ height: var(--bit-ldn-rpl-80);
}
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.razor.cs
index b9a66ce283..c69cdeb7e9 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.razor.cs
@@ -9,7 +9,7 @@ protected override void RegisterCssStyles()
base.RegisterCssStyles();
StyleBuilder.Register(() => $"--bit-ldn-rol-4:{Convert(4)}px");
- StyleBuilder.Register(() => $"--bit-ldn-rol-7:{Convert(7)}px");
+ StyleBuilder.Register(() => $"--bit-ldn-rol-8:{Convert(8)}px");
StyleBuilder.Register(() => $"--bit-ldn-rol-12:{Convert(12)}px");
StyleBuilder.Register(() => $"--bit-ldn-rol-17:{Convert(17)}px");
StyleBuilder.Register(() => $"--bit-ldn-rol-24:{Convert(24)}px");
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.scss b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.scss
index 5faf8c0904..c137a74c76 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.scss
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Progress/Loading/BitRollerLoading.scss
@@ -18,8 +18,8 @@
display: block;
position: absolute;
border-radius: 50%;
- width: var(--bit-ldn-rol-7);
- height: var(--bit-ldn-rol-7);
+ width: var(--bit-ldn-rol-8);
+ height: var(--bit-ldn-rol-8);
background: var(--bit-ldn-color);
margin: calc(-1 * var(--bit-ldn-rol-4)) 0 0 calc(-1 * var(--bit-ldn-rol-4));
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs
index 138eeffd19..3322053a1d 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Callout/BitCallout.razor.cs
@@ -158,8 +158,7 @@ await _js.ToggleCallout(_dotnetObj,
0,
"",
"",
- false,
- RootElementClass);
+ false);
await OnToggle.InvokeAsync(IsOpen);
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor
index db17013e2e..cd189aa5fb 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor
@@ -1,57 +1,24 @@
@namespace Bit.BlazorUI
@inherits BitComponentBase
-@if (IsOpen)
-{
-
- @if (IsModeless is false)
- {
-
- }
-
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs
index cc138f461e..6f6863e164 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.razor.cs
@@ -1,8 +1,9 @@
namespace Bit.BlazorUI;
-public partial class BitPanel : BitComponentBase
+public partial class BitPanel : BitComponentBase, IAsyncDisposable
{
private int _offsetTop;
+ private bool _disposed;
private bool _internalIsOpen;
private string _containerId = default!;
@@ -13,90 +14,80 @@ public partial class BitPanel : BitComponentBase
///
- /// Enables the auto scrollbar toggle behavior of the Panel.
+ /// Enables the auto scrollbar toggle behavior of the panel.
///
[Parameter] public bool AutoToggleScroll { get; set; }
///
- /// The content of the Panel, it can be any custom tag or text.
+ /// Whether the panel can be dismissed by clicking outside of it on the overlay.
///
- [Parameter] public RenderFragment? ChildContent { get; set; }
+ [Parameter] public bool Blocking { get; set; }
///
- /// Custom CSS classes for different parts of the BitPanel component.
+ /// The content of the panel.
///
- [Parameter] public BitPanelClassStyles? Classes { get; set; }
+ [Parameter] public RenderFragment? ChildContent { get; set; }
///
- /// Used to customize how the footer inside the Panel is rendered.
+ /// Custom CSS classes for different parts of the panel.
///
- [Parameter] public RenderFragment? FooterTemplate { get; set; }
+ [Parameter] public BitPanelClassStyles? Classes { get; set; }
///
- /// Used to customize how the header inside the Panel is rendered.
+ /// Determines the openness of the panel.
///
- [Parameter] public RenderFragment? HeaderTemplate { get; set; }
+ [Parameter, TwoWayBound]
+ public bool IsOpen { get; set; }
///
- /// Header text of Panel.
+ /// Removes the overlay element of the panel.
///
- [Parameter] public string? HeaderText { get; set; }
+ [Parameter] public bool Modeless { get; set; }
///
- /// Whether the Panel can be light dismissed by clicking outside the Panel (on the overlay).
+ /// A callback function for when the Panel is dismissed.
///
- [Parameter] public bool IsBlocking { get; set; }
+ [Parameter] public EventCallback
OnDismiss { get; set; }
///
- /// Whether the Panel should be modeless (e.g. not dismiss when focusing/clicking outside of the Panel). if true: IsBlocking is ignored, there will be no overlay.
+ /// The event callback for when the swipe action starts on the container of the panel.
///
- [Parameter] public bool IsModeless { get; set; }
+ [Parameter] public EventCallback OnSwipeStart { get; set; }
///
- /// Whether the Panel is displayed.
+ /// The event callback for when the swipe action moves on the container of the panel.
///
- [Parameter, TwoWayBound]
- public bool IsOpen { get; set; }
+ [Parameter] public EventCallback OnSwipeMove { get; set; }
///
- /// A callback function for when the Panel is dismissed light dismiss, before the animation completes.
+ /// The event callback for when the swipe action ends on the container of the panel.
///
- [Parameter] public EventCallback OnDismiss { get; set; }
+ [Parameter] public EventCallback OnSwipeEnd { get; set; }
///
- /// Position of the modal on the screen.
+ /// The position of the panel to show on the screen.
///
- [Parameter] public BitPanelPosition Position { get; set; } = BitPanelPosition.Right;
+ [Parameter] public BitPanelPosition? Position { get; set; }
///
- /// Provides Height or Width for the Panel.
+ /// The value of the height or width (based on the position) of the Panel.
///
- [Parameter] public double Size { get; set; }
+ [Parameter] public double? Size { get; set; }
///
- /// Set the element selector for which the Panel disables its scroll if applicable.
+ /// Specifies the element selector for which the Panel disables its scroll if applicable.
///
- [Parameter] public string ScrollerSelector { get; set; } = "body";
+ [Parameter] public string? ScrollerSelector { get; set; }
///
- /// Shows or hides the close button of the Panel.
- ///
- [Parameter] public bool ShowCloseButton { get; set; } = true;
-
- ///
- /// Custom CSS styles for different parts of the BitPanel component.
+ /// Custom CSS styles for different parts of the panel component.
///
[Parameter] public BitPanelClassStyles? Styles { get; set; }
///
- /// ARIA id for the subtitle of the Panel, if any.
- ///
- [Parameter] public string? SubtitleAriaId { get; set; }
-
- ///
- /// ARIA id for the title of the Panel, if any.
+ /// The swiping point (difference percentage) based on the width of the panel container to trigger the close action (default is 0.25m).
///
- [Parameter] public string? TitleAriaId { get; set; }
+ [Parameter] public decimal? SwipeTrigger { get; set; }
@@ -116,6 +107,36 @@ public async Task Close()
+ [JSInvokable("OnStart")]
+ public async Task _OnStart(decimal startX, decimal startY)
+ {
+ var start = (Position == BitPanelPosition.Start || Position == BitPanelPosition.End) ? startX : startY;
+ await OnSwipeStart.InvokeAsync(start);
+ }
+
+ [JSInvokable("OnMove")]
+ public async Task _OnMove(decimal diffX, decimal diffY)
+ {
+ var diff = (Position == BitPanelPosition.Start || Position == BitPanelPosition.End) ? diffX : diffY;
+ await OnSwipeMove.InvokeAsync(diff);
+ }
+
+ [JSInvokable("OnEnd")]
+ public async Task _OnEnd(decimal diffX, decimal diffY)
+ {
+ var diff = (Position == BitPanelPosition.Start || Position == BitPanelPosition.End) ? diffX : diffY;
+ await OnSwipeEnd.InvokeAsync(diff);
+ }
+
+ [JSInvokable("OnClose")]
+ public async Task _OnClose()
+ {
+ await ClosePanel(new());
+ await InvokeAsync(StateHasChanged);
+ }
+
+
+
protected override string RootElementClass => "bit-pnl";
protected override void RegisterCssClasses()
@@ -141,6 +162,12 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
+ if (firstRender)
+ {
+ var dotnetObj = DotNetObjectReference.Create(this);
+ await _js.SwipesSetup(_containerId, SwipeTrigger ?? 0.25m, Position ?? BitPanelPosition.End, Dir == BitDir.Rtl, dotnetObj, false);
+ }
+
if (_internalIsOpen == IsOpen) return;
_internalIsOpen = IsOpen;
@@ -149,7 +176,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
if (AutoToggleScroll is false) return;
- _offsetTop = await _js.ToggleOverflow(ScrollerSelector, IsOpen);
+ _offsetTop = await _js.ToggleOverflow(ScrollerSelector ?? "body", IsOpen);
StyleBuilder.Reset();
StateHasChanged();
@@ -168,31 +195,73 @@ private async Task ClosePanel(MouseEventArgs e)
private async Task OnOverlayClicked(MouseEventArgs e)
{
- if (IsBlocking is not false) return;
+ if (Blocking is true) return;
await ClosePanel(e);
}
- private async Task OnCloseButtonClicked(MouseEventArgs e)
+ private string GetContainerCssStyles()
{
- await ClosePanel(e);
+ List styles = [];
+
+ if (IsOpen)
+ {
+ styles.Add("transform:translate3d(0,0,0);opacity:1");
+ }
+
+ if (Size is not null)
+ {
+ var prop = Position is BitPanelPosition.Top or BitPanelPosition.Bottom ? "height" : "width";
+ styles.Add(FormattableString.Invariant($"{prop}:{Size}px"));
+ }
+
+ if (Styles?.Container is string containerStyle && containerStyle.HasValue())
+ {
+ styles.Add(containerStyle);
+ }
+
+ return string.Join(';', styles);
+ }
+
+ private string GetContainerCssClasses()
+ {
+ List classes = ["bit-pnl-cnt"];
+
+ classes.Add(Position switch
+ {
+ BitPanelPosition.Start => "bit-pnl-start",
+ BitPanelPosition.End => "bit-pnl-end",
+ BitPanelPosition.Top => "bit-pnl-top",
+ BitPanelPosition.Bottom => "bit-pnl-bottom",
+ _ => "bit-pnl-end"
+ });
+
+ if (Classes?.Container is string containerClass && containerClass.HasValue())
+ {
+ classes.Add(containerClass);
+ }
+
+ return string.Join(' ', classes);
}
- private string GetPositionClass() => Position switch
+
+
+ public async ValueTask DisposeAsync()
{
- BitPanelPosition.Right => "bit-pnl-right",
- BitPanelPosition.Left => "bit-pnl-left",
- BitPanelPosition.Top => "bit-pnl-top",
- BitPanelPosition.Bottom => "bit-pnl-bottom",
- _ => "bit-pnl-right"
- };
+ await DisposeAsync(true);
+ GC.SuppressFinalize(this);
+ }
- private string GetPanelSizeStyle()
+ protected virtual async ValueTask DisposeAsync(bool disposing)
{
- if (Size == 0) return string.Empty;
+ if (_disposed || disposing is false) return;
- var style = Position is BitPanelPosition.Top or BitPanelPosition.Bottom ? "height" : "width";
+ try
+ {
+ await _js.SwipesDispose(_containerId);
+ }
+ catch (JSDisconnectedException) { } // we can ignore this exception here
- return FormattableString.Invariant($"{style}:{Size}px");
+ _disposed = true;
}
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.scss b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.scss
index 917ed70158..a8a70f87d7 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.scss
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanel.scss
@@ -1,206 +1,72 @@
@import "../../../Styles/functions.scss";
.bit-pnl {
- inset: 0;
- width: 100%;
- height: 100%;
- display: flex;
font-weight: 400;
font-size: spacing(2);
z-index: $zindex-modal;
font-family: $tg-font-family;
+ --bit-pnl-transform-factor: 1;
- @keyframes bit-pnl-trans-x {
- 0% {
- pointer-events: none;
- transform: translate3d(spacing(5), 0px, 0px);
- }
-
- 100% {
- pointer-events: auto;
- transform: translate3d(0px, 0px, 0px);
- }
- }
-
- @keyframes bit-pnl-trans-y {
- 0% {
- pointer-events: none;
- transform: translate3d(0px, spacing(5), 0px);
- }
-
- 100% {
- pointer-events: auto;
- transform: translate3d(0px, 0px, 0px);
- }
- }
-
- @keyframes bit-pnl-trans-x-reverse {
- 0% {
- pointer-events: none;
- transform: translate3d(spacing(-5), 0px, 0px);
- }
-
- 100% {
- pointer-events: auto;
- transform: translate3d(0px, 0px, 0px);
- }
- }
-
- @keyframes bit-pnl-trans-y-reverse {
- 0% {
- pointer-events: none;
- transform: translate3d(0px, spacing(-5), 0px);
- }
-
- 100% {
- pointer-events: auto;
- transform: translate3d(0px, 0px, 0px);
- }
+ &.bit-rtl {
+ --bit-pnl-transform-factor: -1;
}
}
.bit-pnl-ovl {
- top: 0;
- left: 0;
+ inset: 0;
width: 100%;
height: 100%;
- cursor: pointer;
position: fixed;
- pointer-events: auto;
z-index: $zindex-overlay;
- background: $clr-bg-overlay;
}
.bit-pnl-cnt {
- top: 0;
- height: 100%;
- flex-grow: 1;
- display: flex;
- outline: none;
- overflow: auto;
+ opacity: 0;
position: fixed;
- max-width: 100%;
- max-height: 100%;
box-sizing: border-box;
- flex-direction: column;
z-index: $zindex-callout;
- animation-fill-mode: both;
- animation-duration: 0.367s;
- box-shadow: $box-shadow-callout;
- animation-name: opacity, bit-pnl-trans-x;
- background-color: $clr-bg-pri;
- border-radius: 0 0 spacing(0.25) spacing(0.25);
-}
-
-.bit-pnl-hcn {
- top: 0;
- z-index: 1;
- display: flex;
- position: sticky;
- font-weight: 600;
- align-items: center;
- font-size: spacing(2.5);
- overflow-wrap: anywhere;
- color: $clr-fg-pri;
- padding: spacing(2.25) spacing(3) 0;
- background-color: $clr-bg-pri;
-}
-
-.bit-pnl-ttl {
- width: 100%;
- hyphens: auto;
- word-break: break-word;
- overflow-wrap: break-word;
-}
-
-.bit-pnl-cls {
- border: none;
- display: flex;
- cursor: pointer;
- font-weight: 400;
- width: spacing(4);
- margin-left: auto;
- height: spacing(4);
- align-self: normal;
- text-align: center;
- align-items: center;
- text-decoration: none;
- box-sizing: border-box;
- padding: 0 spacing(0.5);
- justify-content: center;
- font-size: spacing(1.75);
- border-radius: spacing(0.25);
- background-color: transparent;
- color: $clr-fg-pri;
-
- span {
- height: 100%;
- display: flex;
- flex-wrap: nowrap;
- align-items: center;
- justify-content: center;
-
- i {
- margin: 0 spacing(0.5);
- }
- }
-
- @media (hover: hover) {
- &:hover {
- color: $clr-fg-pri-hover;
- background-color: $clr-bg-pri-hover;
- }
- }
-
- &:active {
- color: $clr-fg-pri-active;
- background-color: $clr-bg-pri-active;
- }
-}
-
-.bit-pnl-bdy {
- flex-grow: 1;
- overflow-y: auto;
- padding-left: spacing(3);
- padding-right: spacing(3);
- padding-bottom: spacing(2.5);
-}
-
-.bit-pnl-fcn {
- bottom: 0;
- z-index: 1;
- position: sticky;
- padding: spacing(2) spacing(3);
background-color: $clr-bg-pri;
+ box-shadow: $box-shadow-callout;
+ transition: transform 200ms ease-out, opacity 100ms ease-in;
}
-.bit-pnl-right {
- right: 0;
- width: spacing(40);
- animation-name: opacity, bit-pnl-trans-x;
+.bit-pnl-start {
+ height: 100%;
+ max-width: 85%;
+ inset-block: 0;
+ max-height: 100%;
+ width: fit-content;
+ inset-inline-start: 0;
+ transform: translateX(calc(var(--bit-pnl-transform-factor) * -100%));
}
-.bit-pnl-left {
- left: 0;
- width: spacing(40);
- animation-name: opacity, bit-pnl-trans-x-reverse;
+.bit-pnl-end {
+ height: 100%;
+ max-width: 85%;
+ inset-block: 0;
+ max-height: 100%;
+ width: fit-content;
+ inset-inline-end: 0;
+ transform: translateX(calc(var(--bit-pnl-transform-factor) * 100%));
}
.bit-pnl-top {
top: 0;
- left: 0;
- right: 0;
width: 100%;
- height: spacing(40);
- animation-name: opacity, bit-pnl-trans-y-reverse;
+ max-width: 100%;
+ max-height: 85%;
+ inset-inline: 0;
+ height: fit-content;
+ transform: translateY(-100%);
}
.bit-pnl-bottom {
- left: 0;
- right: 0;
bottom: 0;
top: unset;
width: 100%;
- height: spacing(40);
- animation-name: opacity, bit-pnl-trans-y;
+ max-width: 100%;
+ max-height: 85%;
+ inset-inline: 0;
+ height: fit-content;
+ transform: translateY(100%);
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanelClassStyles.cs b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanelClassStyles.cs
index 97b134b402..270ae80e35 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanelClassStyles.cs
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Surfaces/Panel/BitPanelClassStyles.cs
@@ -16,34 +16,4 @@ public class BitPanelClassStyles
/// Custom CSS classes/styles for the container of the BitPanel.
///
public string? Container { get; set; }
-
- ///
- /// Custom CSS classes/styles for the header of the BitPanel.
- ///
- public string? Header { get; set; }
-
- ///
- /// Custom CSS classes/styles for the header text of the BitPanel.
- ///
- public string? HeaderText { get; set; }
-
- ///
- /// Custom CSS classes/styles for the close button of the BitPanel.
- ///
- public string? CloseButton { get; set; }
-
- ///
- /// Custom CSS classes/styles for the close button of the BitPanel.
- ///
- public string? CloseIcon { get; set; }
-
- ///
- /// Custom CSS classes/styles for the body of the BitPanel.
- ///
- public string? Body { get; set; }
-
- ///
- /// Custom CSS classes/styles for the footer of the BitPanel.
- ///
- public string? Footer { get; set; }
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/PullToRefresh/BitPullToRefresh.razor b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/PullToRefresh/BitPullToRefresh.razor
index 09028e60d8..308120e6fd 100644
--- a/src/BlazorUI/Bit.BlazorUI/Components/Utilities/PullToRefresh/BitPullToRefresh.razor
+++ b/src/BlazorUI/Bit.BlazorUI/Components/Utilities/PullToRefresh/BitPullToRefresh.razor
@@ -9,22 +9,20 @@
@(Anchor ?? ChildContent)
- @{
- var wrpSize = (35 * _diff) / Trigger;
- var svgSize = (24 * _diff) / Trigger;
- }
-
-
-
-
+
+
+
@if (Loading is not null)
{
@Loading
}
else
{
-