Skip to content

feat(Sortable): bump version 10.0.2#929

Merged
ArgoZhang merged 4 commits intomasterfrom
dev-sortable
Feb 18, 2026
Merged

feat(Sortable): bump version 10.0.2#929
ArgoZhang merged 4 commits intomasterfrom
dev-sortable

Conversation

@ArgoZhang
Copy link
Member

@ArgoZhang ArgoZhang commented Feb 18, 2026

Link issues

fixes #928

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Update Sortable integration to the latest upstream version and improve documentation for the Sortable components and options.

Bug Fixes:

  • Align Sortable.js to upstream 1.15.7, including improved host element resolution and safer restoration of saved input states within the sortable root.

Enhancements:

  • Add bilingual (Chinese/English) XML documentation for SortableOption, SortableList, SortableEvent, and SortableListItem to clarify configuration and callback semantics.

Copilot AI review requested due to automatic review settings February 18, 2026 01:39
@bb-auto bb-auto bot added the enhancement New feature or request label Feb 18, 2026
@bb-auto bb-auto bot added this to the v9.2.0 milestone Feb 18, 2026
@sourcery-ai
Copy link

sourcery-ai bot commented Feb 18, 2026

Reviewer's Guide

Updates BootstrapBlazor.Sortable to Sortable.js 1.15.7 and enhances the C# sortable component API and docs with bilingual XML comments, while fixing a couple of subtle JS behaviors and keeping the public surface area unchanged.

Sequence diagram for SortableList initialization and JS-to-.NET update callback

sequenceDiagram
    actor User
    participant SortableList as SortableList_component
    participant BlazorJS as Blazor_JSInterop
    participant SortableJS as Sortable_js_1_15_7

    User ->> SortableList: Interact with page (component rendered)
    SortableList ->> BlazorJS: InvokeVoidAsync init(Id, Interop, Option, hasOnUpdate, hasOnRemove, hasOnAdd)
    BlazorJS ->> SortableJS: init sortable instance with options

    User ->> SortableJS: Drag and drop list items
    SortableJS ->> BlazorJS: notify update with item data
    BlazorJS ->> SortableList: JSInvokable TriggerUpdate(List<SortableListItem> items)
    SortableList ->> SortableList: Build SortableEvent from items
    alt OnUpdate callback is set
        SortableList ->> SortableList: await OnUpdate(SortableEvent)
    end
Loading

Updated class diagram for Sortable sortable component API

classDiagram
    class SortableOption {
        +string RootSelector
        +string Group
        +bool Clone
        +bool Putback
        +bool Sort
        +int Delay
        +bool DelayOnTouchOnly
        +int TouchStartThreshold
        +bool Disabled
        +int Animation
        +string Easing
        +string Handle
        +string Filter
        +bool PreventOnFilter
        +string Draggable
        +string DataIdAttr
        +string GhostClass
        +string ChosenClass
        +string DragClass
        +int SwapThreshold
        +bool InvertSwap
        +int InvertedSwapThreshold
        +string Direction
        +bool ForceFallback
        +string FallbackClass
        +bool FallbackOnBody
        +int FallbackTolerance
        +bool DragoverBubble
        +bool RemoveCloneOnHide
        +int EmptyInsertThreshold
        +bool MultiDrag
        +bool Swap
        +bool SwapClass
    }

    class SortableListItem {
        +string FromId
        +int OldIndex
        +int NewIndex
    }

    class SortableEvent {
        +string FromId
        +int OldIndex
        +int NewIndex
        +List~SortableListItem~ Items
    }

    class ISortableList {
    }

    class SortableList {
        +SortableOption Option
        +RenderFragment ChildContent
        +Func~SortableEvent,Task~ OnUpdate
        +Func~SortableEvent,Task~ OnRemove
        +Func~SortableEvent,Task~ OnAdd
        +Task TriggerUpdate(List~SortableListItem~ items)
        +Task TriggerRemove(List~SortableListItem~ items)
        +Task TriggerAdd(List~SortableListItem~ items)
    }

    SortableList ..|> ISortableList
    SortableList --> SortableOption
    SortableList --> SortableEvent
    SortableEvent --> "*" SortableListItem
Loading

File-Level Changes

