|
| 1 | +using System.Text; |
| 2 | + |
1 | 3 | using Microsoft.AspNetCore.Components; |
2 | 4 | using Microsoft.AspNetCore.Components.Rendering; |
3 | 5 | using Microsoft.AspNetCore.Components.Routing; |
@@ -328,15 +330,68 @@ protected override void BuildRenderTree(RenderTreeBuilder builder) |
328 | 330 | return; |
329 | 331 | } |
330 | 332 |
|
331 | | - var cssBuilder = new CssBuilder() |
332 | | - .MergeClass(AdditionalAttributes) |
333 | | - .AddClass(CssClass) |
334 | | - .AddClass(DisabledClass); |
| 333 | + // render a span with the same attributes if no permission |
| 334 | + var (attributes, classString) = ResolveClass(AdditionalAttributes, CssClass, DisabledClass); |
335 | 335 |
|
336 | 336 | builder.OpenElement(0, "span"); |
337 | | - builder.AddMultipleAttributes(1, AdditionalAttributes); |
338 | | - builder.AddAttribute(2, "class", cssBuilder); |
| 337 | + builder.AddMultipleAttributes(1, attributes); |
| 338 | + builder.AddAttribute(2, "class", classString); |
| 339 | + |
339 | 340 | builder.AddContent(3, ChildContent); |
340 | 341 | builder.CloseElement(); |
341 | 342 | } |
| 343 | + |
| 344 | + private static (IEnumerable<KeyValuePair<string, object>>? attributes, string? classString) ResolveClass( |
| 345 | + IReadOnlyDictionary<string, object>? additionalAttributes, |
| 346 | + params IEnumerable<string?> classNames) |
| 347 | + { |
| 348 | + if (additionalAttributes == null && classNames == null) |
| 349 | + return (null, null); |
| 350 | + |
| 351 | + var classes = new HashSet<string>(StringComparer.Ordinal); |
| 352 | + |
| 353 | + static void AddClasses(HashSet<string> classes, string? classValue) |
| 354 | + { |
| 355 | + if (string.IsNullOrWhiteSpace(classValue)) |
| 356 | + return; |
| 357 | + |
| 358 | + foreach (var value in classValue.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) |
| 359 | + { |
| 360 | + if (!string.IsNullOrWhiteSpace(value)) |
| 361 | + classes.Add(value); |
| 362 | + } |
| 363 | + } |
| 364 | + |
| 365 | + IEnumerable<KeyValuePair<string, object>>? attributes = null; |
| 366 | + |
| 367 | + // Add classes from additionalAttributes if present |
| 368 | + if (additionalAttributes != null) |
| 369 | + { |
| 370 | + if (additionalAttributes.TryGetValue("class", out var className) |
| 371 | + && className is string classString) |
| 372 | + { |
| 373 | + AddClasses(classes, classString); |
| 374 | + } |
| 375 | + |
| 376 | + // Exclude the "class" attribute from the additional attributes to avoid duplication |
| 377 | + var filteredAttributes = additionalAttributes |
| 378 | + .Where(attribute => !string.Equals(attribute.Key, "class", StringComparison.OrdinalIgnoreCase)) |
| 379 | + .ToArray(); |
| 380 | + |
| 381 | + // Only set attributes if there are any after filtering |
| 382 | + if (filteredAttributes.Length > 0) |
| 383 | + attributes = filteredAttributes; |
| 384 | + } |
| 385 | + |
| 386 | + // Add classes from the provided classNames parameters |
| 387 | + foreach (var className in classNames) |
| 388 | + AddClasses(classes, className); |
| 389 | + |
| 390 | + // Combine all classes into a single string |
| 391 | + var classStringResult = classes.Count > 0 |
| 392 | + ? string.Join(' ', classes) |
| 393 | + : null; |
| 394 | + |
| 395 | + return (attributes, classStringResult); |
| 396 | + } |
342 | 397 | } |
0 commit comments