Skip to content

Commit

Permalink
feat(SortableList): add SortableList component (#4029)
Browse files Browse the repository at this point in the history
* feat: 增加 Sortable 工程

* feat: 增加 SoratableList 组件

* refactor: 移除接口

* doc: 增加 SortableList 菜单与代码映射配置

* refactor: 增加响应式样式

* doc: 代码格式化

* doc: 增加 SortableList 示例

* doc: 代码格式化

* feat: 增加 Clone 配置

* doc: 增加克隆节点示例

* feat: 增加 putback 参数支持

* doc: 增加排序参数示例

* refactor: 增加 Handler 属性

* doc: 增加有条件性拖拽示例

* refactor: 增加表格拖拽逻辑

* refactor: 更新脚本支持懒加载元素

* feat: 增加 OnUpdate 回调方法

* doc: 增加 OnUpdate 方法示例

* doc: 增加 OnRemove 回调方法示例

* feat: 增加 OnRemove 回调方法

* feat: 增加客户端拖动逻辑提高性能

* chore: bump version 8.0.0
  • Loading branch information
ArgoZhang authored Aug 12, 2024
1 parent 54a180c commit 0acee74
Show file tree
Hide file tree
Showing 22 changed files with 4,172 additions and 5 deletions.
7 changes: 7 additions & 0 deletions BootstrapBlazor.sln
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniTestSvgIcon", "test\UniT
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapBlazor.Core", "src\Extensions\Components\BootstrapBlazor.Core\BootstrapBlazor.Core.csproj", "{7ACF4C1A-C06F-4D2E-A86A-BE40C70E403D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.Sortable", "src\Extensions\Components\BootstrapBlazor.Sortable\BootstrapBlazor.Sortable.csproj", "{50F286FD-D814-46C3-A70C-C2F789C4338C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -364,6 +366,10 @@ Global
{7ACF4C1A-C06F-4D2E-A86A-BE40C70E403D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7ACF4C1A-C06F-4D2E-A86A-BE40C70E403D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7ACF4C1A-C06F-4D2E-A86A-BE40C70E403D}.Release|Any CPU.Build.0 = Release|Any CPU
{50F286FD-D814-46C3-A70C-C2F789C4338C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{50F286FD-D814-46C3-A70C-C2F789C4338C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50F286FD-D814-46C3-A70C-C2F789C4338C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50F286FD-D814-46C3-A70C-C2F789C4338C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -427,6 +433,7 @@ Global
{481653B0-B096-4F72-BA64-83F52E97E45B} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{01DA4687-0973-4CA6-97F5-04E0B8DD1B13} = {7C1D79F1-87BC-42C1-BD5A-CDE4044AC1BD}
{7ACF4C1A-C06F-4D2E-A86A-BE40C70E403D} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{50F286FD-D814-46C3-A70C-C2F789C4338C} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0DCB0756-34FA-4FD0-AE1D-D3F08B5B3A6B}
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<PackageReference Include="BootstrapBlazor.OnScreenKeyboard" Version="8.0.3" />
<PackageReference Include="BootstrapBlazor.PdfReader" Version="8.0.4" />
<PackageReference Include="BootstrapBlazor.SignaturePad" Version="8.0.2" />
<PackageReference Include="BootstrapBlazor.Sortable" Version="8.0.0" />
<PackageReference Include="BootstrapBlazor.Splitting" Version="8.0.0" />
<PackageReference Include="BootstrapBlazor.SvgEditor" Version="8.1.0" />
<PackageReference Include="BootstrapBlazor.SummerNote" Version="8.0.3" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@inherits WebSiteModuleComponentBase
@attribute [JSModuleAutoLoader("Components/VideoDemo.razor.js", AutoInvokeInit = false, AutoInvokeDispose = false)]

<video id="@Id" controls preload="auto" autoplay width="350" src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"></video>
<video id="@Id" controls preload="auto" autoplay muted src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"></video>
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,22 @@
<DemoBlock Title="@Localizer["IntersectionObserverVisibleTitle"]"
Introduction="@Localizer["IntersectionObserverVisibleIntro"]"
Name="Visible">
<section ignore><p>@((MarkupString)Localizer["IntersectionObserverVisibleDesc"].Value)</p></section>
<HeadContent>
<style>
.bb-video video {
width: 256px;
}

@@media (min-width: 767.99px) {
.bb-video video {
width: 350px;
}
}
</style>
</HeadContent>
<section ignore>
<p>@((MarkupString)Localizer["IntersectionObserverVisibleDesc"].Value)</p>
</section>
<p class="text-center @_textColorString">@_videoStateString</p>
<IntersectionObserver OnIntersecting="OnVisibleChanged" Threshold="1" AutoUnobserveWhenIntersection="false">
<div class="bb-video-demo scroll">
Expand Down
176 changes: 176 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/SortableLists.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
@page "/sortable-list"
@inject IStringLocalizer<SortableLists> Localizer
@inject IStringLocalizer<Foo> FooLocalizer

<h3>@Localizer["SortableListTitle"]</h3>

<h4>@Localizer["SortableListDescription"]</h4>

<PackageTips Name="BootstrapBlazor.SortableList" />

<DemoBlock Title="@Localizer["SortableListNormalTitle"]"
Introduction="@Localizer["SortableListNormalIntro"]"
Name="Normal">
<SortableList Option="_option1" OnUpdate="OnUpdate">
<div class="sl-list row g-2">
@foreach(var item in Items)
{
<div @key="item" class="col-12 col-sm-6"><div class="sl-item">@item.Name</div></div>
}
</div>
</SortableList>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListGroupTitle"]"
Introduction="@Localizer["SortableListGroupIntro"]"
Name="Group">
<div class="row g-2">
<div class="col-12 col-sm-6">
<SortableList Option="_option2" OnUpdate="OnUpdate1" OnRemove="OnRemove1">
<div class="sl-list">
@foreach (var item in Items1)
{
<div @key="item" class="sl-item">@item.Name</div>
}
</div>
</SortableList>
</div>
<div class="col-12 col-sm-6">
<SortableList Option="_option2" OnUpdate="OnUpdate2" OnRemove="OnRemove2">
<div class="sl-list">
@foreach (var item in Items2)
{
<div @key="item" class="sl-item">@item.Name</div>
}
</div>
</SortableList>
</div>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListCloneTitle"]"
Introduction="@Localizer["SortableListCloneIntro"]"
Name="Clone">
<div class="row g-2">
<div class="col-12 col-sm-6">
<SortableList Option="_option3">
<div class="sl-list">
<div class="sl-item">1</div>
<div class="sl-item">2</div>
<div class="sl-item">3</div>
<div class="sl-item">4</div>
</div>
</SortableList>
</div>
<div class="col-12 col-sm-6">
<SortableList Option="_option3">
<div class="sl-list">
<div class="sl-item">5</div>
<div class="sl-item">6</div>
<div class="sl-item">7</div>
<div class="sl-item">8</div>
</div>
</SortableList>
</div>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListDisableSortTitle"]"
Introduction="@Localizer["SortableListDisableSortIntro"]"
Name="Sort">
<div class="row g-2">
<div class="col-12 col-sm-6">
<SortableList Option="_option4">
<div class="sl-list">
<div class="sl-item">1</div>
<div class="sl-item">2</div>
<div class="sl-item">3</div>
<div class="sl-item">4</div>
</div>
</SortableList>
</div>
<div class="col-12 col-sm-6">
<SortableList Option="_option5">
<div class="sl-list">
<div class="sl-item">5</div>
<div class="sl-item">6</div>
<div class="sl-item">7</div>
<div class="sl-item">8</div>
</div>
</SortableList>
</div>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListHandlerTitle"]"
Introduction="@Localizer["SortableListHandlerIntro"]"
Name="Handler">
<div class="row g-2">
<div class="col-12 col-sm-6">
<SortableList Option="_option6">
<div class="sl-list">
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>1</span></div>
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>2</span></div>
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>3</span></div>
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>4</span></div>
</div>
</SortableList>
</div>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListFilterTitle"]"
Introduction="@Localizer["SortableListFilterIntro"]"
Name="Filter">
<div class="row g-2">
<div class="col-12 col-sm-6">
<SortableList Option="_option7">
<div class="sl-list">
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>1</span></div>
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>2</span></div>
<div class="sl-item filter"><i class="fa-solid fa-bars"></i><span>3</span></div>
<div class="sl-item"><i class="fa-solid fa-bars"></i><span>4</span></div>
</div>
</SortableList>
</div>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListNestTitle"]"
Introduction="@Localizer["SortableListNestIntro"]"
Name="Nest">
<div class="row g-2">
<div class="col-12 col-sm-6">
<SortableList Option="_option1">
<div class="sl-list">
<div class="sl-item">
<SortableList Option="_option1">
<div class="sl-list">
<div class="sl-item"><span>11</span></div>
<div class="sl-item"><span>12</span></div>
<div class="sl-item"><span>13</span></div>
</div>
</SortableList>
</div>
<div class="sl-item"><span>2</span></div>
<div class="sl-item"><span>3</span></div>
<div class="sl-item"><span>4</span></div>
</div>
</SortableList>
</div>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SortableListTableTitle"]"
Introduction="@Localizer["SortableListTableIntro"]"
Name="Table">
<SortableList Option="_optionTable">
<Table TItem="Foo" Items="@Items.Take(3)" IsStriped="true">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" />
<TableColumn @bind-Field="@context.Name" />
<TableColumn @bind-Field="@context.Address" />
</TableColumns>
</Table>
</SortableList>
</DemoBlock>
132 changes: 132 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/SortableLists.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
namespace BootstrapBlazor.Server.Components.Samples;

/// <summary>
/// SortableList 示例
/// </summary>
public partial class SortableLists
{
[NotNull]
private List<Foo>? Items { get; set; }

[NotNull]
private List<Foo>? Items1 { get; set; }

[NotNull]
private List<Foo>? Items2 { get; set; }

private readonly SortableOption _option1 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost"
};

private readonly SortableOption _option2 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost",
Group = "group"
};

private readonly SortableOption _option3 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost",
Group = "group-clone",
Clone = true
};

private readonly SortableOption _option4 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost",
Group = "group-clone",
Clone = true,
Putback = false
};

private readonly SortableOption _option5 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost",
Group = "group-clone",
Sort = false
};