Change Details Files
Upgrade embedded Sortable.js library from 1.15.6 to 1.15.7 with upstream helper refactors and bug fixes.
  • Update version constant from 1.15.6 to 1.15.7 in the ESM bundle.
  • Replace older Babel helper implementations with the newer ones generated by the upstream build.
  • Tighten getParentOrHost to avoid returning the host when it equals the element itself.
  • Ensure saved input checked state is only restored for inputs contained in the current sortable element during nulling.
src/components/BootstrapBlazor.Sortable/wwwroot/sortable.esm.js
Improve SortableOption API documentation with bilingual XML comments and minor doc clarifications.
  • Convert single-language XML comments to paired zh/en descriptions for each property.
  • Clarify behavior and defaults in several property descriptions (e.g., Clone, Putback, MultiDrag, Swap).
  • Keep property shapes and JSON serialization attributes unchanged.
src/components/BootstrapBlazor.Sortable/Components/SortableOption.cs
Enhance SortableList component documentation and clean up interop comments while preserving behavior.
  • Add bilingual XML comments (zh/en) to the component class and parameters.
  • Clarify JS interop methods as being invoked from JavaScript and describe their purpose.
  • Remove redundant tags from XML comments without changing method signatures or logic.
src/components/BootstrapBlazor.Sortable/Components/SortableList.razor.cs
Document SortableEvent and SortableListItem models with bilingual comments without altering their structure.
  • Add zh/en class-level and property-level XML comments for SortableEvent.
  • Clarify that SortableEvent.Items is a read-only collection initialized inline.
  • Add zh/en XML comments to SortableListItem properties without changing types or defaults.
src/components/BootstrapBlazor.Sortable/Components/SortableEvent.cs
src/components/BootstrapBlazor.Sortable/Components/SortableListItem.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#928 Update the embedded Sortable.js implementation used by the Sortable component to the newer upstream version required for release 10.0.2.
#928 Bump the BootstrapBlazor.Sortable package/component version metadata to 10.0.2 in the project configuration.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ArgoZhang ArgoZhang merged commit ae471b0 into master Feb 18, 2026
6 checks passed
@ArgoZhang ArgoZhang deleted the dev-sortable branch February 18, 2026 01:39
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In SortableOption, the XML doc for SwapClass describes it as a class name, but the property type is bool?; consider changing the type to string? (or adjusting the docs) so the API and documentation are consistent.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `SortableOption`, the XML doc for `SwapClass` describes it as a class name, but the property type is `bool?`; consider changing the type to `string?` (or adjusting the docs) so the API and documentation are consistent.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.Sortable/Components/SortableOption.cs:9-18` </location>
<code_context>

 namespace BootstrapBlazor.Components;

 /// <summary>
-/// SortableEvent 类
+/// <para lang="zh">SortableEvent 类</para>
</code_context>

<issue_to_address>
**issue:** The `SwapClass` property type does not match the description of holding a CSS class name.

The XML comment describes `SwapClass` as a CSS class for the swap dragging item, but the property type is `bool?`. If it should hold a CSS class (like `GhostClass`, `ChosenClass`, `DragClass`), consider changing the type to `string?`. If it is meant as a boolean flag, please update the documentation to match.
</issue_to_address>

### Comment 2
<location> `src/components/BootstrapBlazor.Sortable/Components/SortableEvent.cs:7-16` </location>
<code_context>

 namespace BootstrapBlazor.Components;

 /// <summary>
-/// SortableEvent 类
+/// <para lang="zh">SortableEvent 类</para>
+/// <para lang="en">SortableEvent class</para>
 /// </summary>
 public class SortableEvent
 {
     /// <summary>
-    /// 获得/设置 原始项所属容器 Id
+    /// <para lang="zh">获得/设置 原始项所属容器 Id</para>
+    /// <para lang="en">Gets or sets the container Id of the original item.</para>
     /// </summary>
     [NotNull]
     public string? FromId { get; set; }

     /// <summary>
-    /// 获得/设置 原始索引
+    /// <para lang="zh">获得/设置 原始索引</para>
+    /// <para lang="en">Gets or sets the original index.</para>
     /// </summary>
     [NotNull]
     public int OldIndex { get; set; }

     /// <summary>
-    /// 获得/设置 新索引
+    /// <para lang="zh">获得/设置 新索引</para>
+    /// <para lang="en">Gets or sets the new index.</para>
     /// </summary>
     [NotNull]
</code_context>

<issue_to_address>
**suggestion:** Using `[NotNull]` on value-type properties `OldIndex` and `NewIndex` is redundant and potentially misleading.

Since `OldIndex` and `NewIndex` are non-nullable `int`s, `[NotNull]` has no effect here and may imply they can be null. Please remove the attribute from these properties and keep it only on nullable reference-type members like `FromId`.

Suggested implementation:

```csharp
    /// <summary>
    /// <para lang="zh">获得/设置 原始索引</para>
    /// <para lang="en">Gets or sets the original index.</para>
    /// </summary>
    public int OldIndex { get; set; }

