@* Recursive, read-only UNS browse-tree renderer. Modelled on DriverBrowseTree:
per-node indent, expand chevron and Bootstrap/theme styling. This component
owns no state and calls no service — it reads node.Expanded/Loading/Error/
Children and raises callbacks; the host page owns expansion + lazy loading. *@
@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns
@foreach (var root in Roots)
{
@RenderNode(root, 0)
}
@code {
/// The top-level UNS nodes to render (typically the enterprise roots).
[Parameter, EditorRequired] public IReadOnlyList Roots { get; set; } = default!;
/// Raised for the primary "add child" action of a node (e.g. "+ Area" on a cluster, "+ Tag" on equipment).
[Parameter] public EventCallback OnAddChild { get; set; }
/// Raised for the equipment-only "+ Virtual tag" action, kept distinct from OnAddChild ("+ Tag").
[Parameter] public EventCallback OnAddVirtualTag { get; set; }
/// Raised when the user edits a node (Area/Line/Equipment/Tag/VirtualTag).
[Parameter] public EventCallback OnEdit { get; set; }
/// Raised when the user deletes a node (Area/Line/Equipment/Tag/VirtualTag).
[Parameter] public EventCallback OnDelete { get; set; }
/// Raised when the user toggles a node's expansion; the host owns the resulting state + lazy load.
[Parameter] public EventCallback OnToggleExpand { get; set; }
/// Optional case-insensitive substring filter applied to visible children by DisplayName.
[Parameter] public string? Filter { get; set; }
private RenderFragment RenderNode(UnsNode node, int depth) => __builder =>
{
var indent = $"padding-left:{depth * 18}px";
var hasExpander = node.Children.Count > 0 || node.HasLazyChildren;