private readonly SortableOption _option6 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost",
Handle = "i"
};

private readonly SortableOption _option7 = new()
{
RootSelector = ".sl-list",
GhostClass = "sl-item-ghost",
Filter = ".filter"
};

private readonly SortableOption _optionTable = new()
{
RootSelector = "tbody"
};

/// <summary>
/// OnInitialized
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();

//获取随机数据
//Get random data
Items = Foo.GenerateFoo(FooLocalizer, 8);
Items1 = Foo.GenerateFoo(FooLocalizer, 4);
Items2 = Foo.GenerateFoo(FooLocalizer, 8).Skip(4).ToList();
}

private Task OnUpdate(int oldIndex, int newIndex)
{
var item = Items[oldIndex];
Items.RemoveAt(oldIndex);
Items.Insert(newIndex, item);
StateHasChanged();
return Task.CompletedTask;
}

private Task OnUpdate1(int oldIndex, int newIndex)
{
var item = Items1[oldIndex];
Items1.RemoveAt(oldIndex);
Items1.Insert(newIndex, item);
StateHasChanged();
return Task.CompletedTask;
}

private Task OnUpdate2(int oldIndex, int newIndex)
{
var item = Items[oldIndex];
Items2.RemoveAt(oldIndex);
Items2.Insert(newIndex, item);
StateHasChanged();
return Task.CompletedTask;
}

private Task OnRemove1(int oldIndex, int newIndex)
{
var item = Items1[oldIndex];
Items1.RemoveAt(oldIndex);
Items2.Insert(newIndex, item);
StateHasChanged();
return Task.CompletedTask;
}

private Task OnRemove2(int oldIndex, int newIndex)
{
var item = Items[oldIndex];
Items2.RemoveAt(oldIndex);
Items1.Insert(newIndex, item);
StateHasChanged();
return Task.CompletedTask;
}
}
Loading

0 comments on commit 0acee74

Please sign in to comment.