Skip to content

Commit

Permalink
feat(Split): add OnResizeAsync parameter (#4177)
Browse files Browse the repository at this point in the history
* feat: 增加 OnResizedAsync 回调方法

* feat: 增加 SplitterResizedEventArgs 类

* doc: 增加 OnResizeAsync 示例

* refactor: 增加 SplitsOnResizedAsync 文档

* doc: 增加折叠按钮文档

* refactor: 增加 IsCollapsible 参数动态支持

* test: 更新单元测试

* refactor: 重构方法名

* chore: bump version 8.8.5-beta06
  • Loading branch information
ArgoZhang authored Aug 29, 2024
1 parent ca28669 commit 09d53ff
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 63 deletions.
19 changes: 15 additions & 4 deletions src/BootstrapBlazor.Server/Components/Samples/Splits.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@
<DemoBlock Title="@Localizer["SplitsNormalTitle"]"
Introduction="@Localizer["SplitsNormalIntro"]"
Name="Normal">
<section ignore class="d-flex align-items-center">
<Switch Value="_showBarHandle" OnValueChanged="OnShowBarHandle" class="w-auto"></Switch>
<div class="ms-3">@_barHandleText</div>
<section ignore class="row">
<div class="col-12 col-sm-6">
<div class="d-flex align-items-center">
<Switch Value="_showBarHandle" OnValueChanged="OnShowBarHandle" class="w-auto"></Switch>
<div class="ms-3">@_barHandleText</div>
</div>
</div>
<div class="col-12 col-sm-6">
<div class="d-flex align-items-center">
<Switch Value="_isCollapsible" OnValueChanged="OnCollapsible" class="w-auto"></Switch>
<div class="ms-3">@_collapsibleText</div>
</div>
</div>
</section>
<div class="border split-demo split-demo-horizontal">
<Split ShowBarHandle="_showBarHandle">
<Split ShowBarHandle="_showBarHandle" OnResizedAsync="OnResizedAsync" IsCollapsible="_isCollapsible">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel1"]</div>
</FirstPaneTemplate>
Expand All @@ -20,6 +30,7 @@
</SecondPaneTemplate>
</Split>
</div>
<ConsoleLogger @ref="_logger"></ConsoleLogger>
</DemoBlock>

<DemoBlock Title="@Localizer["SplitsPercentTitle"]"
Expand Down
29 changes: 29 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/Splits.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,22 @@ public sealed partial class Splits
{
private bool _showBarHandle = true;

private bool _isCollapsible = false;

private string? _barHandleText;

private string? _collapsibleText;

private ConsoleLogger _logger = default!;

/// <summary>
/// <inheritdoc/>
/// </summary>
protected override void OnParametersSet()
{
base.OnParametersSet();
_barHandleText = _showBarHandle ? Localizer["SplitsBarHandleShow"] : Localizer["SplitsBarHandleHide"];
_collapsibleText = _showBarHandle ? Localizer["SplitsCollapsibleTrue"] : Localizer["SplitsCollapsibleFalse"];
}

private Task OnShowBarHandle(bool v)
Expand All @@ -30,6 +37,20 @@ private Task OnShowBarHandle(bool v)
return Task.CompletedTask;
}

private Task OnCollapsible(bool v)
{
_isCollapsible = v;
_collapsibleText = _showBarHandle ? Localizer["SplitsCollapsibleTrue"] : Localizer["SplitsCollapsibleFalse"];
StateHasChanged();
return Task.CompletedTask;
}

private Task OnResizedAsync(SplitterResizedEventArgs args)
{
_logger.Log($"FirstPanelSize: {args.FirstPanelSize} IsCollapsed: {args.IsCollapsed} IsExpanded: {args.IsExpanded}");
return Task.CompletedTask;
}

/// <summary>
/// 获得属性方法
/// </summary>
Expand Down Expand Up @@ -91,6 +112,14 @@ private AttributeItem[] GetAttributes() =>
Type = "bool",
ValueList = "true|false",
DefaultValue = "true"
},
new()
{
Name = "OnResizedAsync",
Description = Localizer["SplitsOnResizedAsync"],
Type = "Func<SplitterResizedEventArgs, Task>",
ValueList = "",
DefaultValue = ""
}
];
}
5 changes: 4 additions & 1 deletion src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,10 @@
"SplitsIsKeepOriginalSize": "Whether to keep the original size when restoring after collapsed",
"SplitsShowBarHandle": "Whether to display the drag bar",
"SplitsBarHandleShow": "Bar handle shown",
"SplitsBarHandleHide": "Bar handle hidden"
"SplitsBarHandleHide": "Bar handle hidden",
"SplitsOnResizedAsync": "Callback method when the panel size changes",
"SplitsCollapsibleTrue": "Collapse button shown",
"SplitsCollapsibleFalse": "Collapse button hidden"
},
"BootstrapBlazor.Server.Components.Samples.Dropdowns": {
"Title": "Dropdown",
Expand Down
5 changes: 4 additions & 1 deletion src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,10 @@
"SplitsIsKeepOriginalSize": "折叠后恢复时是否保持原始大小",
"SplitsShowBarHandle": "是否显示拖动条",
"SplitsBarHandleShow": "显示拖动栏",
"SplitsBarHandleHide": "隐藏拖动栏"
"SplitsBarHandleHide": "隐藏拖动栏",
"SplitsOnResizedAsync": "面板尺寸改变时回调方法",
"SplitsCollapsibleTrue": "显示调整按钮",
"SplitsCollapsibleFalse": "隐藏调整按钮"
},
"BootstrapBlazor.Server.Components.Samples.Dropdowns": {
"Title": "Dropdown 下拉菜单",
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>8.8.5-beta05</Version>
<Version>8.8.5-beta06</Version>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
Expand Down
69 changes: 49 additions & 20 deletions src/BootstrapBlazor/Components/Split/Split.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,6 @@ namespace BootstrapBlazor.Components;
/// </summary>
public sealed partial class Split
{
/// <summary>
/// 获得 组件样式
/// </summary>
private string? ClassString => CssBuilder.Default("split")
.AddClass("is-vertical", IsVertical)
.AddClassFromAttributes(AdditionalAttributes)
.Build();

/// <summary>
/// 获得 第一个窗格 Style
/// </summary>
private string? StyleString => CssBuilder.Default()
.AddClass($"flex-basis: {Basis.ConvertToPercentString()};")
.Build();

/// <summary>
/// 获取 是否开启折叠功能 默认 false
/// </summary>
Expand Down Expand Up @@ -70,25 +55,69 @@ public sealed partial class Split
/// 获得/设置 窗格折叠时回调方法 参数 bool 值为 true 是表示已折叠 值为 false 表示第二个已折叠
/// </summary>
[Parameter]
[Obsolete("已过期,请使用 Deprecated. Please use OnResizedAsync")]
[ExcludeFromCodeCoverage]
public Func<bool, Task>? OnCollapsedAsync { get; set; }

/// <summary>
/// 获得/设置 窗格尺寸改变时回调方法 可参阅 <see cref="SplitterResizedEventArgs"/>
/// </summary>
[Parameter]
public Func<SplitterResizedEventArgs, Task>? OnResizedAsync { get; set; }

/// <summary>
/// 获得 组件样式
/// </summary>
private string? ClassString => CssBuilder.Default("split")
.AddClass("is-vertical", IsVertical)
.AddClassFromAttributes(AdditionalAttributes)
.Build();

/// <summary>
/// 获得 第一个窗格 Style
/// </summary>
private string? StyleString => CssBuilder.Default()
.AddClass($"flex-basis: {Basis.ConvertToPercentString()};")
.Build();

private bool _lastCollapsible;

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(TriggerOnCollapsed), new { IsKeepOriginalSize });
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(TriggerOnResize), new { IsKeepOriginalSize });

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);