```

In the same file (`SortableEvent.cs`), also remove `[NotNull]` from any other non-nullable value-type properties such as `NewIndex`, keeping `[NotNull]` only on nullable reference-type members like `FromId`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 9 to 18
/// <summary>
/// SortableOption 配置类
/// <para lang="zh">SortableOption 配置类</para>
/// <para lang="en">SortableOption configuration class</para>
/// </summary>
public class SortableOption
{
/// <summary>
/// 获得/设置 目标元素选择器
/// <para lang="zh">获得/设置 目标元素选择器</para>
/// <para lang="en">Gets or sets the target element selector.</para>
/// </summary>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: The SwapClass property type does not match the description of holding a CSS class name.

The XML comment describes SwapClass as a CSS class for the swap dragging item, but the property type is bool?. If it should hold a CSS class (like GhostClass, ChosenClass, DragClass), consider changing the type to string?. If it is meant as a boolean flag, please update the documentation to match.

Comment on lines 7 to 16
/// <summary>
/// SortableEvent 类
/// <para lang="zh">SortableEvent 类</para>
/// <para lang="en">SortableEvent class</para>
/// </summary>
public class SortableEvent
{
/// <summary>
/// 获得/设置 原始项所属容器 Id
/// <para lang="zh">获得/设置 原始项所属容器 Id</para>
/// <para lang="en">Gets or sets the container Id of the original item.</para>
/// </summary>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Using [NotNull] on value-type properties OldIndex and NewIndex is redundant and potentially misleading.

Since OldIndex and NewIndex are non-nullable ints, [NotNull] has no effect here and may imply they can be null. Please remove the attribute from these properties and keep it only on nullable reference-type members like FromId.

Suggested implementation:

    /// <summary>
    /// <para lang="zh">获得/设置 原始索引</para>
    /// <para lang="en">Gets or sets the original index.</para>
    /// </summary>
    public int OldIndex { get; set; }

In the same file (SortableEvent.cs), also remove [NotNull] from any other non-nullable value-type properties such as NewIndex, keeping [NotNull] only on nullable reference-type members like FromId.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Bumps the BootstrapBlazor.Sortable NuGet package version and updates the embedded SortableJS asset, while also aligning public API XML docs with the repo’s bilingual documentation convention.

Changes:

  • Set BootstrapBlazor.Sortable package <Version> to 10.0.2.
  • Updated embedded SortableJS ESM bundle from 1.15.6 to 1.15.7 (including a couple upstream bug fixes).
  • Updated XML documentation in Sortable component public types to bilingual <para lang="zh/en"> format.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/components/BootstrapBlazor.Sortable/wwwroot/sortable.esm.js Vendor bundle updated to SortableJS 1.15.7 and includes upstream logic changes.
src/components/BootstrapBlazor.Sortable/Components/SortableOption.cs Bilingual docs added/updated for options; exposed a type/doc mismatch for SwapClass.
src/components/BootstrapBlazor.Sortable/Components/SortableListItem.cs Bilingual docs updated; nullability contract (FromId) needs alignment with actual payloads.
src/components/BootstrapBlazor.Sortable/Components/SortableList.razor.cs Bilingual docs updated; event construction still leaves FromId unset for Update/Remove.
src/components/BootstrapBlazor.Sortable/Components/SortableEvent.cs Bilingual docs updated; nullability annotations and [NotNull] usage need cleanup.
src/components/BootstrapBlazor.Sortable/BootstrapBlazor.Sortable.csproj Adds explicit package Version = 10.0.2.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/// <para lang="zh">获得/设置 原始项所属容器 Id</para>
/// <para lang="en">Gets or sets the container Id of the original item.</para>
/// </summary>
[NotNull]
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SortableEvent.FromId is declared string? but annotated [NotNull], and it is not assigned in TriggerUpdate / TriggerRemove, so it can be null at runtime. Either make this property truly required (non-nullable + set it consistently), or remove [NotNull] and document when it is populated (e.g., only for cross-list Add).

Suggested change
[NotNull]

Copilot uses AI. Check for mistakes.
Comment on lines 24 to 26
[NotNull]
public int OldIndex { get; set; }

Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NotNull] on value type properties has no effect (e.g., OldIndex is int and cannot be null). Remove the attribute to avoid implying nullable semantics.

Copilot uses AI. Check for mistakes.
Comment on lines 31 to 32
[NotNull]
public int NewIndex { get; set; }
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NotNull] on value type properties has no effect (e.g., NewIndex is int and cannot be null). Remove the attribute to avoid implying nullable semantics.

Copilot uses AI. Check for mistakes.
Comment on lines 69 to 74
var @event = new SortableEvent();
if (items.Count == 1)
{
@event.OldIndex = items[0].OldIndex;
@event.NewIndex = items[0].NewIndex;
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TriggerUpdate creates a SortableEvent but never sets FromId, even though the event type exposes it (and is currently annotated [NotNull]). If consumers rely on FromId to identify the source container, set it here (e.g., to Id) or adjust the event contract to indicate it may be null.

Copilot uses AI. Check for mistakes.
Comment on lines 90 to 95
var @event = new SortableEvent();
if (items.Count == 1)
{
@event.OldIndex = items[0].OldIndex;
@event.NewIndex = items[0].NewIndex;
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TriggerRemove creates a SortableEvent but never sets FromId, even though the event type exposes it (and is currently annotated [NotNull]). If consumers rely on FromId to identify the source container, set it here (e.g., to Id) or adjust the event contract to indicate it may be null.

Copilot uses AI. Check for mistakes.
/// <para lang="en">Gets or sets the class name for the swap dragging item. Default is null.</para>
/// </summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? SwapClass { get; set; }
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SortableOption.SwapClass is typed as bool?, but SortableJS swapClass is a CSS class name string (default 'sortable-swap-highlight'). With the current type, the option will serialize to a boolean and break swap highlighting. Change this property type to string? (and keep null to use the SortableJS default).

Suggested change
public bool? SwapClass { get; set; }
public string? SwapClass { get; set; }

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +24
/// <para lang="zh">获得/设置 分组配置</para>
/// <para lang="en">Gets or sets the group configuration.</para>
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML docs for Group say “group configuration”, but the API surface is string? Group and the JS interop turns it into { name: op.group } (i.e., this is effectively a group name). Consider updating the docs to avoid implying that callers can provide a full group config object.

Suggested change
/// <para lang="zh">获得/设置 分组配置</para>
/// <para lang="en">Gets or sets the group configuration.</para>
/// <para lang="zh">获得/设置 分组名称</para>
/// <para lang="en">Gets or sets the group name.</para>

Copilot uses AI. Check for mistakes.
Comment on lines +14 to 17
/// <para lang="zh">获得/设置 原始项所属容器 Id</para>
/// <para lang="en">Gets or sets the container Id of the original item.</para>
/// </summary>
[NotNull]
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SortableListItem.FromId is marked [NotNull] but JS only supplies FromId for the Add callback; for Update/Remove the deserialized items will have FromId == null. Either remove [NotNull] / adjust docs to reflect it is optional, or update the JS payloads to always include FromId.

Suggested change
/// <para lang="zh">获得/设置 原始项所属容器 Id</para>
/// <para lang="en">Gets or sets the container Id of the original item.</para>
/// </summary>
[NotNull]
/// <para lang="zh">获得/设置 原始项所属容器 Id(某些回调中可能为空)</para>
/// <para lang="en">Gets or sets the container Id of the original item (may be null for some callbacks).</para>
/// </summary>

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(Sortable): bump version 10.0.2

2 participants