if (firstRender)
{
_lastCollapsible = IsCollapsible;
}
else if (_lastCollapsible != IsCollapsible)
{
_lastCollapsible = IsCollapsible;
await InvokeVoidAsync("update", Id);
}
}

/// <summary>
/// 窗格折叠时回调方法 由 JavaScript 调用
/// </summary>
/// <param name="collapsed"></param>
/// <returns></returns>
[JSInvokable]
public async Task TriggerOnCollapsed(bool collapsed)
public async Task TriggerOnResize(string left)
{
if (OnCollapsedAsync != null)
if (OnResizedAsync != null)
{
await OnCollapsedAsync(collapsed);
await OnResizedAsync(new SplitterResizedEventArgs(left));
}
}
}
76 changes: 48 additions & 28 deletions src/BootstrapBlazor/Components/Split/Split.razor.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ export function init(id, invoke, method, option) {
const splitRight = el.children[1];
const splitBar = el.children[2];

const split = { el, option }
split.splitLeft = splitLeft;
split.splitBar = splitBar;
const split = { el, invoke, method, option, splitLeft, splitBar };
Data.set(id, split)
Drag.drag(splitBar,
e => {
Expand Down Expand Up @@ -55,38 +53,53 @@ export function init(id, invoke, method, option) {
},
() => {
el.classList.remove('dragging');
console.log('end');
delete option.restoreLeftBasis;
removeMask(splitLeft, splitRight);
invoke.invokeMethodAsync(method, splitLeft.style.flexBasis);
}
);

let start = 0;
const step = ts => {
if (start === 0) {
start = ts;
}
if (ts - start > 300) {
splitLeft.classList.remove('is-collapsed');
split.initCollapseButton = () => {
let start = 0;
const step = ts => {
if (start === 0) {
start = ts;
}
if (ts - start > 300) {
splitLeft.classList.remove('is-collapsed');
}
requestAnimationFrame(step);
}
requestAnimationFrame(step);
}

[...splitBar.querySelectorAll('.split-bar-arrow')].forEach(element => {
EventHandler.on(element, 'mousedown', e => {
e.stopPropagation();
splitLeft.classList.add('is-collapsed');
const triggerLeft = element.classList.contains("split-bar-arrow-left");
invoke.invokeMethodAsync(method, triggerLeft);
setLeftBasis(split, triggerLeft);
start = 0;
requestAnimationFrame(step);
[...splitBar.querySelectorAll('.split-bar-arrow')].forEach(element => {
EventHandler.on(element, 'mousedown', e => {
e.stopPropagation();
splitLeft.classList.add('is-collapsed');
const triggerLeft = element.classList.contains("split-bar-arrow-left");
setLeftBasis(split, triggerLeft);
start = 0;
requestAnimationFrame(step);
});
});
});
};

split.initCollapseButton();
}

export function update(id) {
const split = Data.get(id)

if (split) {
const { splitBar, initCollapseButton } = split;
if (splitBar) {
disposeCollapseButton(splitBar);
initCollapseButton();
}
}
}

const setLeftBasis = (split, triggerLeft) => {
const { option, splitLeft } = split;
const { option, splitLeft, invoke, method } = split;
let leftBasis = splitLeft.style.flexBasis;
if (option.isKeepOriginalSize) {
if (option.restoreLeftBasis === void 0) {
Expand All @@ -112,6 +125,7 @@ const setLeftBasis = (split, triggerLeft) => {
}
}
splitLeft.style.setProperty('flex-basis', leftBasis);
invoke.invokeMethodAsync(method, leftBasis);
}

const showMask = (left, right) => {
Expand All @@ -136,15 +150,21 @@ const deleteMask = el => {
}
}

const disposeCollapseButton = splitBar => {
[...splitBar.querySelectorAll('.split-bar-arrow')].forEach(element => {
EventHandler.off(element, 'mousedown');
});
}

export function dispose(id) {
const split = Data.get(id)
Data.remove(id)

if (split) {
const { el } = split;
if (el.splitBar) {
EventHandler.off(splitBar, 'click', '.split-bar-arrow');
Drag.dispose(el.splitBar);
const { splitBar } = split;
if (splitBar) {
disposeCollapseButton(splitBar);
Drag.dispose(splitBar);
}
}
}
26 changes: 26 additions & 0 deletions src/BootstrapBlazor/Components/Split/SplitterResizedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Argo Zhang ([email protected]). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

namespace BootstrapBlazor.Components;

/// <summary>
/// SplitterResizedEventArgs 类
/// </summary>
public class SplitterResizedEventArgs(string left)
{
/// <summary>
/// Gets the size of panel 1 (top/left) after a resize operation.
/// </summary>
public string FirstPanelSize => left;

/// <summary>
/// 获得 组件第一个面板是否折叠
/// </summary>
public bool IsCollapsed => left == "0%";

/// <summary>
/// 获得 组件第一个面板是否展开
/// </summary>
public bool IsExpanded => left == "100%";
}
Loading

0 comments on commit 09d53ff

Please sign in to comment.